vue进阶总结2

62 阅读6分钟

Vue3 ref 和 reactive 区别,如何选择?

个人认为 ref 和 reactive 其实 没必要这个都抛出来给我们用,容易造成一些使用困扰,ref我觉就好,不过存在即合理,还是细说一下区别

区别

ref()reactive()
✅支持基本数据类型+引用数据类型❌只支持对象和数组(引用数据类型)
❌在 ✅在
✅重新分配一个新对象不会失去响应❌重新分配一个新对象会丢失响应性
需要使用 .value 访问属性能直接访问属性
✅传入函数时,不会失去响应❌将对象传入函数时,失去响应
✅解构对象时会丢失响应性,需使用toRefs❌解构时会丢失响应性,需使用toRefs

Vue 模板编译的原理

响应式是 Vue中很重要的一环,但是模板编译也是很重要的一环,从面试的角度来说,Vue的模板编译主要是这几个步骤:

  • 解析:解析器将模板解析为抽象语树 AST,只有将模板解析成 AST 后,才能基于它做优化或者生成代码字符串
    • 使用正则等方式解析模板字符串,生成 AST 抽象语法树
    • 遍历 AST,生成渲染函数
  • 优化:优化抽象语法树
    • 检测子节点中是否是纯静态节点
    • 对数据访问点进行转换,生成 getter/setter,实现响应式
    • 使用缓存存放已经编译好的渲染函数,避免重复编译
  • 生成:将渲染函数打包生成新函数,返回函数的字符串形式
    • 依赖响应式系统触发更新,执行渲染函数重新渲染
    • 通过 diff 算法对比新旧节点,最小化更新实际 DOM

Vue、React、Angular 模板编译方式优缺点

框架模板语法编译方式学习曲线
Vue.js简单 HTML-like运行时和构建时编译
易于理解
ReactJSX (JavaScript XML)编译为 JavaScript中等
嵌入 JavaScript 中
Angular复杂,基于 HTML预编译 (Ahead of Time)较高
双向数据绑定

Vue diff 算法的过程

Vue2

关于Vue2 的 diff 算法个人的理解上是:

  • 深度优先+双指针(头尾交叉对比)的 diff
    • 在对比其子节点数组时,vue对每个子节点数组使用了两个指针,分别指向头尾,然后不断向中间靠拢来进行对比,
    • 这样做的目的是尽量复用真实dom,尽量少的销毁和创建真实dom
    • 之后的节点对比就是深度优先对比的步骤
    • 逐层比较新旧虚拟 DOM 树的节点,对于每一层,它会按照顺序比较节点,找出差异,并标记需要更新的地方。这样的遍历方式有助于更快地发现差异,因为它会首先比较同一层级的节点,然后再递归到下一层级。
    • 通过虚拟节点的key和tag来进行判断是否相同节点
    • 如果相同则将旧节点关联的真实dom的挂到新节点上,然后根据需要更新属性到真实dom,然后再对比其子节点数组
    • 如果不相同,则按照新节点的信息递归创建所有真实dom,同时挂到对应虚拟节点上,然后移除掉旧的dom
    • 深度优先(同层比较):
    • 双指针:

这样一直递归的遍历下去,直到整棵树完成对比。

流程图

### Vu3

  • 双指针+最长递增子序列 diff算法
    • 把没有比较过的新的vnode节点,建立一个数组,每个子元素都是 0 里面的数字记录老节点的索引 ,数组索引就是新节点的索引
    • 如果找到与当前老节点对应的新节点那么 ,将新节点的索引,赋值给newIndex
    • 没有找到与老节点对应的新节点,卸载当前老节点
    • 如果找到与老节点对应的新节点,把老节点的索引,记录在存放新节点的数组中
    • map = [0,0,0,0]
    • 对于老的节点大于新的节点的情况 , 对于超出的节点全部卸载 ( 这种情况说明已经patch完相同的vnode )
    • 如果新的节点大于老的节点数 ,对于剩下的节点全部以新的vnode处理( 这种情况说明已经patch完相同的vnode )。
    • 如果第一步没有patch完,立即,从后往前开始patch ,如果发现不同立即跳出循环
    • 从头对比找到有相同的节点 patch ,发现不同,立即跳出
    • 预处理前前置节点
    • 预处理后置节点
    • 处理仅有新增节点的情况
    • 处理仅有删除节点的情况
    • 处理新增、删除、移动混合的情况
    1. 如果节点发生移动 记录已经移动了
    2. patch新老节点 找到新的节点进行patch节点

Vue 常见的性能优化方式(结合项目场景)

在实际项目中,Vue 的性能优化需要根据具体的场景和需求来选择合适的策略。以下是一些常见的 Vue 性能优化方式,结合项目场景进行总结:

  1. 使用生产环境构建:
    • 在生产环境中使用 Vue 的生产版本,以减少体积和提高性能。
  1. 异步组件和路由懒加载:
    • 对于大型项目,使用异步组件和路由懒加载,以分割代码并实现按需加载,减小初始加载体积。
  1. 合理使用 v-if 和 v-show:
    • 对于频繁切换的元素,使用 v-show,对于不经常切换的元素,使用 v-if,以减少 DOM 元素的挂载和卸载。
  1. 合理使用 v-for:
    • 遍历大数据集时,避免在模板中访问复杂度较高的属性,最好在数据源中进行预处理。如果数据不变,可以考虑使用 Object.freeze 冻结对象,以防止 Vue 的响应式系统监听它。
  1. 合理使用计算属性和 Watch:
    • 将复杂的计算逻辑放入计算属性,避免在模板中进行复杂的计算。使用 deep 选项和 immediate 选项来优化 Watcher。
  1. 合理使用事件委托:
    • 在父组件上使用事件委托,将事件处理推移到父组件上,以减少子组件的监听器数量。
  1. 合理使用 keep-alive:
    • 对于频繁切换的组件,可以考虑使用 缓存组件实例,以减少组件的销毁和重新创建。
  1. 合理使用缓存
    • 利用缓存机制,例如在数据请求结果中使用缓存,以避免不必要的重复请求。
  1. 合理使用过渡效果和动画:
    • 控制过渡效果和动画的触发时机,避免在大量元素上使用过渡效果,以提高性能。
  1. 优化网络请求 - 使用合适的数据加载方式,例如分页加载或滚动加载,以降低页面初始化时的请求量。
  2. 性能监控和分析 - 使用工具进行性能监控和分析,例如 Chrome DevTools、Vue DevTools 等,及时发现和解决性能问题
  3. 使用 Object.freeze() 进行不需要进行响应式的数据进行优化(vue2)