[{"data":1,"prerenderedAt":4605},["ShallowReactive",2],{"\u002Fwriting\u002Fvue-reactivity":3},{"id":4,"title":5,"body":6,"date":4594,"description":12,"extension":4595,"intro":4596,"meta":4597,"navigation":110,"path":4598,"seo":4599,"stem":4600,"tags":4601,"__hash__":4604},"writing\u002Fwriting\u002Fvue-reactivity.md","Dive into Vue：依赖追踪",{"type":7,"value":8,"toc":4585},"minimark",[9,13,130,134,137,148,342,345,348,351,370,377,384,387,477,592,595,602,1018,1021,1166,1178,1181,1184,1262,1272,1278,1305,1313,1332,1335,1356,1399,1416,1666,1678,1914,1917,1923,1933,2865,2887,2896,2902,3046,3055,3059,3062,3093,3121,3127,3324,3327,3333,3336,3442,3458,3464,3623,3626,4581],[10,11,12],"p",{},"在 Vue 中，响应式系统自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 DOM。假如一个副作用函数中读取了某个对象的属性，当这个属性变化时，副作用函数重新执行，那么我们就称这个对象是响应式对象。",[14,15,20],"pre",{"className":16,"code":17,"language":18,"meta":19,"style":19},"language-js shiki shiki-themes houston","const obj = { count: 0 }\nfunction effect() {\n  el.innerText = obj.count\n}\neffect()\n\nobj.count = 3 \u002F\u002F 自动执行 effect()，将 el.innerText 更新为 3\n","js","",[21,22,23,54,67,90,96,105,112],"code",{"__ignoreMap":19},[24,25,28,32,36,40,44,47,51],"span",{"class":26,"line":27},"line",1,[24,29,31],{"class":30},"sqF6k","const",[24,33,35],{"class":34},"s8HWQ"," obj",[24,37,39],{"class":38},"sLo_3"," = { ",[24,41,43],{"class":42},"sb16X","count",[24,45,46],{"class":38},": ",[24,48,50],{"class":49},"se2J0","0",[24,52,53],{"class":38}," }\n",[24,55,57,60,64],{"class":26,"line":56},2,[24,58,59],{"class":30},"function",[24,61,63],{"class":62},"stHQG"," effect",[24,65,66],{"class":38},"() {\n",[24,68,70,73,76,79,82,85,87],{"class":26,"line":69},3,[24,71,72],{"class":42},"  el",[24,74,75],{"class":38},".",[24,77,78],{"class":42},"innerText",[24,80,81],{"class":38}," = ",[24,83,84],{"class":42},"obj",[24,86,75],{"class":38},[24,88,89],{"class":42},"count\n",[24,91,93],{"class":26,"line":92},4,[24,94,95],{"class":38},"}\n",[24,97,99,102],{"class":26,"line":98},5,[24,100,101],{"class":62},"effect",[24,103,104],{"class":38},"()\n",[24,106,108],{"class":26,"line":107},6,[24,109,111],{"emptyLinePlaceholder":110},true,"\n",[24,113,115,117,119,121,123,126],{"class":26,"line":114},7,[24,116,84],{"class":42},[24,118,75],{"class":38},[24,120,43],{"class":42},[24,122,81],{"class":38},[24,124,125],{"class":49},"3",[24,127,129],{"class":128},"sy89t"," \u002F\u002F 自动执行 effect()，将 el.innerText 更新为 3\n",[131,132,133],"h2",{"id":133},"响应性实现方式",[10,135,136],{},"我们不难得出想要数据具备响应特性，就需要在数据更新时执行更新操作。只需要通过某种方式，拦截数据的设置操作就可能实现。",[10,138,139,140,143,144,147],{},"在 Vue 2 中，拦截数据的设置操作是通过",[21,141,142],{},"Object.defineProperty","实现的；在 Vue 3 中，利用的是",[21,145,146],{},"Proxy","对象的特性。Proxy 允许对对象的底层操作进行「拦截」，对外提供统一的访问入口，并在此过程中加入自定义逻辑。",[14,149,151],{"className":16,"code":150,"language":18,"meta":19,"style":19},"const obj = { count: 0 }\nconst proxyObj = new Proxy(obj, {\n  get: (o, k) => {\n    return o[k]\n  },\n  set: (o, k, v) => {\n    o[k] = v\n    return true\n  },\n})\n\nproxyObj.count = 1\nconsole.log(obj.count) \u002F\u002F 1\n",[21,152,153,169,192,219,235,240,264,279,287,292,298,303,318],{"__ignoreMap":19},[24,154,155,157,159,161,163,165,167],{"class":26,"line":27},[24,156,31],{"class":30},[24,158,35],{"class":34},[24,160,39],{"class":38},[24,162,43],{"class":42},[24,164,46],{"class":38},[24,166,50],{"class":49},[24,168,53],{"class":38},[24,170,171,173,176,178,181,184,187,189],{"class":26,"line":56},[24,172,31],{"class":30},[24,174,175],{"class":34}," proxyObj",[24,177,81],{"class":38},[24,179,180],{"class":30},"new",[24,182,183],{"class":62}," Proxy",[24,185,186],{"class":38},"(",[24,188,84],{"class":42},[24,190,191],{"class":38},", {\n",[24,193,194,197,200,204,207,210,213,216],{"class":26,"line":69},[24,195,196],{"class":62},"  get",[24,198,199],{"class":38},": (",[24,201,203],{"class":202},"smONe","o",[24,205,206],{"class":38},", ",[24,208,209],{"class":202},"k",[24,211,212],{"class":38},") ",[24,214,215],{"class":30},"=>",[24,217,218],{"class":38}," {\n",[24,220,221,224,227,230,232],{"class":26,"line":92},[24,222,223],{"class":30},"    return",[24,225,226],{"class":42}," o",[24,228,229],{"class":38},"[",[24,231,209],{"class":42},[24,233,234],{"class":38},"]\n",[24,236,237],{"class":26,"line":98},[24,238,239],{"class":38},"  },\n",[24,241,242,245,247,249,251,253,255,258,260,262],{"class":26,"line":107},[24,243,244],{"class":62},"  set",[24,246,199],{"class":38},[24,248,203],{"class":202},[24,250,206],{"class":38},[24,252,209],{"class":202},[24,254,206],{"class":38},[24,256,257],{"class":202},"v",[24,259,212],{"class":38},[24,261,215],{"class":30},[24,263,218],{"class":38},[24,265,266,269,271,273,276],{"class":26,"line":114},[24,267,268],{"class":42},"    o",[24,270,229],{"class":38},[24,272,209],{"class":42},[24,274,275],{"class":38},"] = ",[24,277,278],{"class":42},"v\n",[24,280,282,284],{"class":26,"line":281},8,[24,283,223],{"class":30},[24,285,286],{"class":49}," true\n",[24,288,290],{"class":26,"line":289},9,[24,291,239],{"class":38},[24,293,295],{"class":26,"line":294},10,[24,296,297],{"class":38},"})\n",[24,299,301],{"class":26,"line":300},11,[24,302,111],{"emptyLinePlaceholder":110},[24,304,306,309,311,313,315],{"class":26,"line":305},12,[24,307,308],{"class":42},"proxyObj",[24,310,75],{"class":38},[24,312,43],{"class":42},[24,314,81],{"class":38},[24,316,317],{"class":49},"1\n",[24,319,321,324,326,329,331,333,335,337,339],{"class":26,"line":320},13,[24,322,323],{"class":42},"console",[24,325,75],{"class":38},[24,327,328],{"class":62},"log",[24,330,186],{"class":38},[24,332,84],{"class":42},[24,334,75],{"class":38},[24,336,43],{"class":42},[24,338,212],{"class":38},[24,340,341],{"class":128},"\u002F\u002F 1\n",[10,343,344],{},"通过 Proxy 的语法特性，我们就能实现数据的响应性。现在问题的关键是如何构建一个响应性系统运行所需的数据结构。",[131,346,347],{"id":347},"存储副作用",[10,349,350],{},"在响应式系统中，需要将响应式数据与副作用函数进行关联，以便能够知道在数据发生变化时需要执行哪些副作用。我们将这个过程称为「依赖收集」。那么应该什么时候收集依赖呢？显然是触发响应式数据的读取操作时。",[10,352,353,354,357,358,361,362,365,366,369],{},"要存储收集的依赖，可以使用一个",[21,355,356],{},"Map","结构，其中的键是响应式对象的属性，值是一个集合，用于存储所有依赖该属性的副作用函数。对于响应式对象",[21,359,360],{},"target","，假设有两个属性",[21,363,364],{},"prop1","和",[21,367,368],{},"prop2","，存储的依赖关系可以以下图表示：",[10,371,372],{},[373,374],"img",{"alt":375,"src":376},"依赖收集的存储结构","\u002Fimg\u002Fvue-reactivity\u002Fdependency-structure.png",[10,378,379,380,383],{},"在有多个 target 的情况下，最顶层还需要一个",[21,381,382],{},"WeakMap","，用于存储每个对象的依赖关系。",[10,385,386],{},"我们定义存储结构如下：",[14,388,392],{"className":389,"code":390,"language":391,"meta":19,"style":19},"language-ts shiki shiki-themes houston","\u002F\u002F 全局存储桶，保存每个对象的依赖关系\ntype Bucket = WeakMap\u003Cobject, DepsMap>\n\u002F\u002F 响应式对象中，每个属性和其对应的副作用函数集合的依赖关系表\ntype DepsMap = Map\u003CPropertyKey, Deps>\n\u002F\u002F 每个属性的副作用函数集合\ntype Deps = Set\u003CFunction>\n","ts",[21,393,394,399,425,430,453,458],{"__ignoreMap":19},[24,395,396],{"class":26,"line":27},[24,397,398],{"class":128},"\u002F\u002F 全局存储桶，保存每个对象的依赖关系\n",[24,400,401,404,407,409,411,414,417,419,422],{"class":26,"line":56},[24,402,403],{"class":30},"type",[24,405,406],{"class":34}," Bucket",[24,408,81],{"class":38},[24,410,382],{"class":34},[24,412,413],{"class":38},"\u003C",[24,415,416],{"class":34},"object",[24,418,206],{"class":38},[24,420,421],{"class":34},"DepsMap",[24,423,424],{"class":38},">\n",[24,426,427],{"class":26,"line":69},[24,428,429],{"class":128},"\u002F\u002F 响应式对象中，每个属性和其对应的副作用函数集合的依赖关系表\n",[24,431,432,434,437,439,441,443,446,448,451],{"class":26,"line":92},[24,433,403],{"class":30},[24,435,436],{"class":34}," DepsMap",[24,438,81],{"class":38},[24,440,356],{"class":34},[24,442,413],{"class":38},[24,444,445],{"class":34},"PropertyKey",[24,447,206],{"class":38},[24,449,450],{"class":34},"Deps",[24,452,424],{"class":38},[24,454,455],{"class":26,"line":98},[24,456,457],{"class":128},"\u002F\u002F 每个属性的副作用函数集合\n",[24,459,460,462,465,467,470,472,475],{"class":26,"line":107},[24,461,403],{"class":30},[24,463,464],{"class":34}," Deps",[24,466,81],{"class":38},[24,468,469],{"class":34},"Set",[24,471,413],{"class":38},[24,473,474],{"class":34},"Function",[24,476,424],{"class":38},[478,479,481,484,589],"callout",{"title":480},"WeakMap 与 Map",[10,482,483],{},"WeakMap 和 Map 都是用于存储键值对的数据结构，但它们在内存管理、键的类型以及可操作性上存在本质的区别。",[485,486,487,505],"table",{},[488,489,490],"thead",{},[491,492,493,501,503],"tr",{},[494,495,496],"th",{},[497,498,500],"div",{"style":499},"min-width: 80px","特性",[494,502,356],{},[494,504,382],{},[506,507,508,520,531,556,573],"tbody",{},[491,509,510,514,517],{},[511,512,513],"td",{},"键的类型",[511,515,516],{},"任意类型",[511,518,519],{},"仅限对象或 ES2023 后的 Symbol",[491,521,522,525,528],{},[511,523,524],{},"引用类型",[511,526,527],{},"强引用：只要 Map 存在，键值对就不会被垃圾回收",[511,529,530],{},"弱引用：若无其他引用，键及其关联值会被自动回收",[491,532,533,536,553],{},[511,534,535],{},"迭代\u002F枚举",[511,537,538,539,542,543,542,546,542,549,552],{},"支持（",[21,540,541],{},"keys()","、",[21,544,545],{},"values()",[21,547,548],{},"entries()",[21,550,551],{},"forEach()","等）",[511,554,555],{},"不支持任何迭代方法",[491,557,558,561,567],{},[511,559,560],{},"大小获取",[511,562,538,563,566],{},[21,564,565],{},"size","属性）",[511,568,569,570,572],{},"无",[21,571,565],{},"属性",[491,574,575,578,584],{},[511,576,577],{},"清除",[511,579,538,580,583],{},[21,581,582],{},"clear()","方法）",[511,585,586,587],{},"不支持",[21,588,582],{},[10,590,591],{},"在进行依赖管理的时候，WeakMap 恰好可以存储响应式对象作为键；当响应式对象在业务代码中不再使用时，由于 WeakMap 的弱引用特性，响应式对象及其关联的依赖关系也会被自动回收，避免内存泄漏。",[131,593,594],{"id":594},"初步实现响应式",[10,596,597,598,601],{},"假设副作用函数为",[21,599,600],{},"activeEffect","，我们可以初步实现响应式系统：",[14,603,605],{"className":389,"code":604,"language":391,"meta":19,"style":19},"const bucket: Bucket = new WeakMap()\n\nconst proxyObj = new Proxy(obj, {\n  get: (target, key) => {\n    \u002F\u002F 没有 activeEffect，直接返回值\n    if (!activeEffect) return target[key]\n    let depsMap = bucket.get(target)\n    if (!depsMap) {\n      bucket.set(target, (depsMap = new Map()))\n    }\n    let deps = depsMap.get(key)\n    if (!deps) {\n      depsMap.set(key, (deps = new Set()))\n    }\n    deps.add(activeEffect)\n    return target[key]\n  },\n  set: (target, key, value) => {\n    target[key] = value\n    const depsMap = bucket.get(target)\n    if (!depsMap) return\n    const deps = depsMap.get(key)\n    if (!deps) return\n    deps.forEach(effectFn => effectFn())\n    return true\n  }\n})\n",[21,606,607,628,632,650,669,674,698,723,735,764,769,790,801,827,832,849,862,867,891,906,928,942,963,976,1000,1007,1013],{"__ignoreMap":19},[24,608,609,611,614,616,619,621,623,626],{"class":26,"line":27},[24,610,31],{"class":30},[24,612,613],{"class":34}," bucket",[24,615,46],{"class":38},[24,617,618],{"class":34},"Bucket",[24,620,81],{"class":38},[24,622,180],{"class":30},[24,624,625],{"class":62}," WeakMap",[24,627,104],{"class":38},[24,629,630],{"class":26,"line":56},[24,631,111],{"emptyLinePlaceholder":110},[24,633,634,636,638,640,642,644,646,648],{"class":26,"line":69},[24,635,31],{"class":30},[24,637,175],{"class":34},[24,639,81],{"class":38},[24,641,180],{"class":30},[24,643,183],{"class":62},[24,645,186],{"class":38},[24,647,84],{"class":42},[24,649,191],{"class":38},[24,651,652,654,656,658,660,663,665,667],{"class":26,"line":92},[24,653,196],{"class":62},[24,655,199],{"class":38},[24,657,360],{"class":202},[24,659,206],{"class":38},[24,661,662],{"class":202},"key",[24,664,212],{"class":38},[24,666,215],{"class":30},[24,668,218],{"class":38},[24,670,671],{"class":26,"line":98},[24,672,673],{"class":128},"    \u002F\u002F 没有 activeEffect，直接返回值\n",[24,675,676,679,682,684,686,689,692,694,696],{"class":26,"line":107},[24,677,678],{"class":30},"    if",[24,680,681],{"class":38}," (!",[24,683,600],{"class":42},[24,685,212],{"class":38},[24,687,688],{"class":30},"return",[24,690,691],{"class":42}," target",[24,693,229],{"class":38},[24,695,662],{"class":42},[24,697,234],{"class":38},[24,699,700,703,706,708,711,713,716,718,720],{"class":26,"line":114},[24,701,702],{"class":30},"    let",[24,704,705],{"class":42}," depsMap",[24,707,81],{"class":38},[24,709,710],{"class":42},"bucket",[24,712,75],{"class":38},[24,714,715],{"class":62},"get",[24,717,186],{"class":38},[24,719,360],{"class":42},[24,721,722],{"class":38},")\n",[24,724,725,727,729,732],{"class":26,"line":281},[24,726,678],{"class":30},[24,728,681],{"class":38},[24,730,731],{"class":42},"depsMap",[24,733,734],{"class":38},") {\n",[24,736,737,740,742,745,747,749,752,754,756,758,761],{"class":26,"line":289},[24,738,739],{"class":42},"      bucket",[24,741,75],{"class":38},[24,743,744],{"class":62},"set",[24,746,186],{"class":38},[24,748,360],{"class":42},[24,750,751],{"class":38},", (",[24,753,731],{"class":42},[24,755,81],{"class":38},[24,757,180],{"class":30},[24,759,760],{"class":62}," Map",[24,762,763],{"class":38},"()))\n",[24,765,766],{"class":26,"line":294},[24,767,768],{"class":38},"    }\n",[24,770,771,773,776,778,780,782,784,786,788],{"class":26,"line":300},[24,772,702],{"class":30},[24,774,775],{"class":42}," deps",[24,777,81],{"class":38},[24,779,731],{"class":42},[24,781,75],{"class":38},[24,783,715],{"class":62},[24,785,186],{"class":38},[24,787,662],{"class":42},[24,789,722],{"class":38},[24,791,792,794,796,799],{"class":26,"line":305},[24,793,678],{"class":30},[24,795,681],{"class":38},[24,797,798],{"class":42},"deps",[24,800,734],{"class":38},[24,802,803,806,808,810,812,814,816,818,820,822,825],{"class":26,"line":320},[24,804,805],{"class":42},"      depsMap",[24,807,75],{"class":38},[24,809,744],{"class":62},[24,811,186],{"class":38},[24,813,662],{"class":42},[24,815,751],{"class":38},[24,817,798],{"class":42},[24,819,81],{"class":38},[24,821,180],{"class":30},[24,823,824],{"class":62}," Set",[24,826,763],{"class":38},[24,828,830],{"class":26,"line":829},14,[24,831,768],{"class":38},[24,833,835,838,840,843,845,847],{"class":26,"line":834},15,[24,836,837],{"class":42},"    deps",[24,839,75],{"class":38},[24,841,842],{"class":62},"add",[24,844,186],{"class":38},[24,846,600],{"class":42},[24,848,722],{"class":38},[24,850,852,854,856,858,860],{"class":26,"line":851},16,[24,853,223],{"class":30},[24,855,691],{"class":42},[24,857,229],{"class":38},[24,859,662],{"class":42},[24,861,234],{"class":38},[24,863,865],{"class":26,"line":864},17,[24,866,239],{"class":38},[24,868,870,872,874,876,878,880,882,885,887,889],{"class":26,"line":869},18,[24,871,244],{"class":62},[24,873,199],{"class":38},[24,875,360],{"class":202},[24,877,206],{"class":38},[24,879,662],{"class":202},[24,881,206],{"class":38},[24,883,884],{"class":202},"value",[24,886,212],{"class":38},[24,888,215],{"class":30},[24,890,218],{"class":38},[24,892,894,897,899,901,903],{"class":26,"line":893},19,[24,895,896],{"class":42},"    target",[24,898,229],{"class":38},[24,900,662],{"class":42},[24,902,275],{"class":38},[24,904,905],{"class":42},"value\n",[24,907,909,912,914,916,918,920,922,924,926],{"class":26,"line":908},20,[24,910,911],{"class":30},"    const",[24,913,705],{"class":34},[24,915,81],{"class":38},[24,917,710],{"class":42},[24,919,75],{"class":38},[24,921,715],{"class":62},[24,923,186],{"class":38},[24,925,360],{"class":42},[24,927,722],{"class":38},[24,929,931,933,935,937,939],{"class":26,"line":930},21,[24,932,678],{"class":30},[24,934,681],{"class":38},[24,936,731],{"class":42},[24,938,212],{"class":38},[24,940,941],{"class":30},"return\n",[24,943,945,947,949,951,953,955,957,959,961],{"class":26,"line":944},22,[24,946,911],{"class":30},[24,948,775],{"class":34},[24,950,81],{"class":38},[24,952,731],{"class":42},[24,954,75],{"class":38},[24,956,715],{"class":62},[24,958,186],{"class":38},[24,960,662],{"class":42},[24,962,722],{"class":38},[24,964,966,968,970,972,974],{"class":26,"line":965},23,[24,967,678],{"class":30},[24,969,681],{"class":38},[24,971,798],{"class":42},[24,973,212],{"class":38},[24,975,941],{"class":30},[24,977,979,981,983,986,988,991,994,997],{"class":26,"line":978},24,[24,980,837],{"class":42},[24,982,75],{"class":38},[24,984,985],{"class":62},"forEach",[24,987,186],{"class":38},[24,989,990],{"class":202},"effectFn",[24,992,993],{"class":30}," =>",[24,995,996],{"class":62}," effectFn",[24,998,999],{"class":38},"())\n",[24,1001,1003,1005],{"class":26,"line":1002},25,[24,1004,223],{"class":30},[24,1006,286],{"class":49},[24,1008,1010],{"class":26,"line":1009},26,[24,1011,1012],{"class":38},"  }\n",[24,1014,1016],{"class":26,"line":1015},27,[24,1017,297],{"class":38},[10,1019,1020],{},"使用时：",[14,1022,1024],{"className":389,"code":1023,"language":391,"meta":19,"style":19},"const obj = { count: 0 }\n\nconst activeEffect = () => {\n  console.log('effect run:', proxyObj.count)\n}\n\nconst proxyObj = new Proxy(obj, { \u002F*... *\u002F })\n\nactiveEffect() \u002F\u002F 执行副作用，触发读取\n\nproxyObj.count = 1 \u002F\u002F 输出：effect run: 1\nproxyObj.count = 3 \u002F\u002F 输出：effect run: 3\n",[21,1025,1026,1042,1046,1060,1084,1088,1092,1117,1121,1131,1135,1151],{"__ignoreMap":19},[24,1027,1028,1030,1032,1034,1036,1038,1040],{"class":26,"line":27},[24,1029,31],{"class":30},[24,1031,35],{"class":34},[24,1033,39],{"class":38},[24,1035,43],{"class":42},[24,1037,46],{"class":38},[24,1039,50],{"class":49},[24,1041,53],{"class":38},[24,1043,1044],{"class":26,"line":56},[24,1045,111],{"emptyLinePlaceholder":110},[24,1047,1048,1050,1053,1056,1058],{"class":26,"line":69},[24,1049,31],{"class":30},[24,1051,1052],{"class":62}," activeEffect",[24,1054,1055],{"class":38}," = () ",[24,1057,215],{"class":30},[24,1059,218],{"class":38},[24,1061,1062,1065,1067,1069,1071,1074,1076,1078,1080,1082],{"class":26,"line":92},[24,1063,1064],{"class":42},"  console",[24,1066,75],{"class":38},[24,1068,328],{"class":62},[24,1070,186],{"class":38},[24,1072,1073],{"class":49},"'effect run:'",[24,1075,206],{"class":38},[24,1077,308],{"class":42},[24,1079,75],{"class":38},[24,1081,43],{"class":42},[24,1083,722],{"class":38},[24,1085,1086],{"class":26,"line":98},[24,1087,95],{"class":38},[24,1089,1090],{"class":26,"line":107},[24,1091,111],{"emptyLinePlaceholder":110},[24,1093,1094,1096,1098,1100,1102,1104,1106,1108,1111,1114],{"class":26,"line":114},[24,1095,31],{"class":30},[24,1097,175],{"class":34},[24,1099,81],{"class":38},[24,1101,180],{"class":30},[24,1103,183],{"class":62},[24,1105,186],{"class":38},[24,1107,84],{"class":42},[24,1109,1110],{"class":38},", { ",[24,1112,1113],{"class":128},"\u002F*... *\u002F",[24,1115,1116],{"class":38}," })\n",[24,1118,1119],{"class":26,"line":281},[24,1120,111],{"emptyLinePlaceholder":110},[24,1122,1123,1125,1128],{"class":26,"line":289},[24,1124,600],{"class":62},[24,1126,1127],{"class":38},"() ",[24,1129,1130],{"class":128},"\u002F\u002F 执行副作用，触发读取\n",[24,1132,1133],{"class":26,"line":294},[24,1134,111],{"emptyLinePlaceholder":110},[24,1136,1137,1139,1141,1143,1145,1148],{"class":26,"line":300},[24,1138,308],{"class":42},[24,1140,75],{"class":38},[24,1142,43],{"class":42},[24,1144,81],{"class":38},[24,1146,1147],{"class":49},"1",[24,1149,1150],{"class":128}," \u002F\u002F 输出：effect run: 1\n",[24,1152,1153,1155,1157,1159,1161,1163],{"class":26,"line":305},[24,1154,308],{"class":42},[24,1156,75],{"class":38},[24,1158,43],{"class":42},[24,1160,81],{"class":38},[24,1162,125],{"class":49},[24,1164,1165],{"class":128}," \u002F\u002F 输出：effect run: 3\n",[10,1167,1168,1169,1171,1172,1174,1175,1177],{},"当改变响应式对象",[21,1170,308],{},"中",[21,1173,43],{},"属性时，副作用函数会自动执行。此时，",[21,1176,43],{},"就是一个响应式数据了。",[131,1179,1180],{"id":1180},"分支切换",[10,1182,1183],{},"在当前的实现中，响应式对象上任何属性的读取操作，都会导致当前的副作用被收集到对应的属性的依赖集合中。这在大部分情况下是符合预期的。但是，假设存在以下情况：",[14,1185,1187],{"className":389,"code":1186,"language":391,"meta":19,"style":19},"const obj = { enabled: true, count: 0 }\nconst activeEffect = () => {\n  el.innerText = proxyObj.enabled ? proxyObj.count : 'N\u002FA'\n}\n",[21,1188,1189,1215,1227,1258],{"__ignoreMap":19},[24,1190,1191,1193,1195,1197,1200,1202,1205,1207,1209,1211,1213],{"class":26,"line":27},[24,1192,31],{"class":30},[24,1194,35],{"class":34},[24,1196,39],{"class":38},[24,1198,1199],{"class":42},"enabled",[24,1201,46],{"class":38},[24,1203,1204],{"class":49},"true",[24,1206,206],{"class":38},[24,1208,43],{"class":42},[24,1210,46],{"class":38},[24,1212,50],{"class":49},[24,1214,53],{"class":38},[24,1216,1217,1219,1221,1223,1225],{"class":26,"line":56},[24,1218,31],{"class":30},[24,1220,1052],{"class":62},[24,1222,1055],{"class":38},[24,1224,215],{"class":30},[24,1226,218],{"class":38},[24,1228,1229,1231,1233,1235,1237,1239,1241,1243,1246,1248,1250,1252,1255],{"class":26,"line":69},[24,1230,72],{"class":42},[24,1232,75],{"class":38},[24,1234,78],{"class":42},[24,1236,81],{"class":38},[24,1238,308],{"class":42},[24,1240,75],{"class":38},[24,1242,1199],{"class":42},[24,1244,1245],{"class":30}," ?",[24,1247,175],{"class":42},[24,1249,75],{"class":38},[24,1251,43],{"class":42},[24,1253,1254],{"class":30}," :",[24,1256,1257],{"class":49}," 'N\u002FA'\n",[24,1259,1260],{"class":26,"line":92},[24,1261,95],{"class":38},[10,1263,1264,1265,365,1268,1271],{},"执行副作用后将触发",[21,1266,1267],{},"proxyObj.enabled",[21,1269,1270],{},"proxyObj.count","的读取操作，建立如下图所示的依赖关系：",[10,1273,1274],{},[373,1275],{"alt":1276,"src":1277},"错误的依赖收集","\u002Fimg\u002Fvue-reactivity\u002Fincorrect-collect.png",[10,1279,1280,1281,1284,1285,1288,1289,1292,1293,1295,1296,1298,1299,1301,1302,1304],{},"此时，再次修改",[21,1282,1283],{},"proxyObj.enabled = false","，触发副作用函数再次执行；执行后，",[21,1286,1287],{},"el.innerText","将被设置为",[21,1290,1291],{},"'N\u002FA'","。此后，无论",[21,1294,1270],{},"如何变化，",[21,1297,1287],{},"都将保持为",[21,1300,1291],{},"。也就是说，",[21,1303,1270],{},"的变化不应当再次触发副作用函数的执行。",[10,1306,1307,1308,365,1310,1312],{},"不过目前的实现并不能做到这一点。即便分析后可以认定",[21,1309,1287],{},[21,1311,1270],{},"不再有依赖关系，但副作用函数依然会执行。这种遗留的副作用在生产中往往会构成不必要的更新。我们知道 Vue 中相当多的特性依靠响应式系统才得以实现，例如计算属性、侦听器等。如果这些特性在依赖收集时没有正确处理，就会导致性能问题。",[10,1314,1315,1316,1318,1319,1322,1323,1325,1326,1328,1329,1331],{},"观察副作用函数。当",[21,1317,1267],{},"变为",[21,1320,1321],{},"false","时，就不会再触发",[21,1324,1270],{},"的读取操作。因此，想要去除遗留的副作用，只需要在每次副作用执行后，都重新建立依赖关系即可。换句话说，响应式系统需要在副作用函数再次执行前，能够把",[21,1327,600],{},"从",[21,1330,1270],{},"的依赖集合中移除。",[10,1333,1334],{},"为了支持这种移除，需要重新设计副作用函数。",[10,1336,1337,1338,1340,1341,1343,1344,1346,1347,1349,1350,1352,1353,1355],{},"当前，示例使用一个名为",[21,1339,600],{},"的全局变量表示当前正在执行的副作用函数。在实际使用时，用户也必须提供一个名为",[21,1342,600],{},"的副作用并手动调用一次触发响应式对象的读取操作，这样很不灵活。改进的方法是保留",[21,1345,600],{},"为内部使用，面向用户提供一个用于注册副作用函数的函数",[21,1348,101],{},"。",[21,1351,101],{},"可以接受一个函数作为参数（即用户传入的真正的副作用函数），将其赋值给",[21,1354,600],{},"，立刻执行一次。",[14,1357,1359],{"className":389,"code":1358,"language":391,"meta":19,"style":19},"function effect(fn: Function) {\n  activeEffect = fn\n  fn()\n}\n",[21,1360,1361,1378,1388,1395],{"__ignoreMap":19},[24,1362,1363,1365,1367,1369,1372,1374,1376],{"class":26,"line":27},[24,1364,59],{"class":30},[24,1366,63],{"class":62},[24,1368,186],{"class":38},[24,1370,1371],{"class":62},"fn",[24,1373,46],{"class":38},[24,1375,474],{"class":34},[24,1377,734],{"class":38},[24,1379,1380,1383,1385],{"class":26,"line":56},[24,1381,1382],{"class":42},"  activeEffect",[24,1384,81],{"class":38},[24,1386,1387],{"class":42},"fn\n",[24,1389,1390,1393],{"class":26,"line":69},[24,1391,1392],{"class":62},"  fn",[24,1394,104],{"class":38},[24,1396,1397],{"class":26,"line":92},[24,1398,95],{"class":38},[10,1400,1401,1402,1404,1405,1407,1408,1411,1412,1415],{},"其次，为了能够将",[21,1403,600],{},"从响应式对象属性的依赖集合中移除，需要为副作用函数保存与其关联的依赖集合。因此，定义",[21,1406,990],{},"，为其增加",[21,1409,1410],{},".deps","属性保存依赖集合，并新增",[21,1413,1414],{},"cleanup","方法用于清除依赖。",[14,1417,1419],{"className":389,"code":1418,"language":391,"meta":19,"style":19},"function effect(fn: Function) {\n  const effectFn = (): Function & { deps: Deps[] } => {\n    \u002F\u002F 新增清除依赖的方法 cleanup\n    cleanup(effectFn)\n    activeEffect = effectFn\n    fn()\n  }\n  effectFn.deps = []\n  return effectFn\n}\n\nfunction cleanup(effectFn: Function & { deps: Deps[] }) {\n  for (let i = 0; i \u003C effectFn.deps.length; i++) {\n    \u002F\u002F deps: 所有关联该副作用函数的依赖集合\n    const deps = effectFn.deps[i]\n    deps.delete(effectFn)\n  }\n  effectFn.deps.length = 0\n}\n",[21,1420,1421,1437,1465,1470,1481,1491,1498,1502,1514,1522,1526,1530,1556,1601,1606,1626,1641,1645,1662],{"__ignoreMap":19},[24,1422,1423,1425,1427,1429,1431,1433,1435],{"class":26,"line":27},[24,1424,59],{"class":30},[24,1426,63],{"class":62},[24,1428,186],{"class":38},[24,1430,1371],{"class":62},[24,1432,46],{"class":38},[24,1434,474],{"class":34},[24,1436,734],{"class":38},[24,1438,1439,1442,1444,1447,1449,1452,1454,1456,1458,1461,1463],{"class":26,"line":56},[24,1440,1441],{"class":30},"  const",[24,1443,996],{"class":62},[24,1445,1446],{"class":38}," = (): ",[24,1448,474],{"class":34},[24,1450,1451],{"class":38}," & { ",[24,1453,798],{"class":42},[24,1455,46],{"class":38},[24,1457,450],{"class":34},[24,1459,1460],{"class":38},"[] } ",[24,1462,215],{"class":30},[24,1464,218],{"class":38},[24,1466,1467],{"class":26,"line":69},[24,1468,1469],{"class":128},"    \u002F\u002F 新增清除依赖的方法 cleanup\n",[24,1471,1472,1475,1477,1479],{"class":26,"line":92},[24,1473,1474],{"class":62},"    cleanup",[24,1476,186],{"class":38},[24,1478,990],{"class":42},[24,1480,722],{"class":38},[24,1482,1483,1486,1488],{"class":26,"line":98},[24,1484,1485],{"class":42},"    activeEffect",[24,1487,81],{"class":38},[24,1489,1490],{"class":42},"effectFn\n",[24,1492,1493,1496],{"class":26,"line":107},[24,1494,1495],{"class":62},"    fn",[24,1497,104],{"class":38},[24,1499,1500],{"class":26,"line":114},[24,1501,1012],{"class":38},[24,1503,1504,1507,1509,1511],{"class":26,"line":281},[24,1505,1506],{"class":42},"  effectFn",[24,1508,75],{"class":38},[24,1510,798],{"class":42},[24,1512,1513],{"class":38}," = []\n",[24,1515,1516,1519],{"class":26,"line":289},[24,1517,1518],{"class":30},"  return",[24,1520,1521],{"class":42}," effectFn\n",[24,1523,1524],{"class":26,"line":294},[24,1525,95],{"class":38},[24,1527,1528],{"class":26,"line":300},[24,1529,111],{"emptyLinePlaceholder":110},[24,1531,1532,1534,1537,1539,1541,1543,1545,1547,1549,1551,1553],{"class":26,"line":305},[24,1533,59],{"class":30},[24,1535,1536],{"class":62}," cleanup",[24,1538,186],{"class":38},[24,1540,990],{"class":62},[24,1542,46],{"class":38},[24,1544,474],{"class":34},[24,1546,1451],{"class":38},[24,1548,798],{"class":42},[24,1550,46],{"class":38},[24,1552,450],{"class":34},[24,1554,1555],{"class":38},"[] }) {\n",[24,1557,1558,1561,1564,1567,1570,1572,1574,1577,1580,1583,1585,1587,1589,1591,1594,1596,1598],{"class":26,"line":320},[24,1559,1560],{"class":30},"  for",[24,1562,1563],{"class":38}," (",[24,1565,1566],{"class":30},"let",[24,1568,1569],{"class":42}," i",[24,1571,81],{"class":38},[24,1573,50],{"class":49},[24,1575,1576],{"class":38},"; ",[24,1578,1579],{"class":42},"i",[24,1581,1582],{"class":38}," \u003C ",[24,1584,990],{"class":42},[24,1586,75],{"class":38},[24,1588,798],{"class":42},[24,1590,75],{"class":38},[24,1592,1593],{"class":42},"length",[24,1595,1576],{"class":38},[24,1597,1579],{"class":42},[24,1599,1600],{"class":38},"++) {\n",[24,1602,1603],{"class":26,"line":829},[24,1604,1605],{"class":128},"    \u002F\u002F deps: 所有关联该副作用函数的依赖集合\n",[24,1607,1608,1610,1612,1614,1616,1618,1620,1622,1624],{"class":26,"line":834},[24,1609,911],{"class":30},[24,1611,775],{"class":34},[24,1613,81],{"class":38},[24,1615,990],{"class":42},[24,1617,75],{"class":38},[24,1619,798],{"class":42},[24,1621,229],{"class":38},[24,1623,1579],{"class":42},[24,1625,234],{"class":38},[24,1627,1628,1630,1632,1635,1637,1639],{"class":26,"line":851},[24,1629,837],{"class":42},[24,1631,75],{"class":38},[24,1633,1634],{"class":62},"delete",[24,1636,186],{"class":38},[24,1638,990],{"class":42},[24,1640,722],{"class":38},[24,1642,1643],{"class":26,"line":864},[24,1644,1012],{"class":38},[24,1646,1647,1649,1651,1653,1655,1657,1659],{"class":26,"line":869},[24,1648,1506],{"class":42},[24,1650,75],{"class":38},[24,1652,798],{"class":42},[24,1654,75],{"class":38},[24,1656,1593],{"class":42},[24,1658,81],{"class":38},[24,1660,1661],{"class":49},"0\n",[24,1663,1664],{"class":26,"line":893},[24,1665,95],{"class":38},[10,1667,1668,1669,1671,1672,1674,1675,1677],{},"现在，依赖集合不仅保存在响应式对象的",[21,1670,731],{},"中，还保存在副作用函数的",[21,1673,1410],{},"属性中。在 getter 中为响应式对象收集依赖时，可一并将依赖集合 push 到副作用函数的",[21,1676,1410],{},"数组中。",[14,1679,1681],{"className":389,"code":1680,"language":391,"meta":19,"style":19},"const proxyObj = new Proxy(obj, {\n  get: (target, key) => {\n    if (!activeEffect) return target[key]\n    let depsMap = bucket.get(target)\n    if (!depsMap) {\n      bucket.set(target, (depsMap = new Map()))\n    }\n    let deps = depsMap.get(key)\n    if (!deps) {\n      depsMap.set(key, (deps = new Set()))\n    }\n    deps.add(activeEffect)\n    effectFn.deps.push(deps)\n    return target[key]\n  },\n  \u002F* ... *\u002F\n})\n",[21,1682,1683,1701,1719,1739,1759,1769,1793,1797,1817,1827,1851,1855,1869,1889,1901,1905,1910],{"__ignoreMap":19},[24,1684,1685,1687,1689,1691,1693,1695,1697,1699],{"class":26,"line":27},[24,1686,31],{"class":30},[24,1688,175],{"class":34},[24,1690,81],{"class":38},[24,1692,180],{"class":30},[24,1694,183],{"class":62},[24,1696,186],{"class":38},[24,1698,84],{"class":42},[24,1700,191],{"class":38},[24,1702,1703,1705,1707,1709,1711,1713,1715,1717],{"class":26,"line":56},[24,1704,196],{"class":62},[24,1706,199],{"class":38},[24,1708,360],{"class":202},[24,1710,206],{"class":38},[24,1712,662],{"class":202},[24,1714,212],{"class":38},[24,1716,215],{"class":30},[24,1718,218],{"class":38},[24,1720,1721,1723,1725,1727,1729,1731,1733,1735,1737],{"class":26,"line":69},[24,1722,678],{"class":30},[24,1724,681],{"class":38},[24,1726,600],{"class":42},[24,1728,212],{"class":38},[24,1730,688],{"class":30},[24,1732,691],{"class":42},[24,1734,229],{"class":38},[24,1736,662],{"class":42},[24,1738,234],{"class":38},[24,1740,1741,1743,1745,1747,1749,1751,1753,1755,1757],{"class":26,"line":92},[24,1742,702],{"class":30},[24,1744,705],{"class":42},[24,1746,81],{"class":38},[24,1748,710],{"class":42},[24,1750,75],{"class":38},[24,1752,715],{"class":62},[24,1754,186],{"class":38},[24,1756,360],{"class":42},[24,1758,722],{"class":38},[24,1760,1761,1763,1765,1767],{"class":26,"line":98},[24,1762,678],{"class":30},[24,1764,681],{"class":38},[24,1766,731],{"class":42},[24,1768,734],{"class":38},[24,1770,1771,1773,1775,1777,1779,1781,1783,1785,1787,1789,1791],{"class":26,"line":107},[24,1772,739],{"class":42},[24,1774,75],{"class":38},[24,1776,744],{"class":62},[24,1778,186],{"class":38},[24,1780,360],{"class":42},[24,1782,751],{"class":38},[24,1784,731],{"class":42},[24,1786,81],{"class":38},[24,1788,180],{"class":30},[24,1790,760],{"class":62},[24,1792,763],{"class":38},[24,1794,1795],{"class":26,"line":114},[24,1796,768],{"class":38},[24,1798,1799,1801,1803,1805,1807,1809,1811,1813,1815],{"class":26,"line":281},[24,1800,702],{"class":30},[24,1802,775],{"class":42},[24,1804,81],{"class":38},[24,1806,731],{"class":42},[24,1808,75],{"class":38},[24,1810,715],{"class":62},[24,1812,186],{"class":38},[24,1814,662],{"class":42},[24,1816,722],{"class":38},[24,1818,1819,1821,1823,1825],{"class":26,"line":289},[24,1820,678],{"class":30},[24,1822,681],{"class":38},[24,1824,798],{"class":42},[24,1826,734],{"class":38},[24,1828,1829,1831,1833,1835,1837,1839,1841,1843,1845,1847,1849],{"class":26,"line":294},[24,1830,805],{"class":42},[24,1832,75],{"class":38},[24,1834,744],{"class":62},[24,1836,186],{"class":38},[24,1838,662],{"class":42},[24,1840,751],{"class":38},[24,1842,798],{"class":42},[24,1844,81],{"class":38},[24,1846,180],{"class":30},[24,1848,824],{"class":62},[24,1850,763],{"class":38},[24,1852,1853],{"class":26,"line":300},[24,1854,768],{"class":38},[24,1856,1857,1859,1861,1863,1865,1867],{"class":26,"line":305},[24,1858,837],{"class":42},[24,1860,75],{"class":38},[24,1862,842],{"class":62},[24,1864,186],{"class":38},[24,1866,600],{"class":42},[24,1868,722],{"class":38},[24,1870,1871,1874,1876,1878,1880,1883,1885,1887],{"class":26,"line":320},[24,1872,1873],{"class":42},"    effectFn",[24,1875,75],{"class":38},[24,1877,798],{"class":42},[24,1879,75],{"class":38},[24,1881,1882],{"class":62},"push",[24,1884,186],{"class":38},[24,1886,798],{"class":42},[24,1888,722],{"class":38},[24,1890,1891,1893,1895,1897,1899],{"class":26,"line":829},[24,1892,223],{"class":30},[24,1894,691],{"class":42},[24,1896,229],{"class":38},[24,1898,662],{"class":42},[24,1900,234],{"class":38},[24,1902,1903],{"class":26,"line":834},[24,1904,239],{"class":38},[24,1906,1907],{"class":26,"line":851},[24,1908,1909],{"class":128},"  \u002F* ... *\u002F\n",[24,1911,1912],{"class":26,"line":864},[24,1913,297],{"class":38},[10,1915,1916],{},"对依赖关系的收集如下图所示：",[10,1918,1919],{},[373,1920],{"alt":1921,"src":1922},"分支依赖收集","\u002Fimg\u002Fvue-reactivity\u002Fbranch-dependency.png",[10,1924,1925,1926,1929,1930,1349],{},"下面是完整的代码。其中将 Proxy 的 getter 中收集依赖的逻辑提取出来，封装为一个函数",[21,1927,1928],{},"track","，将 setter 中触发依赖执行的逻辑提取出来，封装为一个函数",[21,1931,1932],{},"trigger",[14,1934,1936],{"className":389,"code":1935,"language":391,"meta":19,"style":19},"\u002F\u002F 全局存储桶，保存每个对象的依赖关系\ntype Bucket = WeakMap\u003Cobject, DepsMap>\n\u002F\u002F 响应式对象中，每个属性和其对应的副作用函数集合的依赖关系表\ntype DepsMap = Map\u003CPropertyKey, Deps>\n\u002F\u002F 每个属性的副作用函数集合\ntype Deps = Set\u003CEffectFn>\n\u002F\u002F 副作用函数。新增`deps`存储包含该副作用的所有依赖集合\ntype EffectFn = Function & { deps: Deps[] }\n\nconst bucket: Bucket = new WeakMap()\nlet activeEffect: EffectFn\n\nconst obj: Record\u003Cstring, any> = { count: 0, enabled: true }\n\nfunction cleanup(effectFn: EffectFn) {\n  for (let i = 0; i \u003C effectFn.deps.length; i++) {\n    const deps = effectFn.deps[i]\n    deps.delete(effectFn)\n  }\n  effectFn.deps.length = 0\n}\n\nfunction effect(fn: Function) {\n  const effectFn: EffectFn = () => {\n    cleanup(effectFn)\n    activeEffect = effectFn\n    fn()\n  }\n  effectFn.deps = []\n  effectFn()\n}\n\nfunction track(target: object, key: PropertyKey) {\n  \u002F\u002F 没有 activeEffect，直接返回\n  if (!activeEffect) return\n  let depsMap = bucket.get(target)\n  if (!depsMap) {\n    bucket.set(target, (depsMap = new Map()))\n  }\n  let deps = depsMap.get(key)\n  if (!deps) {\n    depsMap.set(key, (deps = new Set()))\n  }\n  deps.add(activeEffect)\n  activeEffect.deps.push(deps)\n}\n\nfunction trigger(target: object, key: PropertyKey): void {\n  const depsMap = bucket.get(target)\n  if (!depsMap) return\n  const deps = depsMap.get(key)\n  if (!deps) return\n  deps.forEach(effectFn => effectFn())\n}\n\nconst proxyObj = new Proxy(obj, {\n  get: (target, key: PropertyKey) => {\n    track(target, key)\n    return target[key]\n  },\n  set: (target, key: PropertyKey, value) => {\n    target[key] = value\n    trigger(target, key)\n    return true\n  }\n})\n\neffect(() => {\n  el.innerText = proxyObj.enabled ? proxyObj.count : 'N\u002FA'\n})\n",[21,1937,1938,1942,1962,1966,1986,1990,2007,2012,2034,2038,2056,2067,2071,2111,2115,2131,2167,2187,2201,2205,2221,2225,2229,2245,2261,2271,2279,2285,2290,2301,2308,2313,2318,2344,2350,2364,2386,2397,2423,2428,2449,2460,2486,2491,2507,2526,2531,2536,2568,2589,2602,2623,2636,2655,2660,2665,2684,2707,2723,2736,2741,2768,2781,2797,2804,2809,2814,2819,2831,2860],{"__ignoreMap":19},[24,1939,1940],{"class":26,"line":27},[24,1941,398],{"class":128},[24,1943,1944,1946,1948,1950,1952,1954,1956,1958,1960],{"class":26,"line":56},[24,1945,403],{"class":30},[24,1947,406],{"class":34},[24,1949,81],{"class":38},[24,1951,382],{"class":34},[24,1953,413],{"class":38},[24,1955,416],{"class":34},[24,1957,206],{"class":38},[24,1959,421],{"class":34},[24,1961,424],{"class":38},[24,1963,1964],{"class":26,"line":69},[24,1965,429],{"class":128},[24,1967,1968,1970,1972,1974,1976,1978,1980,1982,1984],{"class":26,"line":92},[24,1969,403],{"class":30},[24,1971,436],{"class":34},[24,1973,81],{"class":38},[24,1975,356],{"class":34},[24,1977,413],{"class":38},[24,1979,445],{"class":34},[24,1981,206],{"class":38},[24,1983,450],{"class":34},[24,1985,424],{"class":38},[24,1987,1988],{"class":26,"line":98},[24,1989,457],{"class":128},[24,1991,1992,1994,1996,1998,2000,2002,2005],{"class":26,"line":107},[24,1993,403],{"class":30},[24,1995,464],{"class":34},[24,1997,81],{"class":38},[24,1999,469],{"class":34},[24,2001,413],{"class":38},[24,2003,2004],{"class":34},"EffectFn",[24,2006,424],{"class":38},[24,2008,2009],{"class":26,"line":114},[24,2010,2011],{"class":128},"\u002F\u002F 副作用函数。新增`deps`存储包含该副作用的所有依赖集合\n",[24,2013,2014,2016,2019,2021,2023,2025,2027,2029,2031],{"class":26,"line":281},[24,2015,403],{"class":30},[24,2017,2018],{"class":34}," EffectFn",[24,2020,81],{"class":38},[24,2022,474],{"class":34},[24,2024,1451],{"class":38},[24,2026,798],{"class":42},[24,2028,46],{"class":38},[24,2030,450],{"class":34},[24,2032,2033],{"class":38},"[] }\n",[24,2035,2036],{"class":26,"line":289},[24,2037,111],{"emptyLinePlaceholder":110},[24,2039,2040,2042,2044,2046,2048,2050,2052,2054],{"class":26,"line":294},[24,2041,31],{"class":30},[24,2043,613],{"class":34},[24,2045,46],{"class":38},[24,2047,618],{"class":34},[24,2049,81],{"class":38},[24,2051,180],{"class":30},[24,2053,625],{"class":62},[24,2055,104],{"class":38},[24,2057,2058,2060,2062,2064],{"class":26,"line":300},[24,2059,1566],{"class":30},[24,2061,1052],{"class":42},[24,2063,46],{"class":38},[24,2065,2066],{"class":34},"EffectFn\n",[24,2068,2069],{"class":26,"line":305},[24,2070,111],{"emptyLinePlaceholder":110},[24,2072,2073,2075,2077,2079,2082,2084,2087,2089,2092,2095,2097,2099,2101,2103,2105,2107,2109],{"class":26,"line":320},[24,2074,31],{"class":30},[24,2076,35],{"class":34},[24,2078,46],{"class":38},[24,2080,2081],{"class":34},"Record",[24,2083,413],{"class":38},[24,2085,2086],{"class":34},"string",[24,2088,206],{"class":38},[24,2090,2091],{"class":34},"any",[24,2093,2094],{"class":38},"> = { ",[24,2096,43],{"class":42},[24,2098,46],{"class":38},[24,2100,50],{"class":49},[24,2102,206],{"class":38},[24,2104,1199],{"class":42},[24,2106,46],{"class":38},[24,2108,1204],{"class":49},[24,2110,53],{"class":38},[24,2112,2113],{"class":26,"line":829},[24,2114,111],{"emptyLinePlaceholder":110},[24,2116,2117,2119,2121,2123,2125,2127,2129],{"class":26,"line":834},[24,2118,59],{"class":30},[24,2120,1536],{"class":62},[24,2122,186],{"class":38},[24,2124,990],{"class":202},[24,2126,46],{"class":38},[24,2128,2004],{"class":34},[24,2130,734],{"class":38},[24,2132,2133,2135,2137,2139,2141,2143,2145,2147,2149,2151,2153,2155,2157,2159,2161,2163,2165],{"class":26,"line":851},[24,2134,1560],{"class":30},[24,2136,1563],{"class":38},[24,2138,1566],{"class":30},[24,2140,1569],{"class":42},[24,2142,81],{"class":38},[24,2144,50],{"class":49},[24,2146,1576],{"class":38},[24,2148,1579],{"class":42},[24,2150,1582],{"class":38},[24,2152,990],{"class":42},[24,2154,75],{"class":38},[24,2156,798],{"class":42},[24,2158,75],{"class":38},[24,2160,1593],{"class":42},[24,2162,1576],{"class":38},[24,2164,1579],{"class":42},[24,2166,1600],{"class":38},[24,2168,2169,2171,2173,2175,2177,2179,2181,2183,2185],{"class":26,"line":864},[24,2170,911],{"class":30},[24,2172,775],{"class":34},[24,2174,81],{"class":38},[24,2176,990],{"class":42},[24,2178,75],{"class":38},[24,2180,798],{"class":42},[24,2182,229],{"class":38},[24,2184,1579],{"class":42},[24,2186,234],{"class":38},[24,2188,2189,2191,2193,2195,2197,2199],{"class":26,"line":869},[24,2190,837],{"class":42},[24,2192,75],{"class":38},[24,2194,1634],{"class":62},[24,2196,186],{"class":38},[24,2198,990],{"class":42},[24,2200,722],{"class":38},[24,2202,2203],{"class":26,"line":893},[24,2204,1012],{"class":38},[24,2206,2207,2209,2211,2213,2215,2217,2219],{"class":26,"line":908},[24,2208,1506],{"class":42},[24,2210,75],{"class":38},[24,2212,798],{"class":42},[24,2214,75],{"class":38},[24,2216,1593],{"class":42},[24,2218,81],{"class":38},[24,2220,1661],{"class":49},[24,2222,2223],{"class":26,"line":930},[24,2224,95],{"class":38},[24,2226,2227],{"class":26,"line":944},[24,2228,111],{"emptyLinePlaceholder":110},[24,2230,2231,2233,2235,2237,2239,2241,2243],{"class":26,"line":965},[24,2232,59],{"class":30},[24,2234,63],{"class":62},[24,2236,186],{"class":38},[24,2238,1371],{"class":62},[24,2240,46],{"class":38},[24,2242,474],{"class":34},[24,2244,734],{"class":38},[24,2246,2247,2249,2251,2253,2255,2257,2259],{"class":26,"line":978},[24,2248,1441],{"class":30},[24,2250,996],{"class":62},[24,2252,46],{"class":38},[24,2254,2004],{"class":34},[24,2256,1055],{"class":38},[24,2258,215],{"class":30},[24,2260,218],{"class":38},[24,2262,2263,2265,2267,2269],{"class":26,"line":1002},[24,2264,1474],{"class":62},[24,2266,186],{"class":38},[24,2268,990],{"class":42},[24,2270,722],{"class":38},[24,2272,2273,2275,2277],{"class":26,"line":1009},[24,2274,1485],{"class":42},[24,2276,81],{"class":38},[24,2278,1490],{"class":42},[24,2280,2281,2283],{"class":26,"line":1015},[24,2282,1495],{"class":62},[24,2284,104],{"class":38},[24,2286,2288],{"class":26,"line":2287},28,[24,2289,1012],{"class":38},[24,2291,2293,2295,2297,2299],{"class":26,"line":2292},29,[24,2294,1506],{"class":42},[24,2296,75],{"class":38},[24,2298,798],{"class":42},[24,2300,1513],{"class":38},[24,2302,2304,2306],{"class":26,"line":2303},30,[24,2305,1506],{"class":62},[24,2307,104],{"class":38},[24,2309,2311],{"class":26,"line":2310},31,[24,2312,95],{"class":38},[24,2314,2316],{"class":26,"line":2315},32,[24,2317,111],{"emptyLinePlaceholder":110},[24,2319,2321,2323,2326,2328,2330,2332,2334,2336,2338,2340,2342],{"class":26,"line":2320},33,[24,2322,59],{"class":30},[24,2324,2325],{"class":62}," track",[24,2327,186],{"class":38},[24,2329,360],{"class":202},[24,2331,46],{"class":38},[24,2333,416],{"class":34},[24,2335,206],{"class":38},[24,2337,662],{"class":202},[24,2339,46],{"class":38},[24,2341,445],{"class":34},[24,2343,734],{"class":38},[24,2345,2347],{"class":26,"line":2346},34,[24,2348,2349],{"class":128},"  \u002F\u002F 没有 activeEffect，直接返回\n",[24,2351,2353,2356,2358,2360,2362],{"class":26,"line":2352},35,[24,2354,2355],{"class":30},"  if",[24,2357,681],{"class":38},[24,2359,600],{"class":42},[24,2361,212],{"class":38},[24,2363,941],{"class":30},[24,2365,2367,2370,2372,2374,2376,2378,2380,2382,2384],{"class":26,"line":2366},36,[24,2368,2369],{"class":30},"  let",[24,2371,705],{"class":42},[24,2373,81],{"class":38},[24,2375,710],{"class":42},[24,2377,75],{"class":38},[24,2379,715],{"class":62},[24,2381,186],{"class":38},[24,2383,360],{"class":42},[24,2385,722],{"class":38},[24,2387,2389,2391,2393,2395],{"class":26,"line":2388},37,[24,2390,2355],{"class":30},[24,2392,681],{"class":38},[24,2394,731],{"class":42},[24,2396,734],{"class":38},[24,2398,2400,2403,2405,2407,2409,2411,2413,2415,2417,2419,2421],{"class":26,"line":2399},38,[24,2401,2402],{"class":42},"    bucket",[24,2404,75],{"class":38},[24,2406,744],{"class":62},[24,2408,186],{"class":38},[24,2410,360],{"class":42},[24,2412,751],{"class":38},[24,2414,731],{"class":42},[24,2416,81],{"class":38},[24,2418,180],{"class":30},[24,2420,760],{"class":62},[24,2422,763],{"class":38},[24,2424,2426],{"class":26,"line":2425},39,[24,2427,1012],{"class":38},[24,2429,2431,2433,2435,2437,2439,2441,2443,2445,2447],{"class":26,"line":2430},40,[24,2432,2369],{"class":30},[24,2434,775],{"class":42},[24,2436,81],{"class":38},[24,2438,731],{"class":42},[24,2440,75],{"class":38},[24,2442,715],{"class":62},[24,2444,186],{"class":38},[24,2446,662],{"class":42},[24,2448,722],{"class":38},[24,2450,2452,2454,2456,2458],{"class":26,"line":2451},41,[24,2453,2355],{"class":30},[24,2455,681],{"class":38},[24,2457,798],{"class":42},[24,2459,734],{"class":38},[24,2461,2463,2466,2468,2470,2472,2474,2476,2478,2480,2482,2484],{"class":26,"line":2462},42,[24,2464,2465],{"class":42},"    depsMap",[24,2467,75],{"class":38},[24,2469,744],{"class":62},[24,2471,186],{"class":38},[24,2473,662],{"class":42},[24,2475,751],{"class":38},[24,2477,798],{"class":42},[24,2479,81],{"class":38},[24,2481,180],{"class":30},[24,2483,824],{"class":62},[24,2485,763],{"class":38},[24,2487,2489],{"class":26,"line":2488},43,[24,2490,1012],{"class":38},[24,2492,2494,2497,2499,2501,2503,2505],{"class":26,"line":2493},44,[24,2495,2496],{"class":42},"  deps",[24,2498,75],{"class":38},[24,2500,842],{"class":62},[24,2502,186],{"class":38},[24,2504,600],{"class":42},[24,2506,722],{"class":38},[24,2508,2510,2512,2514,2516,2518,2520,2522,2524],{"class":26,"line":2509},45,[24,2511,1382],{"class":42},[24,2513,75],{"class":38},[24,2515,798],{"class":42},[24,2517,75],{"class":38},[24,2519,1882],{"class":62},[24,2521,186],{"class":38},[24,2523,798],{"class":42},[24,2525,722],{"class":38},[24,2527,2529],{"class":26,"line":2528},46,[24,2530,95],{"class":38},[24,2532,2534],{"class":26,"line":2533},47,[24,2535,111],{"emptyLinePlaceholder":110},[24,2537,2539,2541,2544,2546,2548,2550,2552,2554,2556,2558,2560,2563,2566],{"class":26,"line":2538},48,[24,2540,59],{"class":30},[24,2542,2543],{"class":62}," trigger",[24,2545,186],{"class":38},[24,2547,360],{"class":202},[24,2549,46],{"class":38},[24,2551,416],{"class":34},[24,2553,206],{"class":38},[24,2555,662],{"class":202},[24,2557,46],{"class":38},[24,2559,445],{"class":34},[24,2561,2562],{"class":38},"): ",[24,2564,2565],{"class":34},"void",[24,2567,218],{"class":38},[24,2569,2571,2573,2575,2577,2579,2581,2583,2585,2587],{"class":26,"line":2570},49,[24,2572,1441],{"class":30},[24,2574,705],{"class":34},[24,2576,81],{"class":38},[24,2578,710],{"class":42},[24,2580,75],{"class":38},[24,2582,715],{"class":62},[24,2584,186],{"class":38},[24,2586,360],{"class":42},[24,2588,722],{"class":38},[24,2590,2592,2594,2596,2598,2600],{"class":26,"line":2591},50,[24,2593,2355],{"class":30},[24,2595,681],{"class":38},[24,2597,731],{"class":42},[24,2599,212],{"class":38},[24,2601,941],{"class":30},[24,2603,2605,2607,2609,2611,2613,2615,2617,2619,2621],{"class":26,"line":2604},51,[24,2606,1441],{"class":30},[24,2608,775],{"class":34},[24,2610,81],{"class":38},[24,2612,731],{"class":42},[24,2614,75],{"class":38},[24,2616,715],{"class":62},[24,2618,186],{"class":38},[24,2620,662],{"class":42},[24,2622,722],{"class":38},[24,2624,2626,2628,2630,2632,2634],{"class":26,"line":2625},52,[24,2627,2355],{"class":30},[24,2629,681],{"class":38},[24,2631,798],{"class":42},[24,2633,212],{"class":38},[24,2635,941],{"class":30},[24,2637,2639,2641,2643,2645,2647,2649,2651,2653],{"class":26,"line":2638},53,[24,2640,2496],{"class":42},[24,2642,75],{"class":38},[24,2644,985],{"class":62},[24,2646,186],{"class":38},[24,2648,990],{"class":202},[24,2650,993],{"class":30},[24,2652,996],{"class":62},[24,2654,999],{"class":38},[24,2656,2658],{"class":26,"line":2657},54,[24,2659,95],{"class":38},[24,2661,2663],{"class":26,"line":2662},55,[24,2664,111],{"emptyLinePlaceholder":110},[24,2666,2668,2670,2672,2674,2676,2678,2680,2682],{"class":26,"line":2667},56,[24,2669,31],{"class":30},[24,2671,175],{"class":34},[24,2673,81],{"class":38},[24,2675,180],{"class":30},[24,2677,183],{"class":62},[24,2679,186],{"class":38},[24,2681,84],{"class":42},[24,2683,191],{"class":38},[24,2685,2687,2689,2691,2693,2695,2697,2699,2701,2703,2705],{"class":26,"line":2686},57,[24,2688,196],{"class":62},[24,2690,199],{"class":38},[24,2692,360],{"class":202},[24,2694,206],{"class":38},[24,2696,662],{"class":202},[24,2698,46],{"class":38},[24,2700,445],{"class":34},[24,2702,212],{"class":38},[24,2704,215],{"class":30},[24,2706,218],{"class":38},[24,2708,2710,2713,2715,2717,2719,2721],{"class":26,"line":2709},58,[24,2711,2712],{"class":62},"    track",[24,2714,186],{"class":38},[24,2716,360],{"class":42},[24,2718,206],{"class":38},[24,2720,662],{"class":42},[24,2722,722],{"class":38},[24,2724,2726,2728,2730,2732,2734],{"class":26,"line":2725},59,[24,2727,223],{"class":30},[24,2729,691],{"class":42},[24,2731,229],{"class":38},[24,2733,662],{"class":42},[24,2735,234],{"class":38},[24,2737,2739],{"class":26,"line":2738},60,[24,2740,239],{"class":38},[24,2742,2744,2746,2748,2750,2752,2754,2756,2758,2760,2762,2764,2766],{"class":26,"line":2743},61,[24,2745,244],{"class":62},[24,2747,199],{"class":38},[24,2749,360],{"class":202},[24,2751,206],{"class":38},[24,2753,662],{"class":202},[24,2755,46],{"class":38},[24,2757,445],{"class":34},[24,2759,206],{"class":38},[24,2761,884],{"class":202},[24,2763,212],{"class":38},[24,2765,215],{"class":30},[24,2767,218],{"class":38},[24,2769,2771,2773,2775,2777,2779],{"class":26,"line":2770},62,[24,2772,896],{"class":42},[24,2774,229],{"class":38},[24,2776,662],{"class":42},[24,2778,275],{"class":38},[24,2780,905],{"class":42},[24,2782,2784,2787,2789,2791,2793,2795],{"class":26,"line":2783},63,[24,2785,2786],{"class":62},"    trigger",[24,2788,186],{"class":38},[24,2790,360],{"class":42},[24,2792,206],{"class":38},[24,2794,662],{"class":42},[24,2796,722],{"class":38},[24,2798,2800,2802],{"class":26,"line":2799},64,[24,2801,223],{"class":30},[24,2803,286],{"class":49},[24,2805,2807],{"class":26,"line":2806},65,[24,2808,1012],{"class":38},[24,2810,2812],{"class":26,"line":2811},66,[24,2813,297],{"class":38},[24,2815,2817],{"class":26,"line":2816},67,[24,2818,111],{"emptyLinePlaceholder":110},[24,2820,2822,2824,2827,2829],{"class":26,"line":2821},68,[24,2823,101],{"class":62},[24,2825,2826],{"class":38},"(() ",[24,2828,215],{"class":30},[24,2830,218],{"class":38},[24,2832,2834,2836,2838,2840,2842,2844,2846,2848,2850,2852,2854,2856,2858],{"class":26,"line":2833},69,[24,2835,72],{"class":42},[24,2837,75],{"class":38},[24,2839,78],{"class":42},[24,2841,81],{"class":38},[24,2843,308],{"class":42},[24,2845,75],{"class":38},[24,2847,1199],{"class":42},[24,2849,1245],{"class":30},[24,2851,175],{"class":42},[24,2853,75],{"class":38},[24,2855,43],{"class":42},[24,2857,1254],{"class":30},[24,2859,1257],{"class":49},[24,2861,2863],{"class":26,"line":2862},70,[24,2864,297],{"class":38},[10,2866,2867,2868,2870,2871,2874,2875,2877,2878,2880,2881,2883,2884,2886],{},"此时，执行代码会进入死循环。原因是在",[21,2869,1932],{},"中执行",[21,2872,2873],{},"deps.forEach","语句时，执行",[21,2876,990],{},"会触发",[21,2879,1414],{},"，试图将当前执行的副作用函数从",[21,2882,798],{},"中移除；但随后，副作用函数的执行又会导致触发 getter，从而重新收集依赖，又将当前副作用函数添加到",[21,2885,798],{},"中。",[10,2888,2889,2890,2892,2893,2895],{},"解决的方法是在",[21,2891,1932],{},"中依次调用副作用函数前，先构造一个新的集合，将",[21,2894,798],{},"中的副作用函数复制到新集合中，然后遍历新集合执行副作用函数。",[10,2897,2898,2899,2901],{},"修改过的",[21,2900,1932],{},"函数如下：",[14,2903,2905],{"className":389,"code":2904,"language":391,"meta":19,"style":19},"function trigger(target: object, key: PropertyKey): void {\n  const depsMap = bucket.get(target)\n  if (!depsMap) return\n  const deps = depsMap.get(key)\n  if (!deps) return\n  \u002F\u002F 新增：构造新集合，避免触发时修改 deps 导致死循环\n  const effectsToRun = new Set(deps)\n  effectsToRun.forEach(effectFn => effectFn())\n}\n",[21,2906,2907,2935,2955,2967,2987,2999,3004,3023,3042],{"__ignoreMap":19},[24,2908,2909,2911,2913,2915,2917,2919,2921,2923,2925,2927,2929,2931,2933],{"class":26,"line":27},[24,2910,59],{"class":30},[24,2912,2543],{"class":62},[24,2914,186],{"class":38},[24,2916,360],{"class":202},[24,2918,46],{"class":38},[24,2920,416],{"class":34},[24,2922,206],{"class":38},[24,2924,662],{"class":202},[24,2926,46],{"class":38},[24,2928,445],{"class":34},[24,2930,2562],{"class":38},[24,2932,2565],{"class":34},[24,2934,218],{"class":38},[24,2936,2937,2939,2941,2943,2945,2947,2949,2951,2953],{"class":26,"line":56},[24,2938,1441],{"class":30},[24,2940,705],{"class":34},[24,2942,81],{"class":38},[24,2944,710],{"class":42},[24,2946,75],{"class":38},[24,2948,715],{"class":62},[24,2950,186],{"class":38},[24,2952,360],{"class":42},[24,2954,722],{"class":38},[24,2956,2957,2959,2961,2963,2965],{"class":26,"line":69},[24,2958,2355],{"class":30},[24,2960,681],{"class":38},[24,2962,731],{"class":42},[24,2964,212],{"class":38},[24,2966,941],{"class":30},[24,2968,2969,2971,2973,2975,2977,2979,2981,2983,2985],{"class":26,"line":92},[24,2970,1441],{"class":30},[24,2972,775],{"class":34},[24,2974,81],{"class":38},[24,2976,731],{"class":42},[24,2978,75],{"class":38},[24,2980,715],{"class":62},[24,2982,186],{"class":38},[24,2984,662],{"class":42},[24,2986,722],{"class":38},[24,2988,2989,2991,2993,2995,2997],{"class":26,"line":98},[24,2990,2355],{"class":30},[24,2992,681],{"class":38},[24,2994,798],{"class":42},[24,2996,212],{"class":38},[24,2998,941],{"class":30},[24,3000,3001],{"class":26,"line":107},[24,3002,3003],{"class":128},"  \u002F\u002F 新增：构造新集合，避免触发时修改 deps 导致死循环\n",[24,3005,3006,3008,3011,3013,3015,3017,3019,3021],{"class":26,"line":114},[24,3007,1441],{"class":30},[24,3009,3010],{"class":34}," effectsToRun",[24,3012,81],{"class":38},[24,3014,180],{"class":30},[24,3016,824],{"class":62},[24,3018,186],{"class":38},[24,3020,798],{"class":42},[24,3022,722],{"class":38},[24,3024,3025,3028,3030,3032,3034,3036,3038,3040],{"class":26,"line":281},[24,3026,3027],{"class":42},"  effectsToRun",[24,3029,75],{"class":38},[24,3031,985],{"class":62},[24,3033,186],{"class":38},[24,3035,990],{"class":202},[24,3037,993],{"class":30},[24,3039,996],{"class":62},[24,3041,999],{"class":38},[24,3043,3044],{"class":26,"line":289},[24,3045,95],{"class":38},[10,3047,3048,3049,3051,3052,3054],{},"经过调整后的响应式系统，在更改",[21,3050,1283],{},"后，无论",[21,3053,1270],{},"的值被设置为几，都不会再次触发副作用函数的运行了。",[131,3056,3058],{"id":3057},"解决无限循环again","解决无限循环（again）",[10,3060,3061],{},"与上面提到的依赖集合被反复修改类似，还有一种情况也会造成无限循环。考虑下面的副作用：",[14,3063,3065],{"className":389,"code":3064,"language":391,"meta":19,"style":19},"effect(() => {\n  proxyObj.count++\n})\n",[21,3066,3067,3077,3089],{"__ignoreMap":19},[24,3068,3069,3071,3073,3075],{"class":26,"line":27},[24,3070,101],{"class":62},[24,3072,2826],{"class":38},[24,3074,215],{"class":30},[24,3076,218],{"class":38},[24,3078,3079,3082,3084,3086],{"class":26,"line":56},[24,3080,3081],{"class":42},"  proxyObj",[24,3083,75],{"class":38},[24,3085,43],{"class":42},[24,3087,3088],{"class":38},"++\n",[24,3090,3091],{"class":26,"line":69},[24,3092,297],{"class":38},[10,3094,3095,3096,3099,3100,3102,3103,3105,3106,3108,3109,3111,3112,3114,3115,3117,3118,3120],{},"自增操作相当于",[21,3097,3098],{},"proxyObj.count = proxyObj.count + 1","。在这个语句中，同时包含了对",[21,3101,308],{},"的",[21,3104,43],{},"属性的读取和写入。当读取",[21,3107,1270],{},"时，会触发",[21,3110,1928],{},"收集依赖；然后，将",[21,3113,1270],{},"的值增加 1 并赋给",[21,3116,1270],{},"，会触发",[21,3119,1932],{},"执行副作用函数本身。但此时，副作用函数正在执行中，尚未执行完毕就触发了下一次副作用函数的执行，从而无限递归地调用自己。",[10,3122,3123,3124,3126],{},"想要避免第二次调用，需要在执行副作用函数的",[21,3125,1932],{},"中增加守卫：如果需要执行的副作用函数与当前正在执行的副作用函数相同，则不执行，即：",[14,3128,3130],{"className":389,"code":3129,"language":391,"meta":19,"style":19},"function trigger(target: object, key: PropertyKey): void {\n  const depsMap = bucket.get(target)\n  if (!depsMap) return\n  const deps = depsMap.get(key)\n  if (!deps) return\n  \u002F\u002F 新增：构造新集合，避免触发时修改 deps 导致死循环\n  const effectsToRun = new Set\u003CEffectFn>()\n  deps.forEach(effectFn => {\n    if (effectFn !== activeEffect) {\n      effectsToRun.add(effectFn)\n    }\n  })\n  effectsToRun.forEach(effectFn => effectFn())\n}\n",[21,3131,3132,3160,3180,3192,3212,3224,3228,3247,3263,3278,3293,3297,3302,3320],{"__ignoreMap":19},[24,3133,3134,3136,3138,3140,3142,3144,3146,3148,3150,3152,3154,3156,3158],{"class":26,"line":27},[24,3135,59],{"class":30},[24,3137,2543],{"class":62},[24,3139,186],{"class":38},[24,3141,360],{"class":202},[24,3143,46],{"class":38},[24,3145,416],{"class":34},[24,3147,206],{"class":38},[24,3149,662],{"class":202},[24,3151,46],{"class":38},[24,3153,445],{"class":34},[24,3155,2562],{"class":38},[24,3157,2565],{"class":34},[24,3159,218],{"class":38},[24,3161,3162,3164,3166,3168,3170,3172,3174,3176,3178],{"class":26,"line":56},[24,3163,1441],{"class":30},[24,3165,705],{"class":34},[24,3167,81],{"class":38},[24,3169,710],{"class":42},[24,3171,75],{"class":38},[24,3173,715],{"class":62},[24,3175,186],{"class":38},[24,3177,360],{"class":42},[24,3179,722],{"class":38},[24,3181,3182,3184,3186,3188,3190],{"class":26,"line":69},[24,3183,2355],{"class":30},[24,3185,681],{"class":38},[24,3187,731],{"class":42},[24,3189,212],{"class":38},[24,3191,941],{"class":30},[24,3193,3194,3196,3198,3200,3202,3204,3206,3208,3210],{"class":26,"line":92},[24,3195,1441],{"class":30},[24,3197,775],{"class":34},[24,3199,81],{"class":38},[24,3201,731],{"class":42},[24,3203,75],{"class":38},[24,3205,715],{"class":62},[24,3207,186],{"class":38},[24,3209,662],{"class":42},[24,3211,722],{"class":38},[24,3213,3214,3216,3218,3220,3222],{"class":26,"line":98},[24,3215,2355],{"class":30},[24,3217,681],{"class":38},[24,3219,798],{"class":42},[24,3221,212],{"class":38},[24,3223,941],{"class":30},[24,3225,3226],{"class":26,"line":107},[24,3227,3003],{"class":128},[24,3229,3230,3232,3234,3236,3238,3240,3242,3244],{"class":26,"line":114},[24,3231,1441],{"class":30},[24,3233,3010],{"class":34},[24,3235,81],{"class":38},[24,3237,180],{"class":30},[24,3239,824],{"class":62},[24,3241,413],{"class":38},[24,3243,2004],{"class":34},[24,3245,3246],{"class":38},">()\n",[24,3248,3249,3251,3253,3255,3257,3259,3261],{"class":26,"line":281},[24,3250,2496],{"class":42},[24,3252,75],{"class":38},[24,3254,985],{"class":62},[24,3256,186],{"class":38},[24,3258,990],{"class":202},[24,3260,993],{"class":30},[24,3262,218],{"class":38},[24,3264,3265,3267,3269,3271,3274,3276],{"class":26,"line":289},[24,3266,678],{"class":30},[24,3268,1563],{"class":38},[24,3270,990],{"class":42},[24,3272,3273],{"class":38}," !== ",[24,3275,600],{"class":42},[24,3277,734],{"class":38},[24,3279,3280,3283,3285,3287,3289,3291],{"class":26,"line":294},[24,3281,3282],{"class":42},"      effectsToRun",[24,3284,75],{"class":38},[24,3286,842],{"class":62},[24,3288,186],{"class":38},[24,3290,990],{"class":42},[24,3292,722],{"class":38},[24,3294,3295],{"class":26,"line":300},[24,3296,768],{"class":38},[24,3298,3299],{"class":26,"line":305},[24,3300,3301],{"class":38},"  })\n",[24,3303,3304,3306,3308,3310,3312,3314,3316,3318],{"class":26,"line":320},[24,3305,3027],{"class":42},[24,3307,75],{"class":38},[24,3309,985],{"class":62},[24,3311,186],{"class":38},[24,3313,990],{"class":202},[24,3315,993],{"class":30},[24,3317,996],{"class":62},[24,3319,999],{"class":38},[24,3321,3322],{"class":26,"line":829},[24,3323,95],{"class":38},[131,3325,3326],{"id":3326},"嵌套的副作用",[10,3328,3329,3330,3332],{},"在目前为止的例子中，副作用以全局变量",[21,3331,600],{},"的方式存在。但在实际场景中，副作用是应当支持嵌套的。例如，一个父组件的渲染过程中渲染了子组件，就发生了副作用的嵌套。",[10,3334,3335],{},"嵌套的副作用函数看上去是这样的：",[14,3337,3339],{"className":389,"code":3338,"language":391,"meta":19,"style":19},"effect(function effectFn1() {\n  console.log('effectFn1 run')\n  effect(function effectFn2() {\n    console.log('effectFn2 run')\n    el.innerText = obj.foo\n  })\n  el.innerText = obj.bar\n})\n",[21,3340,3341,3354,3369,3383,3399,3417,3421,3438],{"__ignoreMap":19},[24,3342,3343,3345,3347,3349,3352],{"class":26,"line":27},[24,3344,101],{"class":62},[24,3346,186],{"class":38},[24,3348,59],{"class":30},[24,3350,3351],{"class":62}," effectFn1",[24,3353,66],{"class":38},[24,3355,3356,3358,3360,3362,3364,3367],{"class":26,"line":56},[24,3357,1064],{"class":42},[24,3359,75],{"class":38},[24,3361,328],{"class":62},[24,3363,186],{"class":38},[24,3365,3366],{"class":49},"'effectFn1 run'",[24,3368,722],{"class":38},[24,3370,3371,3374,3376,3378,3381],{"class":26,"line":69},[24,3372,3373],{"class":62},"  effect",[24,3375,186],{"class":38},[24,3377,59],{"class":30},[24,3379,3380],{"class":62}," effectFn2",[24,3382,66],{"class":38},[24,3384,3385,3388,3390,3392,3394,3397],{"class":26,"line":92},[24,3386,3387],{"class":42},"    console",[24,3389,75],{"class":38},[24,3391,328],{"class":62},[24,3393,186],{"class":38},[24,3395,3396],{"class":49},"'effectFn2 run'",[24,3398,722],{"class":38},[24,3400,3401,3404,3406,3408,3410,3412,3414],{"class":26,"line":98},[24,3402,3403],{"class":42},"    el",[24,3405,75],{"class":38},[24,3407,78],{"class":42},[24,3409,81],{"class":38},[24,3411,84],{"class":42},[24,3413,75],{"class":38},[24,3415,3416],{"class":42},"foo\n",[24,3418,3419],{"class":26,"line":107},[24,3420,3301],{"class":38},[24,3422,3423,3425,3427,3429,3431,3433,3435],{"class":26,"line":114},[24,3424,72],{"class":42},[24,3426,75],{"class":38},[24,3428,78],{"class":42},[24,3430,81],{"class":38},[24,3432,84],{"class":42},[24,3434,75],{"class":38},[24,3436,3437],{"class":42},"bar\n",[24,3439,3440],{"class":26,"line":281},[24,3441,297],{"class":38},[10,3443,3444,3445,3447,3448,3450,3451,3453,3454,3457],{},"假设以这个嵌套的副作用函数为例，当外层的副作用执行时，",[21,3446,600],{},"的值被修改为 effectFn1；当执行内侧的副作用时，",[21,3449,600],{},"的值被修改为 effectFn2。但当执行完内侧副作用、返回外层继续执行 effectFn1 时，",[21,3452,600],{},"的值并不会重新恢复到 effectFn1。这意味着当修改",[21,3455,3456],{},"obj.bar","时，重新执行的副作用还是 effectFn2 而非预期中的 effectFn1。",[10,3459,3460,3461,3463],{},"要支持嵌套的副作用，显然需要使用栈结构来存储当前正在执行的副作用函数，将",[21,3462,600],{},"指向栈顶元素。当副作用函数执行时压入栈中，当执行完成后进行出栈。",[14,3465,3467],{"className":389,"code":3466,"language":391,"meta":19,"style":19},"let activeEffect: EffectFn\nconst effectStack: EffectFn[] = []\n\nfunction effect(fn: Function) {\n  const effectFn = () => {\n    cleanup(effectFn)\n    activeEffect = effectFn\n    effectStack.push(effectFn)\n    fn()\n    effectStack.pop()\n    activeEffect = effectStack[effectStack.length - 1]\n  }\n  effectFn.deps = []\n  effectFn()\n}\n",[21,3468,3469,3479,3493,3497,3513,3525,3535,3543,3558,3564,3575,3599,3603,3613,3619],{"__ignoreMap":19},[24,3470,3471,3473,3475,3477],{"class":26,"line":27},[24,3472,1566],{"class":30},[24,3474,1052],{"class":42},[24,3476,46],{"class":38},[24,3478,2066],{"class":34},[24,3480,3481,3483,3486,3488,3490],{"class":26,"line":56},[24,3482,31],{"class":30},[24,3484,3485],{"class":34}," effectStack",[24,3487,46],{"class":38},[24,3489,2004],{"class":34},[24,3491,3492],{"class":38},"[] = []\n",[24,3494,3495],{"class":26,"line":69},[24,3496,111],{"emptyLinePlaceholder":110},[24,3498,3499,3501,3503,3505,3507,3509,3511],{"class":26,"line":92},[24,3500,59],{"class":30},[24,3502,63],{"class":62},[24,3504,186],{"class":38},[24,3506,1371],{"class":62},[24,3508,46],{"class":38},[24,3510,474],{"class":34},[24,3512,734],{"class":38},[24,3514,3515,3517,3519,3521,3523],{"class":26,"line":98},[24,3516,1441],{"class":30},[24,3518,996],{"class":62},[24,3520,1055],{"class":38},[24,3522,215],{"class":30},[24,3524,218],{"class":38},[24,3526,3527,3529,3531,3533],{"class":26,"line":107},[24,3528,1474],{"class":62},[24,3530,186],{"class":38},[24,3532,990],{"class":42},[24,3534,722],{"class":38},[24,3536,3537,3539,3541],{"class":26,"line":114},[24,3538,1485],{"class":42},[24,3540,81],{"class":38},[24,3542,1490],{"class":42},[24,3544,3545,3548,3550,3552,3554,3556],{"class":26,"line":281},[24,3546,3547],{"class":42},"    effectStack",[24,3549,75],{"class":38},[24,3551,1882],{"class":62},[24,3553,186],{"class":38},[24,3555,990],{"class":42},[24,3557,722],{"class":38},[24,3559,3560,3562],{"class":26,"line":289},[24,3561,1495],{"class":62},[24,3563,104],{"class":38},[24,3565,3566,3568,3570,3573],{"class":26,"line":294},[24,3567,3547],{"class":42},[24,3569,75],{"class":38},[24,3571,3572],{"class":62},"pop",[24,3574,104],{"class":38},[24,3576,3577,3579,3581,3584,3586,3588,3590,3592,3595,3597],{"class":26,"line":300},[24,3578,1485],{"class":42},[24,3580,81],{"class":38},[24,3582,3583],{"class":42},"effectStack",[24,3585,229],{"class":38},[24,3587,3583],{"class":42},[24,3589,75],{"class":38},[24,3591,1593],{"class":42},[24,3593,3594],{"class":38}," - ",[24,3596,1147],{"class":49},[24,3598,234],{"class":38},[24,3600,3601],{"class":26,"line":305},[24,3602,1012],{"class":38},[24,3604,3605,3607,3609,3611],{"class":26,"line":320},[24,3606,1506],{"class":42},[24,3608,75],{"class":38},[24,3610,798],{"class":42},[24,3612,1513],{"class":38},[24,3614,3615,3617],{"class":26,"line":829},[24,3616,1506],{"class":62},[24,3618,104],{"class":38},[24,3620,3621],{"class":26,"line":834},[24,3622,95],{"class":38},[131,3624,3625],{"id":3625},"目前为止的完整代码",[14,3627,3629],{"className":389,"code":3628,"language":391,"meta":19,"style":19},"\u002F\u002F 全局存储桶，保存每个对象的依赖关系\ntype Bucket = WeakMap\u003Cobject, DepsMap>\n\u002F\u002F 响应式对象中，每个属性和其对应的副作用函数集合的依赖关系表\ntype DepsMap = Map\u003CPropertyKey, Deps>\n\u002F\u002F 每个属性的副作用函数集合\ntype Deps = Set\u003CEffectFn>\n\u002F\u002F 副作用函数。新增`deps`存储包含该副作用的所有依赖集合\ntype EffectFn = Function & { deps: Deps[] }\n\nconst bucket: Bucket = new WeakMap()\nlet activeEffect: EffectFn\nconst effectStack: EffectFn[] = []\n\nconst obj: Record\u003CPropertyKey, any> = { count: 0, enabled: true }\n\nfunction cleanup(effectFn: EffectFn) {\n  for (let i = 0; i \u003C effectFn.deps.length; i++) {\n    const deps = effectFn.deps[i]\n    deps.delete(effectFn)\n  }\n  effectFn.deps.length = 0\n}\n\nfunction effect(fn: Function) {\n  const effectFn: EffectFn = () => {\n    cleanup(effectFn)\n    activeEffect = effectFn\n    effectStack.push(effectFn)\n    fn()\n    effectStack.pop()\n    activeEffect = effectStack[effectStack.length - 1]\n  }\n  effectFn.deps = []\n  effectFn()\n}\n\nfunction track(target: object, key: PropertyKey) {\n  if (!activeEffect) return\n  let depsMap = bucket.get(target)\n  if (!depsMap) {\n    bucket.set(target, (depsMap = new Map()))\n  }\n  let deps = depsMap.get(key)\n  if (!deps) {\n    depsMap.set(key, (deps = new Set()))\n  }\n  deps.add(activeEffect)\n  activeEffect.deps.push(deps)\n}\n\nfunction trigger(target: object, key: PropertyKey): void {\n  const depsMap = bucket.get(target)\n  if (!depsMap) return\n  const deps = depsMap.get(key)\n  if (!deps) return\n  const effectsToRun = new Set\u003CEffectFn>()\n  deps.forEach((effectFn) => {\n    if (effectFn !== activeEffect) {\n      effectsToRun.add(effectFn)\n    }\n  })\n  effectsToRun.forEach((effectFn) => effectFn())\n}\n\nconst proxyObj = new Proxy(obj, {\n  get: (target, key: PropertyKey) => {\n    track(target, key)\n    return target[key]\n  },\n  set: (target, key: PropertyKey, value) => {\n    target[key] = value\n    trigger(target, key)\n    return true\n  }\n})\n",[21,3630,3631,3635,3655,3659,3679,3683,3699,3703,3723,3727,3745,3755,3767,3771,3807,3811,3827,3863,3883,3897,3901,3917,3921,3925,3941,3957,3967,3975,3989,3995,4005,4027,4031,4041,4047,4051,4055,4079,4091,4111,4121,4145,4149,4169,4179,4203,4207,4221,4239,4243,4247,4275,4295,4307,4327,4339,4357,4376,4390,4404,4408,4412,4432,4436,4440,4458,4480,4494,4506,4510,4536,4549,4564,4571,4576],{"__ignoreMap":19},[24,3632,3633],{"class":26,"line":27},[24,3634,398],{"class":128},[24,3636,3637,3639,3641,3643,3645,3647,3649,3651,3653],{"class":26,"line":56},[24,3638,403],{"class":30},[24,3640,406],{"class":34},[24,3642,81],{"class":38},[24,3644,382],{"class":34},[24,3646,413],{"class":38},[24,3648,416],{"class":34},[24,3650,206],{"class":38},[24,3652,421],{"class":34},[24,3654,424],{"class":38},[24,3656,3657],{"class":26,"line":69},[24,3658,429],{"class":128},[24,3660,3661,3663,3665,3667,3669,3671,3673,3675,3677],{"class":26,"line":92},[24,3662,403],{"class":30},[24,3664,436],{"class":34},[24,3666,81],{"class":38},[24,3668,356],{"class":34},[24,3670,413],{"class":38},[24,3672,445],{"class":34},[24,3674,206],{"class":38},[24,3676,450],{"class":34},[24,3678,424],{"class":38},[24,3680,3681],{"class":26,"line":98},[24,3682,457],{"class":128},[24,3684,3685,3687,3689,3691,3693,3695,3697],{"class":26,"line":107},[24,3686,403],{"class":30},[24,3688,464],{"class":34},[24,3690,81],{"class":38},[24,3692,469],{"class":34},[24,3694,413],{"class":38},[24,3696,2004],{"class":34},[24,3698,424],{"class":38},[24,3700,3701],{"class":26,"line":114},[24,3702,2011],{"class":128},[24,3704,3705,3707,3709,3711,3713,3715,3717,3719,3721],{"class":26,"line":281},[24,3706,403],{"class":30},[24,3708,2018],{"class":34},[24,3710,81],{"class":38},[24,3712,474],{"class":34},[24,3714,1451],{"class":38},[24,3716,798],{"class":42},[24,3718,46],{"class":38},[24,3720,450],{"class":34},[24,3722,2033],{"class":38},[24,3724,3725],{"class":26,"line":289},[24,3726,111],{"emptyLinePlaceholder":110},[24,3728,3729,3731,3733,3735,3737,3739,3741,3743],{"class":26,"line":294},[24,3730,31],{"class":30},[24,3732,613],{"class":34},[24,3734,46],{"class":38},[24,3736,618],{"class":34},[24,3738,81],{"class":38},[24,3740,180],{"class":30},[24,3742,625],{"class":62},[24,3744,104],{"class":38},[24,3746,3747,3749,3751,3753],{"class":26,"line":300},[24,3748,1566],{"class":30},[24,3750,1052],{"class":42},[24,3752,46],{"class":38},[24,3754,2066],{"class":34},[24,3756,3757,3759,3761,3763,3765],{"class":26,"line":305},[24,3758,31],{"class":30},[24,3760,3485],{"class":34},[24,3762,46],{"class":38},[24,3764,2004],{"class":34},[24,3766,3492],{"class":38},[24,3768,3769],{"class":26,"line":320},[24,3770,111],{"emptyLinePlaceholder":110},[24,3772,3773,3775,3777,3779,3781,3783,3785,3787,3789,3791,3793,3795,3797,3799,3801,3803,3805],{"class":26,"line":829},[24,3774,31],{"class":30},[24,3776,35],{"class":34},[24,3778,46],{"class":38},[24,3780,2081],{"class":34},[24,3782,413],{"class":38},[24,3784,445],{"class":34},[24,3786,206],{"class":38},[24,3788,2091],{"class":34},[24,3790,2094],{"class":38},[24,3792,43],{"class":42},[24,3794,46],{"class":38},[24,3796,50],{"class":49},[24,3798,206],{"class":38},[24,3800,1199],{"class":42},[24,3802,46],{"class":38},[24,3804,1204],{"class":49},[24,3806,53],{"class":38},[24,3808,3809],{"class":26,"line":834},[24,3810,111],{"emptyLinePlaceholder":110},[24,3812,3813,3815,3817,3819,3821,3823,3825],{"class":26,"line":851},[24,3814,59],{"class":30},[24,3816,1536],{"class":62},[24,3818,186],{"class":38},[24,3820,990],{"class":202},[24,3822,46],{"class":38},[24,3824,2004],{"class":34},[24,3826,734],{"class":38},[24,3828,3829,3831,3833,3835,3837,3839,3841,3843,3845,3847,3849,3851,3853,3855,3857,3859,3861],{"class":26,"line":864},[24,3830,1560],{"class":30},[24,3832,1563],{"class":38},[24,3834,1566],{"class":30},[24,3836,1569],{"class":42},[24,3838,81],{"class":38},[24,3840,50],{"class":49},[24,3842,1576],{"class":38},[24,3844,1579],{"class":42},[24,3846,1582],{"class":38},[24,3848,990],{"class":42},[24,3850,75],{"class":38},[24,3852,798],{"class":42},[24,3854,75],{"class":38},[24,3856,1593],{"class":42},[24,3858,1576],{"class":38},[24,3860,1579],{"class":42},[24,3862,1600],{"class":38},[24,3864,3865,3867,3869,3871,3873,3875,3877,3879,3881],{"class":26,"line":869},[24,3866,911],{"class":30},[24,3868,775],{"class":34},[24,3870,81],{"class":38},[24,3872,990],{"class":42},[24,3874,75],{"class":38},[24,3876,798],{"class":42},[24,3878,229],{"class":38},[24,3880,1579],{"class":42},[24,3882,234],{"class":38},[24,3884,3885,3887,3889,3891,3893,3895],{"class":26,"line":893},[24,3886,837],{"class":42},[24,3888,75],{"class":38},[24,3890,1634],{"class":62},[24,3892,186],{"class":38},[24,3894,990],{"class":42},[24,3896,722],{"class":38},[24,3898,3899],{"class":26,"line":908},[24,3900,1012],{"class":38},[24,3902,3903,3905,3907,3909,3911,3913,3915],{"class":26,"line":930},[24,3904,1506],{"class":42},[24,3906,75],{"class":38},[24,3908,798],{"class":42},[24,3910,75],{"class":38},[24,3912,1593],{"class":42},[24,3914,81],{"class":38},[24,3916,1661],{"class":49},[24,3918,3919],{"class":26,"line":944},[24,3920,95],{"class":38},[24,3922,3923],{"class":26,"line":965},[24,3924,111],{"emptyLinePlaceholder":110},[24,3926,3927,3929,3931,3933,3935,3937,3939],{"class":26,"line":978},[24,3928,59],{"class":30},[24,3930,63],{"class":62},[24,3932,186],{"class":38},[24,3934,1371],{"class":62},[24,3936,46],{"class":38},[24,3938,474],{"class":34},[24,3940,734],{"class":38},[24,3942,3943,3945,3947,3949,3951,3953,3955],{"class":26,"line":1002},[24,3944,1441],{"class":30},[24,3946,996],{"class":62},[24,3948,46],{"class":38},[24,3950,2004],{"class":34},[24,3952,1055],{"class":38},[24,3954,215],{"class":30},[24,3956,218],{"class":38},[24,3958,3959,3961,3963,3965],{"class":26,"line":1009},[24,3960,1474],{"class":62},[24,3962,186],{"class":38},[24,3964,990],{"class":42},[24,3966,722],{"class":38},[24,3968,3969,3971,3973],{"class":26,"line":1015},[24,3970,1485],{"class":42},[24,3972,81],{"class":38},[24,3974,1490],{"class":42},[24,3976,3977,3979,3981,3983,3985,3987],{"class":26,"line":2287},[24,3978,3547],{"class":42},[24,3980,75],{"class":38},[24,3982,1882],{"class":62},[24,3984,186],{"class":38},[24,3986,990],{"class":42},[24,3988,722],{"class":38},[24,3990,3991,3993],{"class":26,"line":2292},[24,3992,1495],{"class":62},[24,3994,104],{"class":38},[24,3996,3997,3999,4001,4003],{"class":26,"line":2303},[24,3998,3547],{"class":42},[24,4000,75],{"class":38},[24,4002,3572],{"class":62},[24,4004,104],{"class":38},[24,4006,4007,4009,4011,4013,4015,4017,4019,4021,4023,4025],{"class":26,"line":2310},[24,4008,1485],{"class":42},[24,4010,81],{"class":38},[24,4012,3583],{"class":42},[24,4014,229],{"class":38},[24,4016,3583],{"class":42},[24,4018,75],{"class":38},[24,4020,1593],{"class":42},[24,4022,3594],{"class":38},[24,4024,1147],{"class":49},[24,4026,234],{"class":38},[24,4028,4029],{"class":26,"line":2315},[24,4030,1012],{"class":38},[24,4032,4033,4035,4037,4039],{"class":26,"line":2320},[24,4034,1506],{"class":42},[24,4036,75],{"class":38},[24,4038,798],{"class":42},[24,4040,1513],{"class":38},[24,4042,4043,4045],{"class":26,"line":2346},[24,4044,1506],{"class":62},[24,4046,104],{"class":38},[24,4048,4049],{"class":26,"line":2352},[24,4050,95],{"class":38},[24,4052,4053],{"class":26,"line":2366},[24,4054,111],{"emptyLinePlaceholder":110},[24,4056,4057,4059,4061,4063,4065,4067,4069,4071,4073,4075,4077],{"class":26,"line":2388},[24,4058,59],{"class":30},[24,4060,2325],{"class":62},[24,4062,186],{"class":38},[24,4064,360],{"class":202},[24,4066,46],{"class":38},[24,4068,416],{"class":34},[24,4070,206],{"class":38},[24,4072,662],{"class":202},[24,4074,46],{"class":38},[24,4076,445],{"class":34},[24,4078,734],{"class":38},[24,4080,4081,4083,4085,4087,4089],{"class":26,"line":2399},[24,4082,2355],{"class":30},[24,4084,681],{"class":38},[24,4086,600],{"class":42},[24,4088,212],{"class":38},[24,4090,941],{"class":30},[24,4092,4093,4095,4097,4099,4101,4103,4105,4107,4109],{"class":26,"line":2425},[24,4094,2369],{"class":30},[24,4096,705],{"class":42},[24,4098,81],{"class":38},[24,4100,710],{"class":42},[24,4102,75],{"class":38},[24,4104,715],{"class":62},[24,4106,186],{"class":38},[24,4108,360],{"class":42},[24,4110,722],{"class":38},[24,4112,4113,4115,4117,4119],{"class":26,"line":2430},[24,4114,2355],{"class":30},[24,4116,681],{"class":38},[24,4118,731],{"class":42},[24,4120,734],{"class":38},[24,4122,4123,4125,4127,4129,4131,4133,4135,4137,4139,4141,4143],{"class":26,"line":2451},[24,4124,2402],{"class":42},[24,4126,75],{"class":38},[24,4128,744],{"class":62},[24,4130,186],{"class":38},[24,4132,360],{"class":42},[24,4134,751],{"class":38},[24,4136,731],{"class":42},[24,4138,81],{"class":38},[24,4140,180],{"class":30},[24,4142,760],{"class":62},[24,4144,763],{"class":38},[24,4146,4147],{"class":26,"line":2462},[24,4148,1012],{"class":38},[24,4150,4151,4153,4155,4157,4159,4161,4163,4165,4167],{"class":26,"line":2488},[24,4152,2369],{"class":30},[24,4154,775],{"class":42},[24,4156,81],{"class":38},[24,4158,731],{"class":42},[24,4160,75],{"class":38},[24,4162,715],{"class":62},[24,4164,186],{"class":38},[24,4166,662],{"class":42},[24,4168,722],{"class":38},[24,4170,4171,4173,4175,4177],{"class":26,"line":2493},[24,4172,2355],{"class":30},[24,4174,681],{"class":38},[24,4176,798],{"class":42},[24,4178,734],{"class":38},[24,4180,4181,4183,4185,4187,4189,4191,4193,4195,4197,4199,4201],{"class":26,"line":2509},[24,4182,2465],{"class":42},[24,4184,75],{"class":38},[24,4186,744],{"class":62},[24,4188,186],{"class":38},[24,4190,662],{"class":42},[24,4192,751],{"class":38},[24,4194,798],{"class":42},[24,4196,81],{"class":38},[24,4198,180],{"class":30},[24,4200,824],{"class":62},[24,4202,763],{"class":38},[24,4204,4205],{"class":26,"line":2528},[24,4206,1012],{"class":38},[24,4208,4209,4211,4213,4215,4217,4219],{"class":26,"line":2533},[24,4210,2496],{"class":42},[24,4212,75],{"class":38},[24,4214,842],{"class":62},[24,4216,186],{"class":38},[24,4218,600],{"class":42},[24,4220,722],{"class":38},[24,4222,4223,4225,4227,4229,4231,4233,4235,4237],{"class":26,"line":2538},[24,4224,1382],{"class":42},[24,4226,75],{"class":38},[24,4228,798],{"class":42},[24,4230,75],{"class":38},[24,4232,1882],{"class":62},[24,4234,186],{"class":38},[24,4236,798],{"class":42},[24,4238,722],{"class":38},[24,4240,4241],{"class":26,"line":2570},[24,4242,95],{"class":38},[24,4244,4245],{"class":26,"line":2591},[24,4246,111],{"emptyLinePlaceholder":110},[24,4248,4249,4251,4253,4255,4257,4259,4261,4263,4265,4267,4269,4271,4273],{"class":26,"line":2604},[24,4250,59],{"class":30},[24,4252,2543],{"class":62},[24,4254,186],{"class":38},[24,4256,360],{"class":202},[24,4258,46],{"class":38},[24,4260,416],{"class":34},[24,4262,206],{"class":38},[24,4264,662],{"class":202},[24,4266,46],{"class":38},[24,4268,445],{"class":34},[24,4270,2562],{"class":38},[24,4272,2565],{"class":34},[24,4274,218],{"class":38},[24,4276,4277,4279,4281,4283,4285,4287,4289,4291,4293],{"class":26,"line":2625},[24,4278,1441],{"class":30},[24,4280,705],{"class":34},[24,4282,81],{"class":38},[24,4284,710],{"class":42},[24,4286,75],{"class":38},[24,4288,715],{"class":62},[24,4290,186],{"class":38},[24,4292,360],{"class":42},[24,4294,722],{"class":38},[24,4296,4297,4299,4301,4303,4305],{"class":26,"line":2638},[24,4298,2355],{"class":30},[24,4300,681],{"class":38},[24,4302,731],{"class":42},[24,4304,212],{"class":38},[24,4306,941],{"class":30},[24,4308,4309,4311,4313,4315,4317,4319,4321,4323,4325],{"class":26,"line":2657},[24,4310,1441],{"class":30},[24,4312,775],{"class":34},[24,4314,81],{"class":38},[24,4316,731],{"class":42},[24,4318,75],{"class":38},[24,4320,715],{"class":62},[24,4322,186],{"class":38},[24,4324,662],{"class":42},[24,4326,722],{"class":38},[24,4328,4329,4331,4333,4335,4337],{"class":26,"line":2662},[24,4330,2355],{"class":30},[24,4332,681],{"class":38},[24,4334,798],{"class":42},[24,4336,212],{"class":38},[24,4338,941],{"class":30},[24,4340,4341,4343,4345,4347,4349,4351,4353,4355],{"class":26,"line":2667},[24,4342,1441],{"class":30},[24,4344,3010],{"class":34},[24,4346,81],{"class":38},[24,4348,180],{"class":30},[24,4350,824],{"class":62},[24,4352,413],{"class":38},[24,4354,2004],{"class":34},[24,4356,3246],{"class":38},[24,4358,4359,4361,4363,4365,4368,4370,4372,4374],{"class":26,"line":2686},[24,4360,2496],{"class":42},[24,4362,75],{"class":38},[24,4364,985],{"class":62},[24,4366,4367],{"class":38},"((",[24,4369,990],{"class":202},[24,4371,212],{"class":38},[24,4373,215],{"class":30},[24,4375,218],{"class":38},[24,4377,4378,4380,4382,4384,4386,4388],{"class":26,"line":2709},[24,4379,678],{"class":30},[24,4381,1563],{"class":38},[24,4383,990],{"class":42},[24,4385,3273],{"class":38},[24,4387,600],{"class":42},[24,4389,734],{"class":38},[24,4391,4392,4394,4396,4398,4400,4402],{"class":26,"line":2725},[24,4393,3282],{"class":42},[24,4395,75],{"class":38},[24,4397,842],{"class":62},[24,4399,186],{"class":38},[24,4401,990],{"class":42},[24,4403,722],{"class":38},[24,4405,4406],{"class":26,"line":2738},[24,4407,768],{"class":38},[24,4409,4410],{"class":26,"line":2743},[24,4411,3301],{"class":38},[24,4413,4414,4416,4418,4420,4422,4424,4426,4428,4430],{"class":26,"line":2770},[24,4415,3027],{"class":42},[24,4417,75],{"class":38},[24,4419,985],{"class":62},[24,4421,4367],{"class":38},[24,4423,990],{"class":202},[24,4425,212],{"class":38},[24,4427,215],{"class":30},[24,4429,996],{"class":62},[24,4431,999],{"class":38},[24,4433,4434],{"class":26,"line":2783},[24,4435,95],{"class":38},[24,4437,4438],{"class":26,"line":2799},[24,4439,111],{"emptyLinePlaceholder":110},[24,4441,4442,4444,4446,4448,4450,4452,4454,4456],{"class":26,"line":2806},[24,4443,31],{"class":30},[24,4445,175],{"class":34},[24,4447,81],{"class":38},[24,4449,180],{"class":30},[24,4451,183],{"class":62},[24,4453,186],{"class":38},[24,4455,84],{"class":42},[24,4457,191],{"class":38},[24,4459,4460,4462,4464,4466,4468,4470,4472,4474,4476,4478],{"class":26,"line":2811},[24,4461,196],{"class":62},[24,4463,199],{"class":38},[24,4465,360],{"class":202},[24,4467,206],{"class":38},[24,4469,662],{"class":202},[24,4471,46],{"class":38},[24,4473,445],{"class":34},[24,4475,212],{"class":38},[24,4477,215],{"class":30},[24,4479,218],{"class":38},[24,4481,4482,4484,4486,4488,4490,4492],{"class":26,"line":2816},[24,4483,2712],{"class":62},[24,4485,186],{"class":38},[24,4487,360],{"class":42},[24,4489,206],{"class":38},[24,4491,662],{"class":42},[24,4493,722],{"class":38},[24,4495,4496,4498,4500,4502,4504],{"class":26,"line":2821},[24,4497,223],{"class":30},[24,4499,691],{"class":42},[24,4501,229],{"class":38},[24,4503,662],{"class":42},[24,4505,234],{"class":38},[24,4507,4508],{"class":26,"line":2833},[24,4509,239],{"class":38},[24,4511,4512,4514,4516,4518,4520,4522,4524,4526,4528,4530,4532,4534],{"class":26,"line":2862},[24,4513,244],{"class":62},[24,4515,199],{"class":38},[24,4517,360],{"class":202},[24,4519,206],{"class":38},[24,4521,662],{"class":202},[24,4523,46],{"class":38},[24,4525,445],{"class":34},[24,4527,206],{"class":38},[24,4529,884],{"class":202},[24,4531,212],{"class":38},[24,4533,215],{"class":30},[24,4535,218],{"class":38},[24,4537,4539,4541,4543,4545,4547],{"class":26,"line":4538},71,[24,4540,896],{"class":42},[24,4542,229],{"class":38},[24,4544,662],{"class":42},[24,4546,275],{"class":38},[24,4548,905],{"class":42},[24,4550,4552,4554,4556,4558,4560,4562],{"class":26,"line":4551},72,[24,4553,2786],{"class":62},[24,4555,186],{"class":38},[24,4557,360],{"class":42},[24,4559,206],{"class":38},[24,4561,662],{"class":42},[24,4563,722],{"class":38},[24,4565,4567,4569],{"class":26,"line":4566},73,[24,4568,223],{"class":30},[24,4570,286],{"class":49},[24,4572,4574],{"class":26,"line":4573},74,[24,4575,1012],{"class":38},[24,4577,4579],{"class":26,"line":4578},75,[24,4580,297],{"class":38},[4582,4583,4584],"style",{},"html pre.shiki code .sqF6k, html code.shiki .sqF6k{--shiki-default:#54B9FF}html pre.shiki code .s8HWQ, html code.shiki .s8HWQ{--shiki-default:#ACAFFF}html pre.shiki code .sLo_3, html code.shiki .sLo_3{--shiki-default:#EEF0F9}html pre.shiki code .sb16X, html code.shiki .sb16X{--shiki-default:#4BF3C8}html pre.shiki code .se2J0, html code.shiki .se2J0{--shiki-default:#FFD493}html pre.shiki code .stHQG, html code.shiki .stHQG{--shiki-default:#00DAEF}html pre.shiki code .sy89t, html code.shiki .sy89t{--shiki-default:#EEF0F98F;--shiki-default-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .smONe, html code.shiki .smONe{--shiki-default:#4BF3C8;--shiki-default-font-style:italic}",{"title":19,"searchDepth":56,"depth":56,"links":4586},[4587,4588,4589,4590,4591,4592,4593],{"id":133,"depth":56,"text":133},{"id":347,"depth":56,"text":347},{"id":594,"depth":56,"text":594},{"id":1180,"depth":56,"text":1180},{"id":3057,"depth":56,"text":3058},{"id":3326,"depth":56,"text":3326},{"id":3625,"depth":56,"text":3625},"2024.07.07","md","响应式系统是 Vue 的核心模块，其原理建立在简单的 JS 语言特性上，却实现了复杂且巧妙的特性。",{},"\u002Fwriting\u002Fvue-reactivity",{"title":5,"description":12},"writing\u002Fvue-reactivity",[4602,4603],"Vue","ES6","iKJ1ZysLPLac7tDCGpqGCKRPFaAlx3QiQJ7yAztnHok",1774950409695]