vue基础问题

import HelloWorld from '@/components/HelloWorld'中的@是什么意思

默认从src下面的目录开始查找模块

resolve:{
  alias: {
    '@': resolve(" src ")
  }
}

因为在webpack.base.config中做了resolve.alias配置,为src目录下的文件创建了别名“@”,以便import或者require指定的module时更容易,所以"@"的意思是从src下面的目录开始查找模块。


Vue.use()作用

Vue.use(plugin)用于引入一个插件。
参数为一个对象或者函数,是对象的时候必须要有install方法。
首先会判断插件是否已经注册,

  • 如果已经注册,则直接返回。
  • 如果没有注册,则:
    (1)toArray()用于把类数组argument转化为数组,然后通过unshift()将数组右移,在数组首部添加this对象,也就是Vue对象。
    (2) 如果传入的是对象,那就调用插件的install方法并通过apply()方法将install方法改变this的指向为plugin。
    args作为参数传递给install方法。
    (3)插件类型为function时,插件运行的上下文this指向null(严格模式下;非严格模式下指向window)
    (4)installedPlugins.push(plugin)在这之后将插件push到插件数组中,表示已注册。
    源码如下:
  Vue.use = function (plugin) {
    /* istanbul ignore if */
    if (plugin.installed) {
      return
    }
    // additional parameters
    var args = toArray(arguments, 1);
    args.unshift(this);
    if (typeof plugin.install === 'function') {
      plugin.install.apply(plugin, args);
    } else if (typeof plugin === 'function') {
      plugin.apply(null, args);
    }
    plugin.installed = true;
    return this
  };

  function toArray (list, start) {
    start = start || 0;
    var i = list.length - start;
    var ret = new Array(i);
    while (i--) {
      ret[i] = list[i + start];
    }
    return ret
  };

Vue.set(target, propertyName/index, value) 或者 this.$set(target, propertyName/index, value)

参数:
{Object | Array} target
{string | number} propertyName/index
{any} value
this.$set是Vue.set()的一个别名
向响应式数据中添加一个属性,并且保证该属性也是响应式的,且触发视图的更新。它必须用于向响应式对象上添加新属性,因为 Vue 无法探测普通的新增属性。

为什么要用Vue.set()或者this.$set();

受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。
要处理这种情况,我们可以使用$set()方法,既可以新增属性,又可以触发视图更新。


computed, watch, methods的区别

  • computed是在HTML DOM加载完成之后就执行
    methods需要一定的触发条件,比如点击事件
    watch用于观察数据,默认的执行顺序是先执行computed,再watch,不执行methods;当触发点击事件时,则先调用methods,再watch
  • computed是计算属性,对于计算结果会缓存。除非依赖的响应式属性变化才会重新计算。注意,如果某个依赖 (比如非响应式属性) 在该实例范畴之外,则计算属性是不会被更新的。这就意味着只要依赖的属性还没有发生改变,多次访问计算属性会立即返回之前的计算结果,而不必再次执行函数。
  • watch只能观察一个响应式属性。(包括通过vue.set()添加的响应式属性)当需要在数据变化时执行异步操作或者开销比较大的操作时,可以用watch。

修饰符


v-prev,v-cloak, v-once

v-prev: 跳过元素和他的子元素的编译过程,可以用来显示原始mustache标签。跳过大量没有指令的节点会加快编译。
v-cloak: 保持在元素上直到关联实例编译结束。比如和display: none结合使用。可以隐藏未编译的mustache标签直到编译结束。
v-once: 只渲染元素和组件一次。随后的重新渲染,将会作为静态内容跳过。可以用来优化性能。


[https://www.jianshu.com/p/db2ab955c351]


vue-router导航守卫

  • 全局导航守卫:
    beforeEach(to,from,next);
    beforeResolve();
    afterEach(to,from)
  • 路由守卫:
    beforeEnter(to,from,next);
  • 组件导航守卫:
    beforeRouteEnter(to,from,next);此时组件实例还没有被创建,不能获取this;beforeRouteEnter 是支持给 next 传递回调的唯一守卫。
    beforeRouteUpdate(to,from,next);
    beforeRouteLeave(to,from,next);

完整的导航解析流程

  • 导航被触发。
  • 在失活的组件里调用离开守卫。
  • 调用全局的 beforeEach 守卫。
  • 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  • 在路由配置里调用 beforeEnter。
  • 解析异步路由组件。
  • 在被激活的组件里调用 beforeRouteEnter。
  • 调用全局的 beforeResolve 守卫 (2.5+)。
  • 导航被确认。
  • 调用全局的 afterEach 钩子。
  • 触发 DOM 更新。
  • 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

路由懒加载

当打包构建应用时,javascript包会变得很大,影响页面的加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
结合vue的异步组件和webpack代码分割可以实现

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

function loadView(view) {
  return () => import(/* webpackChunkName: "view-[request]" */ `@/views/${view}.vue`)
}

export default new Router({
  routes: [
    {
      path: '/home',
      name: 'home',
      component: loadView('Home')
    },
    {
      path: '/about',
      name: 'about',
      component: loadView('About')
    }
  ]
})

或者使用webpack特有的require.ensure()

const Baz = r => require.ensure([], ()=>r(require('./Baz.vue')), '/baz')

推荐阅读更多精彩内容