暗号:笔记

生命周期

Vue 实例从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期,我觉得应该关注的是:

  1. 单组件的生命周期
  2. 父子组件的生命周期
  3. 兄弟组件的生命周期

1. 生命周期钩子函数

下面这张图是vue生命周期各个阶段的执行情况:

Vue阶段总结 - 图1

生命周期钩子 组件状态 最佳实践
beforeCreate 实例初始化之后,this指向创建的实例,不能访问到data、computed、watch、methods上的方法和数据 常用于初始化非响应式变量
created 实例创建完成,可访问data、computed、watch、methods上的方法和数据,未挂载到DOM,不能访问到$el属性,$ref属性内容为空数组 常用于简单的ajax请求,页面的初始化
beforeMount 在挂载开始之前被调用,beforeMount之前,会找到对应的template,并编译成render函数 -
mounted 实例挂载到DOM上,此时可以通过DOM API获取到DOM节点,$ref属性可以访问 常用于获取VNode信息和操作,ajax请求
beforeupdate 响应式数据更新时调用,发生在虚拟DOM打补丁之前 适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器
updated 虚拟 DOM 重新渲染和打补丁之后调用,组件DOM已经更新,可执行依赖于DOM的操作 避免在这个钩子函数中操作数据,可能陷入死循环
beforeDestroy 实例销毁之前调用。这一步,实例仍然完全可用,this仍能获取到实例 常用于销毁定时器、解绑全局事件、销毁插件对象等操作
destroyed 实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁 -

注意:

  1. created阶段的ajax请求与mounted请求的区别:前者页面视图未出现,如果请求信息过多,页面会长时间处于白屏状态
  2. mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick
  3. vue2.0之后主动调用$destroy()不会移除dom节点,作者不推荐直接destroy这种做法,如果实在需要这样用可以在这个生命周期钩子中手动移除dom节点

2. 单个组件的生命周期

  1. 初始化组件时,仅执行了beforeCreate/Created/beforeMount/mounted四个钩子函数
  2. 当改变data中定义的变量(响应式变量)时,会执行beforeUpdate/updated钩子函数
  3. 当切换组件(当前组件未缓存)时,会执行beforeDestory/destroyed钩子函数
  4. 初始化和销毁时的生命钩子函数均只会执行一次,beforeUpdate/updated可多次执行

3. 父子组件的生命周期

  1. 仅当子组件完成挂载后,父组件才会挂载
  2. 当子组件完成挂载后,父组件会主动执行一次beforeUpdate/updated钩子函数(仅首次)
  3. 父子组件在data变化中是分别监控的,但是在更新props中的数据是关联的(可实践)
  4. 销毁父组件时,先将子组件销毁后才会销毁父组件

data与props尝试解释

data

data 是Vue实例的数据对象。Vue将会将data 的属性转换为 getter/setter, 也就是用Object.defineProperty方法对数据进行监听。可是在可复用性组件中,data必须是一个函数,因为只有函数,返回对象的复制,这样组件间才不会相互影响。

props

Props 被称之为静态数据,在各自实例中,一旦在初始化被定义好类型时,基于 Vue 是单向数据流,在数据传递时始终不能改变它的数据类型。更为关键地是,props的数据都是通过父组件或者更高层级的组件数据或者字面量的方式进行传递的,不允许直接操作改变各自实例中的props数据,而是需要通过别的手段,改变传递源中的数据。

子组件中data和props的区别

子组件中的data数据,不是通过父组件传递的是子组件私有的,是可读可写的。

子组件中的所有 props中的数据,都是通过父组件传递给子组件的,是只读的。

computed与watch

computed

computed是计算属性,类似于过滤器,对绑定到视图的数据进行处理,并监听变化进而执行对应的方法。计算属性是基于它们的依赖进行缓存的,只在相关依赖发生改变时它们才会重新求值。

watch

watch是一个侦听的动作,用来观察和响应 Vue 实例上的数据变动。使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

computed和watch用法异同

相同: computed和watch都起到监听/依赖一个数据,并进行处理的作用

异同:它们其实都是vue对监听器的实现,只不过computed主要用于对同步数据的处理,watch则主要用于观测某个值的变化去完成一段开销较大的复杂业务逻辑。能用computed的时候优先用computed,避免了多个数据影响其中某个数据时多次调用watch的尴尬情况。

指令与自定义指令

什么是指令?

一个指令的本质是模板中出现的特殊标记,让处理模板的库知道需要对这里的 DOM 元素进行一些对应的处理。 —— vue官方文档

在Vue中,指令基本上类似于添加到模板中的HTML属性。它们都是以v-开头,表示这是一个Vue特殊属性。Vue中的指令主要分为内嵌的指令和自定义指令。另外有一些指令还带有相应的修饰符。如果你需要对HTML进行底层操作的话,指令是非常有用的。

常用的内嵌指令

  • v-if
  • v-show
  • v-else
  • v-for
  • v-bind
  • v-model
  • v-on
  • v-text

自定义指令

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

同时在指令钩子函数中,会被传入以下参数:

  • el:指令所绑定的元素,可以用来直接操作 DOM 。
  • binding:一个对象
  • vnode:Vue 编译生成的虚拟节点。
  • oldVnode:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用。

vue自定义指令的使用场景

  1. 一键 Copy的功能
  1. // 注册一个全局自定义指令 `v-focus`
  2. Vue.directive('focus', {
  3. // 当被绑定的元素插入到 DOM 中时……
  4. inserted: function (el) {
  5. // 聚焦元素
  6. el.focus()
  7. }
  8. })
  1. 2.按钮级别权限控制
  2. 3.自动获取焦点