@@ -93,7 +93,7 @@ function update() {
93
93
94
94
然后我们定义一些新术语:
95
95
96
- - ` update() ` : 产生副作用的函数,简称副作用函数,它会修改了 sum 的状态
96
+ - ` update() ` : 产生副作用的函数,简称副作用函数,它会修改 sum 的状态
97
97
- ` a ` 和 ` b ` : 副作用函数的依赖
98
98
99
99
同时,假设还存在一个魔术方法 ` whenDepsChange ` ,当依赖 a 和 b 发生变化时,重新执行 update 方法
@@ -126,8 +126,6 @@ a = 10 // 修改 a 的值, 我们期待会重新执行 update 方法,并且 su
126
126
127
127
当然,接下来我们来了解下如何实现响应式数据。
128
128
129
- ---
130
- layout: default
131
129
---
132
130
133
131
## 如何实现响应式数据
@@ -188,8 +186,13 @@ obj.text = 'Hello Vue3!' // 赋值操作
188
186
```
189
187
190
188
<arrow v-click =" [1, 2] " x1 =" 330 " y1 =" 170 " x2 =" 630 " y2 =" 280 " color =" #564 " width =" 3 " arrowSize =" 1 " />
191
- <img v-click =" [1, 2] " alt =" 桶占位 " />
192
- <img v-click =" [2, 3] " alt =" 桶占位 " />
189
+ <arrow v-click =" [2, 3] " x1 =" 230 " y1 =" 230 " x2 =" 630 " y2 =" 280 " color =" #564 " width =" 3 " arrowSize =" 1 " />
190
+ <img
191
+ v-click="[ 1,3] "
192
+ src="public/bucket.excalidraw.png"
193
+ alt="桶占位"
194
+ style="margin-left: 600px; height: 300px"
195
+ />
193
196
194
197
---
195
198
---
@@ -407,13 +410,14 @@ WeakMap<target, Map<key, Set<effectFn>>>
407
410
```
408
411
409
412
<img
410
- src="public/1 .excalidraw.png"
413
+ src="public/data-structure .excalidraw.png"
411
414
alt="the-structure-of-reactivity-data-and-effect-fn"
412
415
/>
413
416
414
417
---
415
418
416
419
最后,再将代码封装一下:
420
+
417
421
``` js
418
422
const obj = reactive (data)
419
423
@@ -436,7 +440,7 @@ function track(target, prop) {/* ... */}
436
440
function trigger (target , prop ) {/* ... */ }
437
441
```
438
442
439
- ` demo: 04-design-a-full-reactivity-system.html `
443
+ demo: ` 04-design-a-full-reactivity-system.html `
440
444
441
445
---
442
446
---
@@ -564,7 +568,8 @@ function effect(fn) {
564
568
activeEffect = effectStack[effectStack .length - 1 ]
565
569
}
566
570
```
567
- demo: 06-nested-effect.html
571
+
572
+ demo: ` 06-nested-effect.html `
568
573
569
574
---
570
575
@@ -629,7 +634,7 @@ function effect(fn, options = {}) {
629
634
}
630
635
```
631
636
632
- ``` js {2-9}
637
+ ``` js
633
638
function trigger (target , prop ) {
634
639
effects .forEach (effectFn => {
635
640
if (effectFn .options .schedular ) {
@@ -663,7 +668,8 @@ console.log('结束了')
663
668
' 结束了'
664
669
2
665
670
```
666
- demo: 07-schedular.html
671
+
672
+ ` demo: 07-schedular.html `
667
673
668
674
---
669
675
@@ -753,7 +759,7 @@ function computed(getter) {
753
759
754
760
测试一下代码:
755
761
756
- demo: 08-computed.html
762
+ demo: ` 08-computed.html `
757
763
758
764
``` js
759
765
const data = { a: 1 , b: 2 }
@@ -833,7 +839,8 @@ computed(obj)
833
839
└── effectFn
834
840
`
835
841
```
836
- demo: 09-computed-2.html
842
+
843
+ demo: ` 09-computed-2.html `
837
844
838
845
---
839
846
@@ -872,7 +879,7 @@ obj.a = 100 // 修改
872
879
873
880
<div grid =" ~ cols-2 gap-4 " >
874
881
875
- 第二版: (demo: 11-watch-2.html)
882
+ 第二版: (demo: ` 11-watch-2.html ` )
876
883
877
884
``` js
878
885
function watch (source , cb ) {
@@ -979,7 +986,7 @@ const obj = reactive(wrapper) // 使用 reactive 将其转为响应式数据
979
986
```
980
987
再封装成 ref 函数:
981
988
``` js
982
- // demo: 14. ref.html
989
+ // demo: 14- ref.html
983
990
function ref (val ) {
984
991
const wrapper = {
985
992
value: val
@@ -1118,7 +1125,7 @@ function toRefs(obj) {
1118
1125
测试一下:
1119
1126
1120
1127
``` js
1121
- // demo: 15. ref-2.html
1128
+ // demo: 15- ref-2.html
1122
1129
const newObj = { ... toRefs (obj) }
1123
1130
effect (() => {
1124
1131
console .log (newObj .foo .value )
@@ -1247,7 +1254,7 @@ const ast = {
1247
1254
{
1248
1255
type: ' Interpolation' ,
1249
1256
content: {
1250
- type: ' Expression ' ,
1257
+ type: ' SimpleExpression ' ,
1251
1258
content: String ,
1252
1259
},
1253
1260
}
@@ -1583,6 +1590,7 @@ function createTransformContext(
1583
1590
```
1584
1591
1585
1592
``` js
1593
+ // 插拔式的插件预设
1586
1594
{
1587
1595
nodeTransforms: [
1588
1596
transformElement,
@@ -1727,6 +1735,55 @@ function processExpression(node) {
1727
1735
1728
1736
## codegen 代码生成
1729
1737
1738
+ 上文实现了 ` transform ` ,接下来进入 ` compile ` 最后的 ` codegen ` 阶段。
1739
+
1740
+ ### 一些准备工作
1741
+
1742
+ ` codegen ` 阶段会根据 ` AST ` 生成 ` render ` 函数的代码字符串,而渲染函数的执行会生成虚拟 DOM。
1743
+
1744
+ 假设模板如下:
1745
+
1746
+ ``` js
1747
+ < div> {{ msg }}< / div>
1748
+ ```
1749
+ 经过 codegen 代码生成后,会生成如下代码:
1750
+ ``` js
1751
+ `
1752
+ function render(_ctx) {
1753
+ return h('div', null, _toDisplayString(_ctx.msg))
1754
+ }
1755
+ `
1756
+ ```
1757
+
1758
+ ---
1759
+
1760
+ 我们看到,代码字符串中有 ` h ` 函数,` h ` 函数实际上就是对 ` createVNode ` 的封装,它们都是用于创建 ` VNode ` 的。
1761
+
1762
+ ``` js
1763
+ // 源码位置: packages/runtime-core/src/h.ts
1764
+ function h (tag , props , children ) {
1765
+ // 我们这里就简单的返回一个对象,实际源码中会复杂很多
1766
+ return {
1767
+ tag,
1768
+ props,
1769
+ children,
1770
+ }
1771
+ }
1772
+ ```
1773
+
1774
+ ` _toDisplayString ` 函数是 ` toDisplayString ` 的别名,它用于将插值表达式转换为字符串:
1775
+
1776
+ ``` js
1777
+ const toDisplayString = (val ) => {
1778
+ return String (val)
1779
+ }
1780
+ ```
1781
+
1782
+ ---
1783
+
1784
+ ### 代码实现
1785
+
1786
+
1730
1787
` codegen ` 主入口函数:
1731
1788
1732
1789
``` js
0 commit comments