Vue 中如何检测数组变化?
由于 Object.defineProperty 无法监听数组的变化。
所以,在 Vue2.X 版本中,作者用了一种 hack 的方式,即:重写了数组原型的方法。
虽然重写,但基本和原来的方法一样,只是多了 通知视图更新(因为改变了数组)
数组里如果也有 Object 类型,那么继续深度遍历
【注】Vue3.0 采用 proxy 监听
为何 Vue 采用异步渲染?
如果不采用异步更新,每次更新数据都会对当前组件进行重新渲染。为了性能考虑,Vue 会在本轮数据更新后,再去异步更新视图。
当某个数据改变时,会通知 与该数据绑定的所有 watcher,会依次调用 watcher 的 update(),并不会立即执行,会先存放进一个队列中(该队列中相同的 watcher 会被过滤),最后异步更新
详细举例:
Dep 是在 数据劫持时,新建的实例。(即每个数据都会建立)
Watcher 是与 html 文档中的数据 有关,因为 发布订阅者模式本身就是为了让 nodeType==3,即 被 mustache 语法包裹起来的数据 能都被更新到。所以,Watcher 会在遍历 html 文档时新建。
nextTick 实现原理?
nextTick(cb),该方法主要使用了 宏任务和微任务,定义了一个异步方法,多次调用 nextTick 会将方法存入队列中,通过这个异步方法清空当前队列。
- 会先将 cb 保存在数组中
- 然后调用 timerFunc(),该方法会根据浏览器兼容问题让数组中的 cb 采用 4 种方式去回调 cb
- Promise (微任务,比宏任务快被执行,优先采用)
- MutationObserve
- setImmediate (比 setTimeout 快)
- setTimeout
Computed,Watch,Methods 的区别?
computed 和 methods 的区别:
- computed 是具备缓存的,只有当绑定的属性发生变化时,才变化
- methods 没有缓存,所以同样调用 3 次,computed 有缓存只会调用 1 次,而 methods 会调用 3 次
- watch 和 computed 原理都是 watcher,只是 computed 具备缓存
【computed 原理】:
computed 在 new Watcher()时候,会有一个 lazy 的属性,他是作为一个标识属性,表示这是一个计算属性,真正发生变化的是 dirty 属性。
lazy 的标识,就是让 计算属性在源码中是非异步更新的。
在计算属性里用了 某个 data 里的数据,会调用 该数据所对应的 get() 方法,该方法又会将 watcher 放入 Dep 数组中,当 该数据被修改时,调用 update,然后修改 dirty 为 true,表示被数据修改过,如果数据被修改,那么 计算属性的下一次调用 就会发生改变。
Watch 默认会先执行。
Vue 生命周期
4 个前后生命周期,总计 8 个生命周期函数,下面是比较用到的
- created :实例已经创建,所以这里可以进行一些数据,资源的请求
- mounted :实例已经挂载完成,可以进行 DOM 操作
- beforeUpdate :可以在这个钩子中进一步更改状态,这不会触发附加的重渲染过程
- updated :更新完成之后,此方法中最好不要执行 DOM 的操作,因为可能会导致更新无限循环
- beforeDestroy : 可以执行一些优化操作,清空定时器,解除绑定事件
何时要使用 beforeDestroy?
页面中使用了$on,那需要在组件销毁前用$off 解绑
清除自定义的定时器
解除事件绑定 scroll mousemove 等