Skip to content

Commit 3adfef2

Browse files
张东张东
authored andcommitted
add
1 parent f49201f commit 3adfef2

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

frame/vue/apis.md

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,13 @@ layout: doc
2828
通过配置这些traps可以进一步实现shallowreactive,readonly等api
2929

3030
## computed
31-
使用computed注册的响应式数据使用方法与ref差不多,都要使用.value,实际上computed会返回一个对象,里面有个访问器属性value
31+
使用computed会返回一个对象,它也有一个访问器属性value,初始化时会执行一遍里面的回调函数,搜集依赖。
3232

33-
初始化会自动执行一遍里面的回调函数,收集依赖,并且还有两个属性dirty和value,dirty初始化是true,代表需要重新执行回调,value则是执行完回调return的值
33+
并且还有两个属性dirty和value,dirty初始化设置为true,代表需要重新执行回调,value则是回调return的值。
3434

35-
当computed依赖的响应式数据发生改变,dirty被设置为true,当触发getter时需要重新执行回调,将return的值缓存到value,并把新值返回
36-
37-
如果依赖没有改变,也就是dirty为false,就会直接返回缓存的value
35+
当computed依赖的响应式数据发生变化,dirty被设置为true,当触发getter时会重新执行回调,并更新value,将新值返回。
3836

37+
如果依赖没有改变,触发getter不会重新执行回调,而是返回缓存的value。
3938
## nextTick
4039
::: tip :rocket:
4140
我们通过js修改dom时 dom树在内存中是同步发生更新的,但是此时的最新状态并不会立即反应到屏幕上 而是要等待浏览器的渲染周期和帧率有关 一般在16.6ms 当渲染完成后 才能在屏幕观测到最新的页面
@@ -47,20 +46,15 @@ layout: doc
4746

4847
nexttick的原理就是通过promise的链式调用,将nexttick里的回调放在上面的微任务.then里执行
4948
## watch
50-
首先会把watch的第一个参数标准化,也就是getter函数的形式。然后使用ReactiveEffect类创建一个effect对象,并将watch里的回调函数设置为effect的调度器函数,
51-
52-
当监听的响应式数据发生变化,会执行effect里的调度器。并且执行过程中会调用effect.run,会返回getter函数return的值,也就获取了新值。旧值是通过闭包拿到
53-
54-
把新值和旧值作为watch回调的参数
55-
56-
通过源码可以发现,watch监听ref reactive数据类型是不同的,当是reactive类型,默认会调用traverse进行深度监听,对于ref类型,不会进行深度监听,通过设置deep:true能实现深度监听
49+
基于vue响应式系统,首先会将watch的第一个参数标准化,也就是getter函数的形式,将其创建为一个响应式副作用,配合调度器控制watch回调的执行。
5750

58-
对于immediate,默认是false,不会执行effect的调度器函数
51+
当响应式数据发生改变,触发trigger派发更新,由于调度器的存在,会再次执行watch里的回调,也会执行上面的getter函数拿到新值,旧值通过闭包拿到,最后将新旧值做为回调的参数。
5952

60-
对于flush,这跟组件的更新时机有关系,默认是pre,也就是在父组件更新之后,子组件更新之前执行,post是在组件更新之后,sync则是同步执行
53+
通过源码可以发现,watch监听ref reactive数据类型是不同的,当是reactive类型,默认会调用traverse进行深度监听,对于ref类型,不会进行深度监听,通过设置deep:true能实现深度监听。
6154

62-
watchEffect都是基于doWatch方法,不同点是回调为null,配置也只有flush
55+
对于flush,这跟组件的更新时机有关系,默认是pre,也就是在父组件更新之后,子组件更新之前执行,post是在组件更新之后,sync则是同步执行。
6356

57+
watchEffect则是vue提供的创建响应式副作用的api。
6458
## keepalive
6559
卸载时并不会真的卸载,而是移动到一个隐藏容器里,挂载时也不是真的挂载,而是从隐藏容器中取出放在页面上
6660

frame/vue/reactivity.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,22 @@ activeEffect 还原为之前的值
154154
33
155155
34 obj.foo++
156156
35 obj.foo++
157-
```
157+
```
158+
## 响应式原理
159+
Vue的响应式系统在运行时跟踪属性的访问,它通过结合proxy包装器和getter/setter函数来实现。
160+
161+
proxy第一个参数是被代理对象,第二个参数是一组traps,通过这些traps可以控制被代理对象的基本操作。
162+
163+
对于reactive来说,有get、set、deleteProperty、has、ownKeys这些traps,在get中触发track依赖收集。
164+
165+
在track内部我们会检查当前是否有正在运行的副作用。如果有,我们会查找到一个存储了所有追踪了该属性的订阅者的Set,然后将当前这个副作用作为新订阅者添加到该Set中。
166+
167+
副作用订阅将被存储在一个全局的WeakMap<target, Map<key, Set<effect>>>数据结构中。如果在第一次追踪时没有找到对相应属性订阅的副作用集合,它将会在这里新建。
168+
169+
在set中处理新增和修改属性,会触发trigger派发更新。
170+
171+
在trigger内部,我们会再查找到该属性的所有订阅副作用。但这一次我们需要执行它们。
172+
173+
最常见的响应式副作用就是更新dom。每个组件实例创建一个响应式副作用来渲染和更新dom。
174+
175+
而对于ref,返回一个对象,里面有一个响应式属性value,执行getter时,进行track,执行setter时触发trigger,对于setter的参数value则会使用reactive处理。

0 commit comments

Comments
 (0)