阅读 491

7x2 精读Vue官方文档 - 组件对象选项

精读 Vue 官方文档系列 🎉


创建组件时的配置项,属于 optionsAPI 范畴。

组件选项 - 数据

data

值必须是一个函数

为了防止跨组件共享数据,组件的 data 选项必须是一个函数。 data 函数返回的数据对象,会被 Vue 递归处理,最终转换为带有 getter/setter 的响应式对象。

访问 Vue 实例的数据对象

可以通过 vm.$data.property 的方式访问,也可以使用 vm.property 的方式访问响应式对象,因为 Vue 实例已经代理了对 $data 的访问。

私有的数据对象

_$ 开头的 property 不会被 Vue 实例代理,因为它们可能和 Vue 内置的 property、API 方法冲突。你可以使用例如 vm.$data._property 的方式访问这些 property。

data: (vm) => {
    return {
      _msg:'111'
    };
},
mounted(){
    console.log(this.$data._msg)
}
复制代码

关于 data 函数内的 this

data 函数里面通过 this 来访问当前组件的实例,但是如果 data 是一个箭头函数,那么只能通过接受参数的形式来访问当前的组件实例。

{
 props: {
    myProp: String,
  },
  data: (vm) => {
    return {
      msg: vm.myProps,
    };
  }
}
复制代码

究其本质是因为箭头函数的 this 永远指向的是上一个作用域的上下文对象。而 data 的初始化是在独立的 initData -> getData 函数中进行,它们的上下文对象,非严格模式下是 window 对象,严格模式下则为 undefined

在 Vue 源码 initState 中会首先初始化 propsmthods,所以 data 选项函数中就可以事先拿到这些值,来帮助初始化响应式数据。

props

值可以是一个对象或数组,数组可以声明多种类型,对象则允许更高级的配置:

  • 类型检查:type 的值除了原生的构造函数,也可以通过 as 类型断言结合 TypeScript 类型声明一起使用。
  • 默认值:default,为该 prop 指定一个默认值。
  • 是否必传:required,值是一个 Boolean 类型。
  • 校验值:validator,值是一个 Function,返回值是一个布尔类型,用于表明校验的状态。

propsData

只用于 new 创建的实例中,可以实时传入 props,方便测试。

var Comp = Vue.extend({
  props: ['msg'],
  template: '<div>{{ msg }}</div>'
})

var vm = new Comp({
  propsData: {
    msg: 'hello'
  }
})
复制代码

computed

  • 计算属性是通过混入的方式加入到 Vue 实例中,可以通过 vm 组件实例来直接访问。所有的 getter/setter 函数的 this 上下都将自动绑定为 Vue 实例。
  • 计算属性的结果会被缓存,只有依赖的响应式对象发生更改时,才会重新计算。
  • 计算属性如果没有使用到,则不会执行,因此具有懒执行的特性。
  • 计算属性方法如果是一个箭头函数,则也会遇到 data 选项函数同样的问题,此时可以通过参数的方式来访问当前组件实例。
computed: {
  aDouble: vm => vm.a * 2
}
复制代码

methods

methods 中的方法是以混入的方式加入到 Vue 实例中的,所以我们可以通过的 vm 组件实例来直接访问这些方法。并且方法内部的 this 也是自动绑定为当前的组件实例。

不应该使用箭头函数来定义 method 方法,因为它的上下文永远是父级的上下文对象。

watch

值是一个对象,对象的 key 是要监听的表达式,value 则是对应的回调函数

{
    a:function(){},
    'b.c':function(){}
}
复制代码

value 也可以是一个方法名,Vue 会自动调用 vm.$methods 中同名的方法。

{
   d:'doSomeThing'
}
复制代码

否则是一个对象选项,可以实现更丰富的监听设置。

e:{
    handler: function(){},
    deep:true,
    immediate:true
}
复制代码

不应该使用箭头函数来定义 watch 的方法,因为它的上下文永远是父级的上下文对象。

组件选项 - DOM

el

只在用 new 创建实例时生效。 提供一个在页面上已存在的 DOM 元素作为值,可灵活的将组件挂载到指定的 DOM 位置。 在实例挂载之后,元素可以用 vm.$el 访问。

