# 进阶知识点

# 1.响应式原理

Vue 内部使用了Object.defineProperty()来实现数据响应式,通过这个函数可以监听到setget的事件

# 2.Object.defineProperty 的缺陷

如果通过下标方式修改数组数据或者给对象新增属性并不会触发组件的重新渲染,因为Object.defineProperty不能拦截到这些操作,更精确的来说,对于数组而言,大部分操作都是拦截不到的,只是 Vue 内部通过重写函数的方式解决了这个问题。

# 3.编译过程

Vue 会通过编译器将模板通过几个阶段最终编译为render函数,然后通过执行render函数生成 Virtual DOM 最终映射为真实 DOM

编译阶段大致分为三个阶段:

  • 将模板解析为 AST
  • 优化 AST
  • 将 AST 转换为reder函数

# 4.NextTick 原理分析

nextTick可以让我们在下次 DOM 更新循环结束之后执行延迟回调,用于获得更新后的 DOM。

在 Vue 2.4 之前都是使用的 microtasks,但是 microtasks 的优先级过高,在某些情况下可能会出现比事件冒泡更快的情况,但如果都使用 macrotasks 又可能出现渲染性能问题。所以在新版中,会默认使用 microtasks,但在特殊情况下会使用 macrotasks,比如 v-on。

对于实现 macrotasks 会先判断是否能用setImmediate,不能的话降级为MessageChannel,以上都不行的话就使用setTimeout

if (typeof setImmediate !== "undefined" && isNative(setImmediate)) {
  macroTimerFunc = () => {
    setImmediate(flushCallbacks)
  }
}else if(
  typeof MessageChannel !== 'undefined' &&
  (isNative(MessageChannel) ||
  MwssageChannel.toString() === '[object MessageChannelConstructor]')
){
  const channel = new MessageChannel()
  const port = channel.port2
  channel.port1.onmessage = flushCallbacks
  macroTimerFunc = () =>{
    port.postMessage(1)
  }else {
    macroTimerFunc=()=>{
      setTimeout(flushCallbacks,0)
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
上次更新: 2022/6/29 上午12:09:44