Vue知识点梳理

372 阅读3分钟

Vue基础

v-if 和 v-show

v-if 控制dom节点是否存在、更高的切换消耗、惰性的(初始条件为假什么也不做)、有局部编译和卸载的过程
v-show 控制css:display、更高的初始消耗
切换频繁用v-show,条件改变很少时用v-if

v-for key作用

必须用key,且不能是index和random,diff算法中通过tag和key来判断是否是相同节点,用key可以使diff算法减少渲染次数提升渲染性能。

组件通讯

  • 父子组件:props 和 this.$emit
  • 非父子组件:自定义事件 event.emit触发, event.on绑定/event.$off销毁
  • vuex

组件生命周期

  • 挂载阶段

    • beforeCreate:$el和data未初始化
    • created:$el未初始化 data初始化
    • beforeMount:$el和data初始化,未挂载
    • mounted:已挂载
  • 更新阶段

    • beforeUpdate
    • updated
  • 销毁阶段

  • beforeDestroy

  • destroyed

父子组件生命周期顺序

  • 挂载阶段:父created - 子created - 子mounted - 父mounted
  • 更新阶段:父beforeUpdate - 子beforeUpdate - 子updated - 父updated

组件如何抽离公共逻辑——mixin

mixin缺点:

  • 变量来源不明确,不利于阅读
  • 多 mixin 可能会引起命名冲突
  • mixin 和组件可能会出现多对多的关系 造成混乱

动态注册全局组件

核心:通过 require.context() 方法获取文件夹下所有vue文件路径

Vue组件更新后如何获取最新DOM

vue是异步渲染,data 修改后不会立刻修改dom,而是会整合多次修改结果,更新一次dom。

路由原理

  • hash路由:window.onhashchange事件
  • history路由:history.pushState事件、window.onpopstate事件(前进/后退)

history路由需要服务端支持(无论url是什么,都返回index.html这个主文件)

 data为什么是函数?

定义vue组件是一个Class类,如果data不是函数,实例化出来的每一个vue实例的data都是一样的,相互影响。data是函数,实例化的时候函数会形成一个闭包,不同实例之间的data数据不会相互影响。

ajax请求放在哪个生命周期?

mounted. 等页面渲染挂载完成,再请求数据,渲染数据。由于js是单线程的,ajax异步获取数据,放在mounted之前没有用(即便你先拿到数据,页面没渲染完成,数据也是在异步队列中),只会让逻辑更加混乱。

注意:如果父组件请求接口拿到的数据,需要传给子组件,这个请求需要放到created。因为父子组件的生命周期执行顺序是:父created-子craeted-子mounted-父mounted。

vue常见性能优化方式 

  • 合理使用 v-show 和 v-if
  • 合理使用 computed
  • v-for 加 key,避免和 v-if 同时使用
  • 自定义事件、DOM事件及时销毁(内存泄漏)
  • 合理使用异步组件(大的第三方组件)
  • 合理使用 keep-alive
  • data层级不要太深(响应式监听一次会监听到最底层)

用 vnode 描述一个 DOM 结构

<div class="container">
    <p>vdom</p>
</div>

{
    tag: 'div',
    props: {
        className: 'container'
    },
    children: [
        {
            tag: 'p',
            children: 'vdom'
        }
    ]
}

何时需要使用 beforeDestroy

  • 解绑自定义事件 event.$off

  • 清除定时器

  • 解绑自定义的 DOM 事件,如 window.onscroll 等

Vue原理

Vue工作机制

MVVM

MVVM模型:model-view-viewmodel
核心是viewmodel,充当两个方向的桥梁。

  1. model->view 数据绑定(Directives)
  2. view->model Dom事件监听(Dom Listeners)

响应式原理

Vue2

利用 Object.defineProperty,对 data 里的每一个属性的 get 和 set 都重新定义(数据劫持),从而可以监听属性的变化。在 get 的时候通过依赖收集器收集依赖(Watcher),在 set 的时候通知相应的依赖去更新。

缺点:

  • 深度监听,需要递归到底,一次性计算量大
  • 无法监听新增属性、删除属性(Vue.set Vue.delete解决)
  • 无法原生监听数组变化,需特殊处理

Vue3

利用 Proxy 做数据劫持。

优点:

  • data属性访问到哪一层就响应式监听到哪一层
  • 可以监听对象、数组的变化

缺点:兼容性差,无法 polyfill

Object.defineProperty不能监听数组变化,为什么Vue2可以?

Vue改写了data里的数组属性的原型链,使其等于Vue自定义的数组类的原型,在访问数组属性的方法时,实际上调用的是Vue自定义的数组方法,并且在这里会执行一次视图更新方法,从而监听数组变化。

v-model双向绑定原理

模型到视图:input框的value属性设置为data里的某个属性

视图到模型:利用input框的@input事件,在输入框发生变化时,触发input事件,把data里绑定给input框的属性的值设置为当前输入框的event.target.value。由于data是响应式的,所以依赖data属性的地方都会自动更新。

模板编译

概述

通过模板编译实现依赖收集,让视图和模型产生联系,在模型发生变化时,根据依赖关系更新视图。

将template模板内容编译成 Js 代码,先编译成 render 函数,再编译成 vnode。

组件渲染/更新过程

  1. 解析模板,生成 render 函数,执行 render 函数,触发 data 里的 getter,并进行依赖收集。(模板里用到了哪个变量,用一个wather观察起来)
  2. 修改 data 里的某个属性值,触发其 setter 方法,通知相应的 watcher 更新,重新调用 render 函数

初次渲染过程

  1. 解析模板为 render 函数
  2. 触发响应式,监听 data 属性的 getter、setter
  3. 执行 render 函数,生产 vnode ,打补丁调用 patch(ele, vnode),生成 dom

更新过程

  1. 修改 data ,触发 setter (此前在 getter 中已监听)
  2. 通知 watcher 更新,重新调用 render 函数,生成 newVnode
  3. 打补丁,调用 patch(vnode, newVnode),生成最终的 dom

异步渲染

  • $nextTick 在 dom 渲染之后触发回调
  • 汇总 data 的修改,一次性更新视图
  • 减少 DOM 操作次数,提高性能