生命周期介绍

beforeCreate 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问
created 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。这里没有$el,如果非要想与 Dom 进行交互,可以通过 vm.$nextTick 来访问 Dom
beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted 在挂载完成后发生,在当前阶段,真实的 Dom 挂载完毕,数据完成双向绑定,可以访问到 Dom 节点
beforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁(patch)之前。可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程
updated 发生在更新完成之后,当前阶段组件 Dom 已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新,该钩子在服务器端渲染期间不被调用。
beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用。我们可以在这时进行善后收尾工作,比如清除计时器。
destroyed Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
activated keep-alive 专属,组件被激活时调用
deactivated keep-alive 专属,组件被销毁时调用

父子组件的渲染顺序?

father beforeCreate
father created
father beforeMount
child beforeCreate
child created
child beforeMount
child mounted
father mounted

为什么列表中 index 不能作为key?

链接
因为key值会影响 Vue 中 diff 算法对于性能优化的判断,举例来说,Vue 会根据 key 值来判断是否需要重新渲染,对于需要增删列表项或者需要重新排序的场景的话,用 index 作为 key 值会让 diff 算法无法对新 vnode 和 旧 vnode 做比较。会造成严重的性能损耗。而且有时遇到删除列表中的项就会发生Bug,列表中含有子组件,子组件的值不依赖props时。这时候删除任何一个项目,在页面上显示的都是删掉了最后一个。

  1. // vue 源码
  2. function sameVnode (a, b) {
  3. return (
  4. a.key === b.key && (
  5. (
  6. a.tag === b.tag &&
  7. a.isComment === b.isComment &&
  8. isDef(a.data) === isDef(b.data) &&
  9. sameInputType(a, b)
  10. ) || (
  11. isTrue(a.isAsyncPlaceholder) &&
  12. a.asyncFactory === b.asyncFactory &&
  13. isUndef(b.asyncFactory.error)
  14. )
  15. )
  16. )
  17. }

Vue 通讯机制?

  • props/$emit 适用父子组件通信
  • ref与parent/children适用父子组件通信 :::info 要注意边界情况,如在#app上拿parent得到的是new Vue()的实例,在这实例上再拿 parent得到的是undefined,而在最底层的子组件拿$children是个空数组。也要注意得到$parent和$children的值不一样,$children 的值是数组,而$parent是个对象 :::

  • EventBus(事件总线) 适用于父子、隔代、兄弟组件通信

  • attrs/listeners 适用于隔代组件通信
  • provide/inject 适用于隔代组件通信
    父组件提供使用 provide 提供一个全局变量 子组件通过 inject 来注入
    官网很明确的说了provide 和 inject 绑定并不是可响应的。但是,如果你传入了一个可监听的对象,那么这个对象的属性还是可响应的。
  • vuex 适用于父子、隔代、兄弟组件通信
    localStorge 和 sessionStorage
  • slot插槽方式
  • Vue 3 新增的方式

    • exposeref``defineExpose

      watchEffectwatch 的区别是什么?

  • vue2中的 watch 监听的是对象,监听的属性必须要在对象上声明。vue3 的 watchEffect 则是监听的一个函数,函数中有任何响应式对象都能被监听到。

  • watch 是惰性的,只有被监听的值变化了,才会执行watch中的函数。watchEffect 在声明的时候就会执行,会收集一遍需要跟踪的依赖值。

组件中 data 为什么是一个函数?

因为函数中有作用域的限制,每一个Vue 实例的data函数 return出来的对象都是独立的。不会因为组件的复用而受到影响。

keep-alive的介绍

  • keep-alive 可以缓存组件的状态,避免重新渲染。
  • 一般跟路由和动态组件一起配合使用。比如切换Tab页 可以保留切换前后的组件状态。
  • 提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
  • 提供两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。

compositon API 和 options API 的 优劣

options API 按照API的功能分类。能够相对便捷的在对应的功能下找到关联数据。
compositon API 的优势在于能够更好的组织代码和对逻辑的复用。
在中小型应用时,compositon 优势并不明显。但在大型应用中,compositon API 能够更好的组织代码实现业务逻辑的封装和复用。

Mixin 的缺点

  1. 多个 mixin 混合时,可能会找不到 对应的 data 值来自哪一个 mixin

image.png

  1. 会造成命名空间冲突

Ref 和 Reactive 的区别

  • Ref 适用于处理值类型的响应式。 Reactive 适用于对象的响应式
  • Reactive 内部用了 proxy 的代理去监听属性上的变更。Ref对于值类型的使用 getter 和 setter 来处理响应式。如果ref 传入的参数是对象,那么就会包装成 reactive 来实现引用类型的深层响应。