注意,如果组件选项不存在 template 也不存在 render 选项,那么 el 指定 DOM 元素的 innerHTML 内容将会被取出来作为模板使用。此种方式只能用于完整版(Runtime + Compiler)的 Vue 中。

template

字符串模板。如果值是以 # 开始,则会作为选择符,将匹配到的 X-Template 元素的 innerHTML 值作为模板。

出于安全考虑,你应该只使用你信任的 Vue 模板。避免使用其他人生成的内容作为你的模板。 如果 Vue 选项中包含渲染函数,该模板将被忽略。

render

渲染函数,接收一个 createElement 参数,可使用 JavaScript 编程能力来创建 Vnode,其优先级高于 template 字符串模板方式。

如果组件是一个函数组件,渲染函数还会接收一个额外的 context 参数,为没有实例的函数组件提供上下文信息。

renderError

只用于开发环境。 当 render 函数遭遇错误时,提供另外一种渲染输出。其错误将会作为第二个参数传递到 renderError。这个功能配合 hot-reload 非常实用。

new Vue({
  render (h) {
    throw new Error('oops')
  },
  renderError (h, err) {
    return h('pre', { style: { color: 'red' }}, err.stack)
  }
}).$mount('#app')
复制代码

组件选项 - 生命周期钩子

beforeCreate

此时响应式数据、事件方法、watch 都还没有被初始化,所以无法使用。

created

此时响应式数据、事件方法、watch 都可以使用,但是组件还没有渲染与挂载,所以 $el property 还不可用。

beforeMount

挂载之前调用,相关的 render 函数被首次调用,此时 Vnode 开始创建。

mounted

实例被挂载后调用,此时 $el 可以被访问。

注意 mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick:

mounted: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been rendered
  })
}
复制代码

beforeUpdate

数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

updated

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。

注意 updated 不会保证所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick:

actived

被 keep-alive 缓存的组件激活时调用。

deactived

被 keep-alive 缓存的组件停用时调用。

beforeDestroy

实例销毁之前调用。在这一步,实例仍然完全可用。 通常我们会在这里清除定时器、解除全局的事件监听。

destroyed

Vue 实例销毁后调用。 对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。

errorCaptured

当捕获到一个来自子孙组件的错误时被调用。 其传播链路是 子级的 errorCaptured -> 父级的 errorCaptured -> 全局的 errorHandler。 如果方法内部返回一个 false 则可以中断自身继续向上传播的链路。

你可以在此钩子中修改组件的状态,专门实现错误时的提示。

组件选项 - 组合

parent

手动指定当前组件实例的父实例,建立父子关系(子实例被推入父实例的 $children 数组中)。

export default Vue.extend({
  name: "HelloWorld",
  mounted() {
    new (Vue.extend({
      name: "Comp",
      parent: this,
      mounted() {
        console.log(this.$parent);
      },
      render(c) {
        return c("h1", ["h1"]);
      },
    }))().$mount("#box");
  },
});
复制代码

子实例可以通过 this.$parent 获取父实例,

mixins

mixins 选项接收一个混入对象的数组。这些混入对象可以像正常的组件对象一样包含实例选项,这些选项将会被合并到最终的选项中。

extends

扩展另一个组件选项对象,它与 mixins 非常类似。与 mixins 的最大区别就在于前者可以接收一个混入对象的数组,而后者只能是一个组件选项对象。

provide/inject

这对组件选项必须要一起使用。以允许一个祖先组件向其所有后代组件注入一个依赖,不论组件的层级有多深。

Vue 的 provide/inject 本身并不是响应式的,但是支持传输本身就是响应式对象的依赖。

组件选项 - 其它

name

  1. 为组件定义名称。
  2. 组件模板更好的递归调用自身。
  3. 结合 vue-devtools 工具可以更方便的调试。

model

值是一个 { prop?: string, event?: string } 的对象,用于自定义组件的 v-model

inHeritAttrs

如果父组件通过 v-bind 指令传入的 prop 没有在子组件中通过 props 选项进行预先声明,那么就会被作为普通的 HTML Attribute 绑定到子组件的根元素上。

通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。

注意:这个选项不影响 class 和 style 绑定。

文章分类
前端
文章标签