[{"data":1,"prerenderedAt":6482},["ShallowReactive",2],{"\u002Fwriting\u002Fvue-scheduler":3},{"id":4,"title":5,"body":6,"date":6471,"description":46,"extension":6472,"intro":6473,"meta":6474,"navigation":85,"path":6475,"seo":6476,"stem":6477,"tags":6478,"__hash__":6481},"writing\u002Fwriting\u002Fvue-scheduler.md","Dive into Vue：调度执行",{"type":7,"value":8,"toc":6456},"minimark",[9,21,29,34,40,172,175,183,186,192,203,209,212,218,516,523,806,833,838,847,1117,1120,1127,1133,1149,1152,1157,1160,1166,1347,1364,1621,1631,1634,1679,1685,1891,1897,2172,2175,2190,2213,2385,2410,2425,2600,2606,2696,2699,2702,2705,2806,2815,2835,2850,3069,3072,3079,3084,3087,3149,3152,3177,3180,3184,3200,3327,3346,3586,3598,3740,3743,3749,4074,4092,4098,4113,4475,4485,4488,4491,5748,5751,5984,5987,6452],[10,11,12],"callout",{},[13,14,15,16],"p",{},"Previously on Dive into Vue: ",[17,18,20],"a",{"href":19},"vue-reactivity","响应式系统",[13,22,23,24,28],{},"调度执行机制，指在响应式系统中",[25,26,27],"code",{},"trigger","函数具备的，可以决定副作用执行的时机、次数和方式的能力。在 Vue 的响应式系统中，除了依赖追踪，调度机制也是一个至关重要的组成部分。它决定了副作用在何时、以何种顺序执行，以及如何避免不必要的计算。深入调度执行机制，是理解 Vue 响应式系统不可或缺的步骤。",[30,31,33],"h2",{"id":32},"为什么需要调度机制","为什么需要调度机制？",[13,35,36,37,39],{},"在当前版本的响应式系统视线中，代码不包含调度机制。当触发",[25,38,27],{},"函数时，会立即执行副作用。考虑下面的例子：",[41,42,47],"pre",{"className":43,"code":44,"language":45,"meta":46,"style":46},"language-js shiki shiki-themes houston","const count = ref(0)\n\nwatchEffect(() => {\n  console.log(count.value)\n})\n\ncount.value++\ncount.value++\ncount.value++\n","js","",[25,48,49,80,87,102,127,133,138,150,161],{"__ignoreMap":46},[50,51,54,58,62,66,70,73,77],"span",{"class":52,"line":53},"line",1,[50,55,57],{"class":56},"sqF6k","const",[50,59,61],{"class":60},"s8HWQ"," count",[50,63,65],{"class":64},"sLo_3"," = ",[50,67,69],{"class":68},"stHQG","ref",[50,71,72],{"class":64},"(",[50,74,76],{"class":75},"se2J0","0",[50,78,79],{"class":64},")\n",[50,81,83],{"class":52,"line":82},2,[50,84,86],{"emptyLinePlaceholder":85},true,"\n",[50,88,90,93,96,99],{"class":52,"line":89},3,[50,91,92],{"class":68},"watchEffect",[50,94,95],{"class":64},"(() ",[50,97,98],{"class":56},"=>",[50,100,101],{"class":64}," {\n",[50,103,105,109,112,115,117,120,122,125],{"class":52,"line":104},4,[50,106,108],{"class":107},"sb16X","  console",[50,110,111],{"class":64},".",[50,113,114],{"class":68},"log",[50,116,72],{"class":64},[50,118,119],{"class":107},"count",[50,121,111],{"class":64},[50,123,124],{"class":107},"value",[50,126,79],{"class":64},[50,128,130],{"class":52,"line":129},5,[50,131,132],{"class":64},"})\n",[50,134,136],{"class":52,"line":135},6,[50,137,86],{"emptyLinePlaceholder":85},[50,139,141,143,145,147],{"class":52,"line":140},7,[50,142,119],{"class":107},[50,144,111],{"class":64},[50,146,124],{"class":107},[50,148,149],{"class":64},"++\n",[50,151,153,155,157,159],{"class":52,"line":152},8,[50,154,119],{"class":107},[50,156,111],{"class":64},[50,158,124],{"class":107},[50,160,149],{"class":64},[50,162,164,166,168,170],{"class":52,"line":163},9,[50,165,119],{"class":107},[50,167,111],{"class":64},[50,169,124],{"class":107},[50,171,149],{"class":64},[13,173,174],{},"如果没有调度机制，上述代码会输出：",[41,176,181],{"className":177,"code":179,"language":180},[178],"language-text","0\n1\n2\n3\n","text",[25,182,179],{"__ignoreMap":46},[13,184,185],{},"而在 Vue 中，实际上只会输出：",[41,187,190],{"className":188,"code":189,"language":180},[178],"0\n3\n",[25,191,189],{"__ignoreMap":46},[13,193,194,195,197,198,202],{},"即：数据只更新了一次。不难得出结论：在 Vue 中，实际上",[25,196,27],{},"并",[199,200,201],"strong",{},"不会","直接执行副作用，而是将更新任务统一交给了调度机制进行处理。这避免了大量中间无用状态导致的重复更新。",[13,204,205,206,208],{},"在",[17,207,20],{"href":19},"中的代码实现目前还无法做到这一点。在已有逻辑的基础上，可以模仿 Vue 实现简化的调度机制。",[30,210,211],{"id":211},"支持调度器",[13,213,214,215,217],{},"当前的任务，是需要",[25,216,27],{},"可以通过调度机制调用副作用。这就需要修改副作用函数的结构，使其支持传入一个自定义的调度器。",[41,219,223],{"className":220,"code":221,"language":222,"meta":46,"style":46},"language-ts shiki shiki-themes houston","\u002F\u002F 副作用函数注册时，允许传入`options`配置项，通过`options.scheduler`指定自定义调度器\ntype EffectRegisterOptions = {\n  scheduler?: (fn: Function) => void\n}\n\u002F\u002F 更新副作用函数的类型，使用`options`存储注册时的配置项\ntype EffectFn = Function & {\n  deps: Deps[]\n  options: EffectRegisterOptions\n}\n\nfunction effect(fn: Function, options: EffectRegisterOptions = {}) {\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\n  effectFn.options = options\n  effectFn.deps = []\n  effectFn()\n}\n","ts",[25,224,225,231,242,270,275,280,294,307,317,321,326,358,374,387,398,415,424,436,465,471,476,491,504,511],{"__ignoreMap":46},[50,226,227],{"class":52,"line":53},[50,228,230],{"class":229},"sy89t","\u002F\u002F 副作用函数注册时，允许传入`options`配置项，通过`options.scheduler`指定自定义调度器\n",[50,232,233,236,239],{"class":52,"line":82},[50,234,235],{"class":56},"type",[50,237,238],{"class":60}," EffectRegisterOptions",[50,240,241],{"class":64}," = {\n",[50,243,244,247,250,253,256,259,262,265,267],{"class":52,"line":89},[50,245,246],{"class":68},"  scheduler",[50,248,249],{"class":56},"?",[50,251,252],{"class":64},": (",[50,254,255],{"class":68},"fn",[50,257,258],{"class":64},": ",[50,260,261],{"class":60},"Function",[50,263,264],{"class":64},") ",[50,266,98],{"class":56},[50,268,269],{"class":60}," void\n",[50,271,272],{"class":52,"line":104},[50,273,274],{"class":64},"}\n",[50,276,277],{"class":52,"line":129},[50,278,279],{"class":229},"\u002F\u002F 更新副作用函数的类型，使用`options`存储注册时的配置项\n",[50,281,282,284,287,289,291],{"class":52,"line":135},[50,283,235],{"class":56},[50,285,286],{"class":60}," EffectFn",[50,288,65],{"class":64},[50,290,261],{"class":60},[50,292,293],{"class":64}," & {\n",[50,295,296,299,301,304],{"class":52,"line":140},[50,297,298],{"class":107},"  deps",[50,300,258],{"class":64},[50,302,303],{"class":60},"Deps",[50,305,306],{"class":64},"[]\n",[50,308,309,312,314],{"class":52,"line":152},[50,310,311],{"class":107},"  options",[50,313,258],{"class":64},[50,315,316],{"class":60},"EffectRegisterOptions\n",[50,318,319],{"class":52,"line":163},[50,320,274],{"class":64},[50,322,324],{"class":52,"line":323},10,[50,325,86],{"emptyLinePlaceholder":85},[50,327,329,332,335,337,339,341,343,346,350,352,355],{"class":52,"line":328},11,[50,330,331],{"class":56},"function",[50,333,334],{"class":68}," effect",[50,336,72],{"class":64},[50,338,255],{"class":68},[50,340,258],{"class":64},[50,342,261],{"class":60},[50,344,345],{"class":64},", ",[50,347,349],{"class":348},"smONe","options",[50,351,258],{"class":64},[50,353,354],{"class":60},"EffectRegisterOptions",[50,356,357],{"class":64}," = {}) {\n",[50,359,361,364,367,370,372],{"class":52,"line":360},12,[50,362,363],{"class":56},"  const",[50,365,366],{"class":68}," effectFn",[50,368,369],{"class":64}," = () ",[50,371,98],{"class":56},[50,373,101],{"class":64},[50,375,377,380,382,385],{"class":52,"line":376},13,[50,378,379],{"class":68},"    cleanup",[50,381,72],{"class":64},[50,383,384],{"class":107},"effectFn",[50,386,79],{"class":64},[50,388,390,393,395],{"class":52,"line":389},14,[50,391,392],{"class":107},"    activeEffect",[50,394,65],{"class":64},[50,396,397],{"class":107},"effectFn\n",[50,399,401,404,406,409,411,413],{"class":52,"line":400},15,[50,402,403],{"class":107},"    effectStack",[50,405,111],{"class":64},[50,407,408],{"class":68},"push",[50,410,72],{"class":64},[50,412,384],{"class":107},[50,414,79],{"class":64},[50,416,418,421],{"class":52,"line":417},16,[50,419,420],{"class":68},"    fn",[50,422,423],{"class":64},"()\n",[50,425,427,429,431,434],{"class":52,"line":426},17,[50,428,403],{"class":107},[50,430,111],{"class":64},[50,432,433],{"class":68},"pop",[50,435,423],{"class":64},[50,437,439,441,443,446,449,451,453,456,459,462],{"class":52,"line":438},18,[50,440,392],{"class":107},[50,442,65],{"class":64},[50,444,445],{"class":107},"effectStack",[50,447,448],{"class":64},"[",[50,450,445],{"class":107},[50,452,111],{"class":64},[50,454,455],{"class":107},"length",[50,457,458],{"class":64}," - ",[50,460,461],{"class":75},"1",[50,463,464],{"class":64},"]\n",[50,466,468],{"class":52,"line":467},19,[50,469,470],{"class":64},"  }\n",[50,472,474],{"class":52,"line":473},20,[50,475,86],{"emptyLinePlaceholder":85},[50,477,479,482,484,486,488],{"class":52,"line":478},21,[50,480,481],{"class":107},"  effectFn",[50,483,111],{"class":64},[50,485,349],{"class":107},[50,487,65],{"class":64},[50,489,490],{"class":107},"options\n",[50,492,494,496,498,501],{"class":52,"line":493},22,[50,495,481],{"class":107},[50,497,111],{"class":64},[50,499,500],{"class":107},"deps",[50,502,503],{"class":64}," = []\n",[50,505,507,509],{"class":52,"line":506},23,[50,508,481],{"class":68},[50,510,423],{"class":64},[50,512,514],{"class":52,"line":513},24,[50,515,274],{"class":64},[13,517,518,519,522],{},"调度器",[25,520,521],{},"options.scheduler","可由用户自定义。那么，如何实现上文中提到的省略中间状态、避免额外更新的调度器呢？可以利用微任务队列在事件循环中「延后执行」的特性。简单的实现代码如下：",[41,524,526],{"className":220,"code":525,"language":222,"meta":46,"style":46},"\u002F\u002F 任务队列\nconst queue = new Set\u003CFunction>()\n\u002F\u002F 利用 Promise 实现微任务队列\nconst p = Promise.resolve()\n\u002F\u002F 是否正在刷新任务队列\nlet isFlushing = false\n\nfunction flushJob() {\n  if (isFlushing) return\n  isFlushing = true\n  p.then(() => {\n    \u002F\u002F 将队列中的任务依次执行\n    queue.forEach(job => job())\n  }).finally(() => {\n    isFlushing = false\n  })\n}\n\neffect(() => {\n  console.log(proxyObj.count)\n}, {\n  scheduler: (fn) => {\n    \u002F\u002F 每次调度时，将副作用函数添加到队列中而非立即执行\n    queue.add(fn)\n    flushJob()\n  }\n})\n",[25,527,528,533,556,561,580,585,598,602,612,628,638,654,659,683,697,706,711,715,719,730,749,754,768,773,788,796,801],{"__ignoreMap":46},[50,529,530],{"class":52,"line":53},[50,531,532],{"class":229},"\u002F\u002F 任务队列\n",[50,534,535,537,540,542,545,548,551,553],{"class":52,"line":82},[50,536,57],{"class":56},[50,538,539],{"class":60}," queue",[50,541,65],{"class":64},[50,543,544],{"class":56},"new",[50,546,547],{"class":68}," Set",[50,549,550],{"class":64},"\u003C",[50,552,261],{"class":60},[50,554,555],{"class":64},">()\n",[50,557,558],{"class":52,"line":89},[50,559,560],{"class":229},"\u002F\u002F 利用 Promise 实现微任务队列\n",[50,562,563,565,568,570,573,575,578],{"class":52,"line":104},[50,564,57],{"class":56},[50,566,567],{"class":60}," p",[50,569,65],{"class":64},[50,571,572],{"class":60},"Promise",[50,574,111],{"class":64},[50,576,577],{"class":68},"resolve",[50,579,423],{"class":64},[50,581,582],{"class":52,"line":129},[50,583,584],{"class":229},"\u002F\u002F 是否正在刷新任务队列\n",[50,586,587,590,593,595],{"class":52,"line":135},[50,588,589],{"class":56},"let",[50,591,592],{"class":107}," isFlushing",[50,594,65],{"class":64},[50,596,597],{"class":75},"false\n",[50,599,600],{"class":52,"line":140},[50,601,86],{"emptyLinePlaceholder":85},[50,603,604,606,609],{"class":52,"line":152},[50,605,331],{"class":56},[50,607,608],{"class":68}," flushJob",[50,610,611],{"class":64},"() {\n",[50,613,614,617,620,623,625],{"class":52,"line":163},[50,615,616],{"class":56},"  if",[50,618,619],{"class":64}," (",[50,621,622],{"class":107},"isFlushing",[50,624,264],{"class":64},[50,626,627],{"class":56},"return\n",[50,629,630,633,635],{"class":52,"line":323},[50,631,632],{"class":107},"  isFlushing",[50,634,65],{"class":64},[50,636,637],{"class":75},"true\n",[50,639,640,643,645,648,650,652],{"class":52,"line":328},[50,641,642],{"class":107},"  p",[50,644,111],{"class":64},[50,646,647],{"class":68},"then",[50,649,95],{"class":64},[50,651,98],{"class":56},[50,653,101],{"class":64},[50,655,656],{"class":52,"line":360},[50,657,658],{"class":229},"    \u002F\u002F 将队列中的任务依次执行\n",[50,660,661,664,666,669,671,674,677,680],{"class":52,"line":376},[50,662,663],{"class":107},"    queue",[50,665,111],{"class":64},[50,667,668],{"class":68},"forEach",[50,670,72],{"class":64},[50,672,673],{"class":348},"job",[50,675,676],{"class":56}," =>",[50,678,679],{"class":68}," job",[50,681,682],{"class":64},"())\n",[50,684,685,688,691,693,695],{"class":52,"line":389},[50,686,687],{"class":64},"  }).",[50,689,690],{"class":68},"finally",[50,692,95],{"class":64},[50,694,98],{"class":56},[50,696,101],{"class":64},[50,698,699,702,704],{"class":52,"line":400},[50,700,701],{"class":107},"    isFlushing",[50,703,65],{"class":64},[50,705,597],{"class":75},[50,707,708],{"class":52,"line":417},[50,709,710],{"class":64},"  })\n",[50,712,713],{"class":52,"line":426},[50,714,274],{"class":64},[50,716,717],{"class":52,"line":438},[50,718,86],{"emptyLinePlaceholder":85},[50,720,721,724,726,728],{"class":52,"line":467},[50,722,723],{"class":68},"effect",[50,725,95],{"class":64},[50,727,98],{"class":56},[50,729,101],{"class":64},[50,731,732,734,736,738,740,743,745,747],{"class":52,"line":473},[50,733,108],{"class":107},[50,735,111],{"class":64},[50,737,114],{"class":68},[50,739,72],{"class":64},[50,741,742],{"class":107},"proxyObj",[50,744,111],{"class":64},[50,746,119],{"class":107},[50,748,79],{"class":64},[50,750,751],{"class":52,"line":478},[50,752,753],{"class":64},"}, {\n",[50,755,756,758,760,762,764,766],{"class":52,"line":493},[50,757,246],{"class":68},[50,759,252],{"class":64},[50,761,255],{"class":348},[50,763,264],{"class":64},[50,765,98],{"class":56},[50,767,101],{"class":64},[50,769,770],{"class":52,"line":506},[50,771,772],{"class":229},"    \u002F\u002F 每次调度时，将副作用函数添加到队列中而非立即执行\n",[50,774,775,777,779,782,784,786],{"class":52,"line":513},[50,776,663],{"class":107},[50,778,111],{"class":64},[50,780,781],{"class":68},"add",[50,783,72],{"class":64},[50,785,255],{"class":107},[50,787,79],{"class":64},[50,789,791,794],{"class":52,"line":790},25,[50,792,793],{"class":68},"    flushJob",[50,795,423],{"class":64},[50,797,799],{"class":52,"line":798},26,[50,800,470],{"class":64},[50,802,804],{"class":52,"line":803},27,[50,805,132],{"class":64},[13,807,808,809,813,814,817,818,821,822,825,826,828,829,832],{},"这个调度器使用 Set 来实现一个任务队列。当",[17,810,812],{"href":811},"#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81%E8%B0%83%E5%BA%A6%E6%9C%BA%E5%88%B6","前文中","多次调用",[25,815,816],{},"count.value ++","时，实际上只有一次更新操作会被添加到队列中；随后，",[25,819,820],{},"isFlusing","标志保证了",[25,823,824],{},"flushJob","在一个周期内无论被调用多少次，都只会执行一次。当队列执行完毕并最终被清空时，",[25,827,820],{},"标志会被重置为",[25,830,831],{},"false","，下一个周期又会重复以上过程。",[10,834,835],{},[13,836,837],{},"该调度器只为演示 Vue 内部「连续多次修改响应式数据但只会触发一次更新」的基本原理，调度器可以由用户自定义来实现复杂的副作用执行策略。Vue 内部实现的调度器思路类似，但更加完善。",[13,839,840,841,843,844,846],{},"接着，在",[25,842,27],{},"函数中，当需要执行副作用时，如果副作用函数",[25,845,384],{},"上指定了调度器，那么调用调度器函数而不是立即执行副作用。",[41,848,850],{"className":220,"code":849,"language":222,"meta":46,"style":46},"function trigger(target: object, key: PropertyKey) {\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) => {\n    if (effectFn.options.scheduler) {\n      effectFn.options.scheduler(effectFn)\n    } else {\n      effectFn()\n    }\n  })\n}\n",[25,851,852,882,905,919,940,952,972,991,1008,1023,1028,1032,1051,1070,1089,1099,1105,1109,1113],{"__ignoreMap":46},[50,853,854,856,859,861,864,866,869,871,874,876,879],{"class":52,"line":53},[50,855,331],{"class":56},[50,857,858],{"class":68}," trigger",[50,860,72],{"class":64},[50,862,863],{"class":348},"target",[50,865,258],{"class":64},[50,867,868],{"class":60},"object",[50,870,345],{"class":64},[50,872,873],{"class":348},"key",[50,875,258],{"class":64},[50,877,878],{"class":60},"PropertyKey",[50,880,881],{"class":64},") {\n",[50,883,884,886,889,891,894,896,899,901,903],{"class":52,"line":82},[50,885,363],{"class":56},[50,887,888],{"class":60}," depsMap",[50,890,65],{"class":64},[50,892,893],{"class":107},"bucket",[50,895,111],{"class":64},[50,897,898],{"class":68},"get",[50,900,72],{"class":64},[50,902,863],{"class":107},[50,904,79],{"class":64},[50,906,907,909,912,915,917],{"class":52,"line":89},[50,908,616],{"class":56},[50,910,911],{"class":64}," (!",[50,913,914],{"class":107},"depsMap",[50,916,264],{"class":64},[50,918,627],{"class":56},[50,920,921,923,926,928,930,932,934,936,938],{"class":52,"line":104},[50,922,363],{"class":56},[50,924,925],{"class":60}," deps",[50,927,65],{"class":64},[50,929,914],{"class":107},[50,931,111],{"class":64},[50,933,898],{"class":68},[50,935,72],{"class":64},[50,937,873],{"class":107},[50,939,79],{"class":64},[50,941,942,944,946,948,950],{"class":52,"line":129},[50,943,616],{"class":56},[50,945,911],{"class":64},[50,947,500],{"class":107},[50,949,264],{"class":64},[50,951,627],{"class":56},[50,953,954,956,959,961,963,965,967,970],{"class":52,"line":135},[50,955,363],{"class":56},[50,957,958],{"class":60}," effectsToRun",[50,960,65],{"class":64},[50,962,544],{"class":56},[50,964,547],{"class":68},[50,966,550],{"class":64},[50,968,969],{"class":60},"EffectFn",[50,971,555],{"class":64},[50,973,974,976,978,980,983,985,987,989],{"class":52,"line":140},[50,975,298],{"class":107},[50,977,111],{"class":64},[50,979,668],{"class":68},[50,981,982],{"class":64},"((",[50,984,384],{"class":348},[50,986,264],{"class":64},[50,988,98],{"class":56},[50,990,101],{"class":64},[50,992,993,996,998,1000,1003,1006],{"class":52,"line":152},[50,994,995],{"class":56},"    if",[50,997,619],{"class":64},[50,999,384],{"class":107},[50,1001,1002],{"class":64}," !== ",[50,1004,1005],{"class":107},"activeEffect",[50,1007,881],{"class":64},[50,1009,1010,1013,1015,1017,1019,1021],{"class":52,"line":163},[50,1011,1012],{"class":107},"      effectsToRun",[50,1014,111],{"class":64},[50,1016,781],{"class":68},[50,1018,72],{"class":64},[50,1020,384],{"class":107},[50,1022,79],{"class":64},[50,1024,1025],{"class":52,"line":323},[50,1026,1027],{"class":64},"    }\n",[50,1029,1030],{"class":52,"line":328},[50,1031,710],{"class":64},[50,1033,1034,1037,1039,1041,1043,1045,1047,1049],{"class":52,"line":360},[50,1035,1036],{"class":107},"  effectsToRun",[50,1038,111],{"class":64},[50,1040,668],{"class":68},[50,1042,982],{"class":64},[50,1044,384],{"class":348},[50,1046,264],{"class":64},[50,1048,98],{"class":56},[50,1050,101],{"class":64},[50,1052,1053,1055,1057,1059,1061,1063,1065,1068],{"class":52,"line":376},[50,1054,995],{"class":56},[50,1056,619],{"class":64},[50,1058,384],{"class":107},[50,1060,111],{"class":64},[50,1062,349],{"class":107},[50,1064,111],{"class":64},[50,1066,1067],{"class":107},"scheduler",[50,1069,881],{"class":64},[50,1071,1072,1075,1077,1079,1081,1083,1085,1087],{"class":52,"line":389},[50,1073,1074],{"class":107},"      effectFn",[50,1076,111],{"class":64},[50,1078,349],{"class":107},[50,1080,111],{"class":64},[50,1082,1067],{"class":68},[50,1084,72],{"class":64},[50,1086,384],{"class":107},[50,1088,79],{"class":64},[50,1090,1091,1094,1097],{"class":52,"line":400},[50,1092,1093],{"class":64},"    } ",[50,1095,1096],{"class":56},"else",[50,1098,101],{"class":64},[50,1100,1101,1103],{"class":52,"line":417},[50,1102,1074],{"class":68},[50,1104,423],{"class":64},[50,1106,1107],{"class":52,"line":426},[50,1108,1027],{"class":64},[50,1110,1111],{"class":52,"line":438},[50,1112,710],{"class":64},[50,1114,1115],{"class":52,"line":467},[50,1116,274],{"class":64},[13,1118,1119],{},"截至目前，响应式系统已经具备了调度能力，并且还实现了一个行为类似 Vue 的调度器。",[30,1121,1123,1124],{"id":1122},"计算属性computed","计算属性",[25,1125,1126],{},"computed",[13,1128,1129,1130,1132],{},"Vue 中的一个重要功能就是计算属性",[25,1131,1126],{},"。计算属性接受一个 getter，返回计算结果。计算属性具有如下特性：",[1134,1135,1136,1143],"ul",{},[1137,1138,1139,1142],"li",{},[199,1140,1141],{},"Lazy","：不会立即返回值，只在访问时进行计算；",[1137,1144,1145,1148],{},[199,1146,1147],{},"缓存","：只有当计算属性依赖的响应式数据发生变化时，才会重新计算。",[13,1150,1151],{},"计算属性的这两点特性均可以通过调度机制实现。",[1153,1154,1156],"h3",{"id":1155},"lazy-effect","Lazy Effect",[13,1158,1159],{},"在计算属性中，计算是懒执行的。必须要实现一个同样懒执行的副作用函数，才能作为实现计算属性的基础。",[13,1161,1162,1163,1165],{},"观察当前版本的",[25,1164,723],{},"实现：",[41,1167,1170],{"className":220,"code":1168,"highlights":1169,"language":222,"meta":46,"style":46},"function effect(fn: Function, options: EffectRegisterOptions = {}) {\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\n  effectFn.options = options\n  effectFn.deps = []\n  effectFn()\n}\n\neffect(() => console.log('effect run'))\n",[376],[25,1171,1172,1196,1208,1218,1226,1240,1246,1256,1278,1282,1286,1298,1308,1316,1320,1324],{"__ignoreMap":46},[50,1173,1174,1176,1178,1180,1182,1184,1186,1188,1190,1192,1194],{"class":52,"line":53},[50,1175,331],{"class":56},[50,1177,334],{"class":68},[50,1179,72],{"class":64},[50,1181,255],{"class":68},[50,1183,258],{"class":64},[50,1185,261],{"class":60},[50,1187,345],{"class":64},[50,1189,349],{"class":348},[50,1191,258],{"class":64},[50,1193,354],{"class":60},[50,1195,357],{"class":64},[50,1197,1198,1200,1202,1204,1206],{"class":52,"line":82},[50,1199,363],{"class":56},[50,1201,366],{"class":68},[50,1203,369],{"class":64},[50,1205,98],{"class":56},[50,1207,101],{"class":64},[50,1209,1210,1212,1214,1216],{"class":52,"line":89},[50,1211,379],{"class":68},[50,1213,72],{"class":64},[50,1215,384],{"class":107},[50,1217,79],{"class":64},[50,1219,1220,1222,1224],{"class":52,"line":104},[50,1221,392],{"class":107},[50,1223,65],{"class":64},[50,1225,397],{"class":107},[50,1227,1228,1230,1232,1234,1236,1238],{"class":52,"line":129},[50,1229,403],{"class":107},[50,1231,111],{"class":64},[50,1233,408],{"class":68},[50,1235,72],{"class":64},[50,1237,384],{"class":107},[50,1239,79],{"class":64},[50,1241,1242,1244],{"class":52,"line":135},[50,1243,420],{"class":68},[50,1245,423],{"class":64},[50,1247,1248,1250,1252,1254],{"class":52,"line":140},[50,1249,403],{"class":107},[50,1251,111],{"class":64},[50,1253,433],{"class":68},[50,1255,423],{"class":64},[50,1257,1258,1260,1262,1264,1266,1268,1270,1272,1274,1276],{"class":52,"line":152},[50,1259,392],{"class":107},[50,1261,65],{"class":64},[50,1263,445],{"class":107},[50,1265,448],{"class":64},[50,1267,445],{"class":107},[50,1269,111],{"class":64},[50,1271,455],{"class":107},[50,1273,458],{"class":64},[50,1275,461],{"class":75},[50,1277,464],{"class":64},[50,1279,1280],{"class":52,"line":163},[50,1281,470],{"class":64},[50,1283,1284],{"class":52,"line":323},[50,1285,86],{"emptyLinePlaceholder":85},[50,1287,1288,1290,1292,1294,1296],{"class":52,"line":328},[50,1289,481],{"class":107},[50,1291,111],{"class":64},[50,1293,349],{"class":107},[50,1295,65],{"class":64},[50,1297,490],{"class":107},[50,1299,1300,1302,1304,1306],{"class":52,"line":360},[50,1301,481],{"class":107},[50,1303,111],{"class":64},[50,1305,500],{"class":107},[50,1307,503],{"class":64},[50,1309,1312,1314],{"class":1310,"line":376},[52,1311],"highlight",[50,1313,481],{"class":68},[50,1315,423],{"class":64},[50,1317,1318],{"class":52,"line":389},[50,1319,274],{"class":64},[50,1321,1322],{"class":52,"line":400},[50,1323,86],{"emptyLinePlaceholder":85},[50,1325,1326,1328,1330,1332,1335,1337,1339,1341,1344],{"class":52,"line":417},[50,1327,723],{"class":68},[50,1329,95],{"class":64},[50,1331,98],{"class":56},[50,1333,1334],{"class":107}," console",[50,1336,111],{"class":64},[50,1338,114],{"class":68},[50,1340,72],{"class":64},[50,1342,1343],{"class":75},"'effect run'",[50,1345,1346],{"class":64},"))\n",[13,1348,1349,1350,1352,1353,1356,1357,1360,1361,1363],{},"在调用",[25,1351,723],{},"注册副作用时，由于高亮的第 13 行，副作用总是立即执行一次。若要实现懒执行，需要在 13 行执行前增加判断，表明是否立即执行副作用。因此，增加参数",[25,1354,1355],{},"options.lazy","，若为",[25,1358,1359],{},"true","，则不立即执行，而是返回副作用函数",[25,1362,384],{},"以便在后续的某个时刻手动调用求值。",[41,1365,1368],{"className":220,"code":1366,"highlights":1367,"language":222,"meta":46,"style":46},"type EffectRegisterOptions = {\n  scheduler?: (fn: Function) => void\n  lazy?: boolean\n}\n\nfunction effect(fn: Function, options: EffectRegisterOptions = {}) {\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\n  effectFn.options = options\n  effectFn.deps = []\n  if (!options.lazy) {\n    effectFn()\n  }\n  return effectFn\n}\n\neffect(() => console.log('effect run'))\n",[89,438,467,473,478],[25,1369,1370,1378,1398,1411,1415,1419,1443,1455,1465,1473,1487,1493,1503,1525,1529,1533,1545,1555,1571,1579,1584,1593,1597,1601],{"__ignoreMap":46},[50,1371,1372,1374,1376],{"class":52,"line":53},[50,1373,235],{"class":56},[50,1375,238],{"class":60},[50,1377,241],{"class":64},[50,1379,1380,1382,1384,1386,1388,1390,1392,1394,1396],{"class":52,"line":82},[50,1381,246],{"class":68},[50,1383,249],{"class":56},[50,1385,252],{"class":64},[50,1387,255],{"class":68},[50,1389,258],{"class":64},[50,1391,261],{"class":60},[50,1393,264],{"class":64},[50,1395,98],{"class":56},[50,1397,269],{"class":60},[50,1399,1401,1404,1406,1408],{"class":1400,"line":89},[52,1311],[50,1402,1403],{"class":107},"  lazy",[50,1405,249],{"class":56},[50,1407,258],{"class":64},[50,1409,1410],{"class":60},"boolean\n",[50,1412,1413],{"class":52,"line":104},[50,1414,274],{"class":64},[50,1416,1417],{"class":52,"line":129},[50,1418,86],{"emptyLinePlaceholder":85},[50,1420,1421,1423,1425,1427,1429,1431,1433,1435,1437,1439,1441],{"class":52,"line":135},[50,1422,331],{"class":56},[50,1424,334],{"class":68},[50,1426,72],{"class":64},[50,1428,255],{"class":68},[50,1430,258],{"class":64},[50,1432,261],{"class":60},[50,1434,345],{"class":64},[50,1436,349],{"class":348},[50,1438,258],{"class":64},[50,1440,354],{"class":60},[50,1442,357],{"class":64},[50,1444,1445,1447,1449,1451,1453],{"class":52,"line":140},[50,1446,363],{"class":56},[50,1448,366],{"class":68},[50,1450,369],{"class":64},[50,1452,98],{"class":56},[50,1454,101],{"class":64},[50,1456,1457,1459,1461,1463],{"class":52,"line":152},[50,1458,379],{"class":68},[50,1460,72],{"class":64},[50,1462,384],{"class":107},[50,1464,79],{"class":64},[50,1466,1467,1469,1471],{"class":52,"line":163},[50,1468,392],{"class":107},[50,1470,65],{"class":64},[50,1472,397],{"class":107},[50,1474,1475,1477,1479,1481,1483,1485],{"class":52,"line":323},[50,1476,403],{"class":107},[50,1478,111],{"class":64},[50,1480,408],{"class":68},[50,1482,72],{"class":64},[50,1484,384],{"class":107},[50,1486,79],{"class":64},[50,1488,1489,1491],{"class":52,"line":328},[50,1490,420],{"class":68},[50,1492,423],{"class":64},[50,1494,1495,1497,1499,1501],{"class":52,"line":360},[50,1496,403],{"class":107},[50,1498,111],{"class":64},[50,1500,433],{"class":68},[50,1502,423],{"class":64},[50,1504,1505,1507,1509,1511,1513,1515,1517,1519,1521,1523],{"class":52,"line":376},[50,1506,392],{"class":107},[50,1508,65],{"class":64},[50,1510,445],{"class":107},[50,1512,448],{"class":64},[50,1514,445],{"class":107},[50,1516,111],{"class":64},[50,1518,455],{"class":107},[50,1520,458],{"class":64},[50,1522,461],{"class":75},[50,1524,464],{"class":64},[50,1526,1527],{"class":52,"line":389},[50,1528,470],{"class":64},[50,1530,1531],{"class":52,"line":400},[50,1532,86],{"emptyLinePlaceholder":85},[50,1534,1535,1537,1539,1541,1543],{"class":52,"line":417},[50,1536,481],{"class":107},[50,1538,111],{"class":64},[50,1540,349],{"class":107},[50,1542,65],{"class":64},[50,1544,490],{"class":107},[50,1546,1547,1549,1551,1553],{"class":52,"line":426},[50,1548,481],{"class":107},[50,1550,111],{"class":64},[50,1552,500],{"class":107},[50,1554,503],{"class":64},[50,1556,1558,1560,1562,1564,1566,1569],{"class":1557,"line":438},[52,1311],[50,1559,616],{"class":56},[50,1561,911],{"class":64},[50,1563,349],{"class":107},[50,1565,111],{"class":64},[50,1567,1568],{"class":107},"lazy",[50,1570,881],{"class":64},[50,1572,1574,1577],{"class":1573,"line":467},[52,1311],[50,1575,1576],{"class":68},"    effectFn",[50,1578,423],{"class":64},[50,1580,1582],{"class":1581,"line":473},[52,1311],[50,1583,470],{"class":64},[50,1585,1587,1590],{"class":1586,"line":478},[52,1311],[50,1588,1589],{"class":56},"  return",[50,1591,1592],{"class":107}," effectFn\n",[50,1594,1595],{"class":52,"line":493},[50,1596,274],{"class":64},[50,1598,1599],{"class":52,"line":506},[50,1600,86],{"emptyLinePlaceholder":85},[50,1602,1603,1605,1607,1609,1611,1613,1615,1617,1619],{"class":52,"line":513},[50,1604,723],{"class":68},[50,1606,95],{"class":64},[50,1608,98],{"class":56},[50,1610,1334],{"class":107},[50,1612,111],{"class":64},[50,1614,114],{"class":68},[50,1616,72],{"class":64},[50,1618,1343],{"class":75},[50,1620,1346],{"class":64},[13,1622,1623,1624,1626,1627,1630],{},"此时，当调用",[25,1625,723],{},"注册副作用且同时指定",[25,1628,1629],{},"lazy: true","时，副作用函数就不会立即执行了。",[13,1632,1633],{},"下面考虑一个使用计算属性的例子：",[41,1635,1637],{"className":220,"code":1636,"language":222,"meta":46,"style":46},"const fullName = computed(() => proxyObj.firstName + ' ' + proxyObj.lastName)\n",[25,1638,1639],{"__ignoreMap":46},[50,1640,1641,1643,1646,1648,1650,1652,1654,1657,1659,1662,1665,1668,1670,1672,1674,1677],{"class":52,"line":53},[50,1642,57],{"class":56},[50,1644,1645],{"class":60}," fullName",[50,1647,65],{"class":64},[50,1649,1126],{"class":68},[50,1651,95],{"class":64},[50,1653,98],{"class":56},[50,1655,1656],{"class":107}," proxyObj",[50,1658,111],{"class":64},[50,1660,1661],{"class":107},"firstName",[50,1663,1664],{"class":64}," + ",[50,1666,1667],{"class":75},"' '",[50,1669,1664],{"class":64},[50,1671,742],{"class":107},[50,1673,111],{"class":64},[50,1675,1676],{"class":107},"lastName",[50,1678,79],{"class":64},[13,1680,1681,1682,1684],{},"在这个例子中，副作用是一个 getter 函数。在这种情况下仅仅实现了手动调用副作用是不够的，还需要能够在手动调用副作用时获取返回值（即计算结果）。为了实现这个目标，需要对",[25,1683,723],{},"进行修改，增加可以保存和返回计算结果的能力。",[41,1686,1689],{"className":220,"code":1687,"highlights":1688,"language":222,"meta":46,"style":46},"function effect(fn: Function, options: EffectRegisterOptions = {}) {\n  const effectFn = () => {\n    cleanup(effectFn)\n    activeEffect = effectFn\n    effectStack.push(effectFn)\n    \u002F\u002F 使用变量保存计算结果\n    const res = fn()\n    effectStack.pop()\n    activeEffect = effectStack[effectStack.length - 1]\n    \u002F\u002F 当手动调用副作用函数时，可以通过返回值获取计算结果\n    return res\n  }\n\n  effectFn.options = options\n  effectFn.deps = []\n  if (!options.lazy) {\n    effectFn()\n  }\n  return effectFn\n}\n",[135,140,323,328],[25,1690,1691,1715,1727,1737,1745,1759,1765,1780,1790,1812,1818,1827,1831,1835,1847,1857,1871,1877,1881,1887],{"__ignoreMap":46},[50,1692,1693,1695,1697,1699,1701,1703,1705,1707,1709,1711,1713],{"class":52,"line":53},[50,1694,331],{"class":56},[50,1696,334],{"class":68},[50,1698,72],{"class":64},[50,1700,255],{"class":68},[50,1702,258],{"class":64},[50,1704,261],{"class":60},[50,1706,345],{"class":64},[50,1708,349],{"class":348},[50,1710,258],{"class":64},[50,1712,354],{"class":60},[50,1714,357],{"class":64},[50,1716,1717,1719,1721,1723,1725],{"class":52,"line":82},[50,1718,363],{"class":56},[50,1720,366],{"class":68},[50,1722,369],{"class":64},[50,1724,98],{"class":56},[50,1726,101],{"class":64},[50,1728,1729,1731,1733,1735],{"class":52,"line":89},[50,1730,379],{"class":68},[50,1732,72],{"class":64},[50,1734,384],{"class":107},[50,1736,79],{"class":64},[50,1738,1739,1741,1743],{"class":52,"line":104},[50,1740,392],{"class":107},[50,1742,65],{"class":64},[50,1744,397],{"class":107},[50,1746,1747,1749,1751,1753,1755,1757],{"class":52,"line":129},[50,1748,403],{"class":107},[50,1750,111],{"class":64},[50,1752,408],{"class":68},[50,1754,72],{"class":64},[50,1756,384],{"class":107},[50,1758,79],{"class":64},[50,1760,1762],{"class":1761,"line":135},[52,1311],[50,1763,1764],{"class":229},"    \u002F\u002F 使用变量保存计算结果\n",[50,1766,1768,1771,1774,1776,1778],{"class":1767,"line":140},[52,1311],[50,1769,1770],{"class":56},"    const",[50,1772,1773],{"class":60}," res",[50,1775,65],{"class":64},[50,1777,255],{"class":68},[50,1779,423],{"class":64},[50,1781,1782,1784,1786,1788],{"class":52,"line":152},[50,1783,403],{"class":107},[50,1785,111],{"class":64},[50,1787,433],{"class":68},[50,1789,423],{"class":64},[50,1791,1792,1794,1796,1798,1800,1802,1804,1806,1808,1810],{"class":52,"line":163},[50,1793,392],{"class":107},[50,1795,65],{"class":64},[50,1797,445],{"class":107},[50,1799,448],{"class":64},[50,1801,445],{"class":107},[50,1803,111],{"class":64},[50,1805,455],{"class":107},[50,1807,458],{"class":64},[50,1809,461],{"class":75},[50,1811,464],{"class":64},[50,1813,1815],{"class":1814,"line":323},[52,1311],[50,1816,1817],{"class":229},"    \u002F\u002F 当手动调用副作用函数时，可以通过返回值获取计算结果\n",[50,1819,1821,1824],{"class":1820,"line":328},[52,1311],[50,1822,1823],{"class":56},"    return",[50,1825,1826],{"class":107}," res\n",[50,1828,1829],{"class":52,"line":360},[50,1830,470],{"class":64},[50,1832,1833],{"class":52,"line":376},[50,1834,86],{"emptyLinePlaceholder":85},[50,1836,1837,1839,1841,1843,1845],{"class":52,"line":389},[50,1838,481],{"class":107},[50,1840,111],{"class":64},[50,1842,349],{"class":107},[50,1844,65],{"class":64},[50,1846,490],{"class":107},[50,1848,1849,1851,1853,1855],{"class":52,"line":400},[50,1850,481],{"class":107},[50,1852,111],{"class":64},[50,1854,500],{"class":107},[50,1856,503],{"class":64},[50,1858,1859,1861,1863,1865,1867,1869],{"class":52,"line":417},[50,1860,616],{"class":56},[50,1862,911],{"class":64},[50,1864,349],{"class":107},[50,1866,111],{"class":64},[50,1868,1568],{"class":107},[50,1870,881],{"class":64},[50,1872,1873,1875],{"class":52,"line":426},[50,1874,1576],{"class":68},[50,1876,423],{"class":64},[50,1878,1879],{"class":52,"line":438},[50,1880,470],{"class":64},[50,1882,1883,1885],{"class":52,"line":467},[50,1884,1589],{"class":56},[50,1886,1592],{"class":107},[50,1888,1889],{"class":52,"line":473},[50,1890,274],{"class":64},[13,1892,1893,1894,1896],{},"接下来，基于 Lazy Effect 编写计算属性",[25,1895,1126],{},"的实现函数：",[41,1898,1901],{"className":220,"code":1899,"highlights":1900,"language":222,"meta":46,"style":46},"function computed(getter: Function) {\n  const effectFn = effect(() => {\n    \u002F\u002F 增加一个输出，更好地识别计算属性在何时进行求值\n    console.log('effectFn invoked')\n    return getter()\n  }, { lazy: true })\n  \n  const obj = {\n    get value() {\n      return effectFn()\n    }\n  }\n\n  return obj\n}\n\nconst obj = {\n  firstName: 'John',\n  lastName: 'Doe'\n}\nconst proxyObj = new Proxy(obj, { \u002F* get, set *\u002F })\n\n\u002F\u002F ↓ 调用 computed 并不会触发\nconst fullName = computed(() => proxyObj.firstName + ' ' + proxyObj.lastName)\n\u002F\u002F ↓ 计算属性仅在访问 fullName.value 时才会进行求值\nconsole.log(fullName.value)\n",[89,104],[25,1902,1903,1921,1937,1943,1960,1969,1983,1988,1997,2007,2016,2020,2024,2028,2035,2039,2043,2051,2064,2074,2078,2104,2108,2113,2147,2152],{"__ignoreMap":46},[50,1904,1905,1907,1910,1912,1915,1917,1919],{"class":52,"line":53},[50,1906,331],{"class":56},[50,1908,1909],{"class":68}," computed",[50,1911,72],{"class":64},[50,1913,1914],{"class":68},"getter",[50,1916,258],{"class":64},[50,1918,261],{"class":60},[50,1920,881],{"class":64},[50,1922,1923,1925,1927,1929,1931,1933,1935],{"class":52,"line":82},[50,1924,363],{"class":56},[50,1926,366],{"class":60},[50,1928,65],{"class":64},[50,1930,723],{"class":68},[50,1932,95],{"class":64},[50,1934,98],{"class":56},[50,1936,101],{"class":64},[50,1938,1940],{"class":1939,"line":89},[52,1311],[50,1941,1942],{"class":229},"    \u002F\u002F 增加一个输出，更好地识别计算属性在何时进行求值\n",[50,1944,1946,1949,1951,1953,1955,1958],{"class":1945,"line":104},[52,1311],[50,1947,1948],{"class":107},"    console",[50,1950,111],{"class":64},[50,1952,114],{"class":68},[50,1954,72],{"class":64},[50,1956,1957],{"class":75},"'effectFn invoked'",[50,1959,79],{"class":64},[50,1961,1962,1964,1967],{"class":52,"line":129},[50,1963,1823],{"class":56},[50,1965,1966],{"class":68}," getter",[50,1968,423],{"class":64},[50,1970,1971,1974,1976,1978,1980],{"class":52,"line":135},[50,1972,1973],{"class":64},"  }, { ",[50,1975,1568],{"class":107},[50,1977,258],{"class":64},[50,1979,1359],{"class":75},[50,1981,1982],{"class":64}," })\n",[50,1984,1985],{"class":52,"line":140},[50,1986,1987],{"class":64},"  \n",[50,1989,1990,1992,1995],{"class":52,"line":152},[50,1991,363],{"class":56},[50,1993,1994],{"class":60}," obj",[50,1996,241],{"class":64},[50,1998,1999,2002,2005],{"class":52,"line":163},[50,2000,2001],{"class":56},"    get",[50,2003,2004],{"class":68}," value",[50,2006,611],{"class":64},[50,2008,2009,2012,2014],{"class":52,"line":323},[50,2010,2011],{"class":56},"      return",[50,2013,366],{"class":68},[50,2015,423],{"class":64},[50,2017,2018],{"class":52,"line":328},[50,2019,1027],{"class":64},[50,2021,2022],{"class":52,"line":360},[50,2023,470],{"class":64},[50,2025,2026],{"class":52,"line":376},[50,2027,86],{"emptyLinePlaceholder":85},[50,2029,2030,2032],{"class":52,"line":389},[50,2031,1589],{"class":56},[50,2033,2034],{"class":107}," obj\n",[50,2036,2037],{"class":52,"line":400},[50,2038,274],{"class":64},[50,2040,2041],{"class":52,"line":417},[50,2042,86],{"emptyLinePlaceholder":85},[50,2044,2045,2047,2049],{"class":52,"line":426},[50,2046,57],{"class":56},[50,2048,1994],{"class":60},[50,2050,241],{"class":64},[50,2052,2053,2056,2058,2061],{"class":52,"line":438},[50,2054,2055],{"class":107},"  firstName",[50,2057,258],{"class":64},[50,2059,2060],{"class":75},"'John'",[50,2062,2063],{"class":64},",\n",[50,2065,2066,2069,2071],{"class":52,"line":467},[50,2067,2068],{"class":107},"  lastName",[50,2070,258],{"class":64},[50,2072,2073],{"class":75},"'Doe'\n",[50,2075,2076],{"class":52,"line":473},[50,2077,274],{"class":64},[50,2079,2080,2082,2084,2086,2088,2091,2093,2096,2099,2102],{"class":52,"line":478},[50,2081,57],{"class":56},[50,2083,1656],{"class":60},[50,2085,65],{"class":64},[50,2087,544],{"class":56},[50,2089,2090],{"class":68}," Proxy",[50,2092,72],{"class":64},[50,2094,2095],{"class":107},"obj",[50,2097,2098],{"class":64},", { ",[50,2100,2101],{"class":229},"\u002F* get, set *\u002F",[50,2103,1982],{"class":64},[50,2105,2106],{"class":52,"line":493},[50,2107,86],{"emptyLinePlaceholder":85},[50,2109,2110],{"class":52,"line":506},[50,2111,2112],{"class":229},"\u002F\u002F ↓ 调用 computed 并不会触发\n",[50,2114,2115,2117,2119,2121,2123,2125,2127,2129,2131,2133,2135,2137,2139,2141,2143,2145],{"class":52,"line":513},[50,2116,57],{"class":56},[50,2118,1645],{"class":60},[50,2120,65],{"class":64},[50,2122,1126],{"class":68},[50,2124,95],{"class":64},[50,2126,98],{"class":56},[50,2128,1656],{"class":107},[50,2130,111],{"class":64},[50,2132,1661],{"class":107},[50,2134,1664],{"class":64},[50,2136,1667],{"class":75},[50,2138,1664],{"class":64},[50,2140,742],{"class":107},[50,2142,111],{"class":64},[50,2144,1676],{"class":107},[50,2146,79],{"class":64},[50,2148,2149],{"class":52,"line":790},[50,2150,2151],{"class":229},"\u002F\u002F ↓ 计算属性仅在访问 fullName.value 时才会进行求值\n",[50,2153,2154,2157,2159,2161,2163,2166,2168,2170],{"class":52,"line":798},[50,2155,2156],{"class":107},"console",[50,2158,111],{"class":64},[50,2160,114],{"class":68},[50,2162,72],{"class":64},[50,2164,2165],{"class":107},"fullName",[50,2167,111],{"class":64},[50,2169,124],{"class":107},[50,2171,79],{"class":64},[1153,2173,2174],{"id":2174},"缓存计算结果",[13,2176,2177,2178,2181,2182,2185,2186,2189],{},"上文已经实现了懒执行的计算属性。但当多次访问",[25,2179,2180],{},"fullName.value","时，即便依赖的响应式数据",[25,2183,2184],{},"proxyObj.firstName","和",[25,2187,2188],{},"proxyObj.lastName","没有发生变化，计算属性也会重新求值。为了避免重复计算，需要缓存计算结果。",[13,2191,2192,2193,2196,2197,2200,2201,2203,2204,2206,2207,2209,2210,2212],{},"在计算属性的实现中，增加一个变量",[25,2194,2195],{},"cache","，用于缓存计算结果；使用",[25,2198,2199],{},"dirty","标志位表示是否需要重新计算。当",[25,2202,2199],{},"为",[25,2205,1359],{},"时，才进行重新求值，否则当访问",[25,2208,124],{},"时应当直接返回",[25,2211,2195],{},"。",[41,2214,2217],{"className":220,"code":2215,"highlights":2216,"language":222,"meta":46,"style":46},"function computed(getter: Function) {\n  let cache: any\n  let dirty = true\n\n  const effectFn = effect(getter, {\n    lazy: true\n  })\n\n  const obj = {\n    get value() {\n      if (dirty) {\n        cache = effectFn()\n        dirty = false\n      }\n      return cache\n    }\n  }\n\n  return obj\n}\n",[82,89,328,360,376,389,400],[25,2218,2219,2235,2249,2261,2265,2282,2291,2295,2299,2307,2315,2327,2339,2349,2355,2363,2367,2371,2375,2381],{"__ignoreMap":46},[50,2220,2221,2223,2225,2227,2229,2231,2233],{"class":52,"line":53},[50,2222,331],{"class":56},[50,2224,1909],{"class":68},[50,2226,72],{"class":64},[50,2228,1914],{"class":68},[50,2230,258],{"class":64},[50,2232,261],{"class":60},[50,2234,881],{"class":64},[50,2236,2238,2241,2244,2246],{"class":2237,"line":82},[52,1311],[50,2239,2240],{"class":56},"  let",[50,2242,2243],{"class":107}," cache",[50,2245,258],{"class":64},[50,2247,2248],{"class":60},"any\n",[50,2250,2252,2254,2257,2259],{"class":2251,"line":89},[52,1311],[50,2253,2240],{"class":56},[50,2255,2256],{"class":107}," dirty",[50,2258,65],{"class":64},[50,2260,637],{"class":75},[50,2262,2263],{"class":52,"line":104},[50,2264,86],{"emptyLinePlaceholder":85},[50,2266,2267,2269,2271,2273,2275,2277,2279],{"class":52,"line":129},[50,2268,363],{"class":56},[50,2270,366],{"class":60},[50,2272,65],{"class":64},[50,2274,723],{"class":68},[50,2276,72],{"class":64},[50,2278,1914],{"class":107},[50,2280,2281],{"class":64},", {\n",[50,2283,2284,2287,2289],{"class":52,"line":135},[50,2285,2286],{"class":107},"    lazy",[50,2288,258],{"class":64},[50,2290,637],{"class":75},[50,2292,2293],{"class":52,"line":140},[50,2294,710],{"class":64},[50,2296,2297],{"class":52,"line":152},[50,2298,86],{"emptyLinePlaceholder":85},[50,2300,2301,2303,2305],{"class":52,"line":163},[50,2302,363],{"class":56},[50,2304,1994],{"class":60},[50,2306,241],{"class":64},[50,2308,2309,2311,2313],{"class":52,"line":323},[50,2310,2001],{"class":56},[50,2312,2004],{"class":68},[50,2314,611],{"class":64},[50,2316,2318,2321,2323,2325],{"class":2317,"line":328},[52,1311],[50,2319,2320],{"class":56},"      if",[50,2322,619],{"class":64},[50,2324,2199],{"class":107},[50,2326,881],{"class":64},[50,2328,2330,2333,2335,2337],{"class":2329,"line":360},[52,1311],[50,2331,2332],{"class":107},"        cache",[50,2334,65],{"class":64},[50,2336,384],{"class":68},[50,2338,423],{"class":64},[50,2340,2342,2345,2347],{"class":2341,"line":376},[52,1311],[50,2343,2344],{"class":107},"        dirty",[50,2346,65],{"class":64},[50,2348,597],{"class":75},[50,2350,2352],{"class":2351,"line":389},[52,1311],[50,2353,2354],{"class":64},"      }\n",[50,2356,2358,2360],{"class":2357,"line":400},[52,1311],[50,2359,2011],{"class":56},[50,2361,2362],{"class":107}," cache\n",[50,2364,2365],{"class":52,"line":417},[50,2366,1027],{"class":64},[50,2368,2369],{"class":52,"line":426},[50,2370,470],{"class":64},[50,2372,2373],{"class":52,"line":438},[50,2374,86],{"emptyLinePlaceholder":85},[50,2376,2377,2379],{"class":52,"line":467},[50,2378,1589],{"class":56},[50,2380,2034],{"class":107},[50,2382,2383],{"class":52,"line":473},[50,2384,274],{"class":64},[13,2386,2387,2388,2390,2391,2393,2394,2396,2397,2399,2400,2402,2403,2405,2406,2399,2408,2212],{},"用于判断是否需要重新计算的根据就是",[25,2389,2199],{},"的值。可以看到",[25,2392,2199],{},"会在每一次重新计算后被标记为",[25,2395,831],{},"。那么什么时候应当把",[25,2398,2199],{},"置为",[25,2401,1359],{},"呢？我们知道当响应式数据发生变化时",[25,2404,1126],{},"应当重新求值。因此，在响应式数据发生变化时，就需要把",[25,2407,2199],{},[25,2409,1359],{},[13,2411,2412,2413,2415,2416,2418,2419,2421,2422,2424],{},"此处可以利用",[25,2414,723],{},"的",[25,2417,1067],{},"调度器选项来实现。当响应式数据发生变化时，会调用副作用的调度器函数（如有），因此可以在",[25,2420,1126],{},"中调用",[25,2423,723],{},"注册副作用时传入调度器：",[41,2426,2428],{"className":220,"code":2427,"language":222,"meta":46,"style":46},"function computed(getter: Function) {\n  let cache: any\n  let dirty = true\n\n  const effectFn = effect(getter, {\n    lazy: true,\n    scheduler() {\n      dirty = true\n    }\n  })\n\n  const obj = {\n    get value() {\n      if (dirty) {\n        cache = effectFn()\n        dirty = false\n      }\n      return cache\n    }\n  }\n\n  return obj\n}\n",[25,2429,2430,2446,2456,2466,2470,2486,2496,2503,2512,2516,2520,2524,2532,2540,2550,2560,2568,2572,2578,2582,2586,2590,2596],{"__ignoreMap":46},[50,2431,2432,2434,2436,2438,2440,2442,2444],{"class":52,"line":53},[50,2433,331],{"class":56},[50,2435,1909],{"class":68},[50,2437,72],{"class":64},[50,2439,1914],{"class":68},[50,2441,258],{"class":64},[50,2443,261],{"class":60},[50,2445,881],{"class":64},[50,2447,2448,2450,2452,2454],{"class":52,"line":82},[50,2449,2240],{"class":56},[50,2451,2243],{"class":107},[50,2453,258],{"class":64},[50,2455,2248],{"class":60},[50,2457,2458,2460,2462,2464],{"class":52,"line":89},[50,2459,2240],{"class":56},[50,2461,2256],{"class":107},[50,2463,65],{"class":64},[50,2465,637],{"class":75},[50,2467,2468],{"class":52,"line":104},[50,2469,86],{"emptyLinePlaceholder":85},[50,2471,2472,2474,2476,2478,2480,2482,2484],{"class":52,"line":129},[50,2473,363],{"class":56},[50,2475,366],{"class":60},[50,2477,65],{"class":64},[50,2479,723],{"class":68},[50,2481,72],{"class":64},[50,2483,1914],{"class":107},[50,2485,2281],{"class":64},[50,2487,2488,2490,2492,2494],{"class":52,"line":135},[50,2489,2286],{"class":107},[50,2491,258],{"class":64},[50,2493,1359],{"class":75},[50,2495,2063],{"class":64},[50,2497,2498,2501],{"class":52,"line":140},[50,2499,2500],{"class":68},"    scheduler",[50,2502,611],{"class":64},[50,2504,2505,2508,2510],{"class":52,"line":152},[50,2506,2507],{"class":107},"      dirty",[50,2509,65],{"class":64},[50,2511,637],{"class":75},[50,2513,2514],{"class":52,"line":163},[50,2515,1027],{"class":64},[50,2517,2518],{"class":52,"line":323},[50,2519,710],{"class":64},[50,2521,2522],{"class":52,"line":328},[50,2523,86],{"emptyLinePlaceholder":85},[50,2525,2526,2528,2530],{"class":52,"line":360},[50,2527,363],{"class":56},[50,2529,1994],{"class":60},[50,2531,241],{"class":64},[50,2533,2534,2536,2538],{"class":52,"line":376},[50,2535,2001],{"class":56},[50,2537,2004],{"class":68},[50,2539,611],{"class":64},[50,2541,2542,2544,2546,2548],{"class":52,"line":389},[50,2543,2320],{"class":56},[50,2545,619],{"class":64},[50,2547,2199],{"class":107},[50,2549,881],{"class":64},[50,2551,2552,2554,2556,2558],{"class":52,"line":400},[50,2553,2332],{"class":107},[50,2555,65],{"class":64},[50,2557,384],{"class":68},[50,2559,423],{"class":64},[50,2561,2562,2564,2566],{"class":52,"line":417},[50,2563,2344],{"class":107},[50,2565,65],{"class":64},[50,2567,597],{"class":75},[50,2569,2570],{"class":52,"line":426},[50,2571,2354],{"class":64},[50,2573,2574,2576],{"class":52,"line":438},[50,2575,2011],{"class":56},[50,2577,2362],{"class":107},[50,2579,2580],{"class":52,"line":467},[50,2581,1027],{"class":64},[50,2583,2584],{"class":52,"line":473},[50,2585,470],{"class":64},[50,2587,2588],{"class":52,"line":478},[50,2589,86],{"emptyLinePlaceholder":85},[50,2591,2592,2594],{"class":52,"line":493},[50,2593,1589],{"class":56},[50,2595,2034],{"class":107},[50,2597,2598],{"class":52,"line":506},[50,2599,274],{"class":64},[13,2601,2602,2603,2605],{},"现在，尝试多次访问",[25,2604,2180],{},"：",[41,2607,2609],{"className":220,"code":2608,"language":222,"meta":46,"style":46},"console.log(fullName.value)\nconsole.log(fullName.value)\nproxyObj.firstName = 'Jane'\nconsole.log(fullName.value)\nconsole.log(fullName.value)\n",[25,2610,2611,2629,2647,2660,2678],{"__ignoreMap":46},[50,2612,2613,2615,2617,2619,2621,2623,2625,2627],{"class":52,"line":53},[50,2614,2156],{"class":107},[50,2616,111],{"class":64},[50,2618,114],{"class":68},[50,2620,72],{"class":64},[50,2622,2165],{"class":107},[50,2624,111],{"class":64},[50,2626,124],{"class":107},[50,2628,79],{"class":64},[50,2630,2631,2633,2635,2637,2639,2641,2643,2645],{"class":52,"line":82},[50,2632,2156],{"class":107},[50,2634,111],{"class":64},[50,2636,114],{"class":68},[50,2638,72],{"class":64},[50,2640,2165],{"class":107},[50,2642,111],{"class":64},[50,2644,124],{"class":107},[50,2646,79],{"class":64},[50,2648,2649,2651,2653,2655,2657],{"class":52,"line":89},[50,2650,742],{"class":107},[50,2652,111],{"class":64},[50,2654,1661],{"class":107},[50,2656,65],{"class":64},[50,2658,2659],{"class":75},"'Jane'\n",[50,2661,2662,2664,2666,2668,2670,2672,2674,2676],{"class":52,"line":104},[50,2663,2156],{"class":107},[50,2665,111],{"class":64},[50,2667,114],{"class":68},[50,2669,72],{"class":64},[50,2671,2165],{"class":107},[50,2673,111],{"class":64},[50,2675,124],{"class":107},[50,2677,79],{"class":64},[50,2679,2680,2682,2684,2686,2688,2690,2692,2694],{"class":52,"line":129},[50,2681,2156],{"class":107},[50,2683,111],{"class":64},[50,2685,114],{"class":68},[50,2687,72],{"class":64},[50,2689,2165],{"class":107},[50,2691,111],{"class":64},[50,2693,124],{"class":107},[50,2695,79],{"class":64},[13,2697,2698],{},"副作用仅执行了两次，说明计算属性返回的值是缓存的结果。",[1153,2700,2701],{"id":2701},"嵌套的副作用",[13,2703,2704],{},"考虑以下例子，即在副作用中读取计算属性的值：",[41,2706,2708],{"className":220,"code":2707,"language":222,"meta":46,"style":46},"const fullName = computed(() => proxyObj.firstName + ' ' + proxyObj.lastName)\n\neffect(() => {\n  console.log('effect run with value: ', fullName.value)\n})\n\nproxyObj.firstName = 'Jane'\n\u002F\u002F effect run with value: John Doe\n",[25,2709,2710,2744,2748,2758,2781,2785,2789,2801],{"__ignoreMap":46},[50,2711,2712,2714,2716,2718,2720,2722,2724,2726,2728,2730,2732,2734,2736,2738,2740,2742],{"class":52,"line":53},[50,2713,57],{"class":56},[50,2715,1645],{"class":60},[50,2717,65],{"class":64},[50,2719,1126],{"class":68},[50,2721,95],{"class":64},[50,2723,98],{"class":56},[50,2725,1656],{"class":107},[50,2727,111],{"class":64},[50,2729,1661],{"class":107},[50,2731,1664],{"class":64},[50,2733,1667],{"class":75},[50,2735,1664],{"class":64},[50,2737,742],{"class":107},[50,2739,111],{"class":64},[50,2741,1676],{"class":107},[50,2743,79],{"class":64},[50,2745,2746],{"class":52,"line":82},[50,2747,86],{"emptyLinePlaceholder":85},[50,2749,2750,2752,2754,2756],{"class":52,"line":89},[50,2751,723],{"class":68},[50,2753,95],{"class":64},[50,2755,98],{"class":56},[50,2757,101],{"class":64},[50,2759,2760,2762,2764,2766,2768,2771,2773,2775,2777,2779],{"class":52,"line":104},[50,2761,108],{"class":107},[50,2763,111],{"class":64},[50,2765,114],{"class":68},[50,2767,72],{"class":64},[50,2769,2770],{"class":75},"'effect run with value: '",[50,2772,345],{"class":64},[50,2774,2165],{"class":107},[50,2776,111],{"class":64},[50,2778,124],{"class":107},[50,2780,79],{"class":64},[50,2782,2783],{"class":52,"line":129},[50,2784,132],{"class":64},[50,2786,2787],{"class":52,"line":135},[50,2788,86],{"emptyLinePlaceholder":85},[50,2790,2791,2793,2795,2797,2799],{"class":52,"line":140},[50,2792,742],{"class":107},[50,2794,111],{"class":64},[50,2796,1661],{"class":107},[50,2798,65],{"class":64},[50,2800,2659],{"class":75},[50,2802,2803],{"class":52,"line":152},[50,2804,2805],{"class":229},"\u002F\u002F effect run with value: John Doe\n",[13,2807,2808,2809,2811,2812,2814],{},"可以看到，当",[25,2810,2184],{},"发生变化时，副作用会被触发，但计算属性的值依然是旧值。我们期望的结果是当",[25,2813,2184],{},"发生变化时，计算属性的值也会发生变化。",[13,2816,2817,2818,2820,2821,2823,2824,2827,2828,2831,2832,2834],{},"分析原因，这本质上是一个副作用的嵌套。外层的副作用读取",[25,2819,2180],{},"，而",[25,2822,2165],{},"目前并非响应式数据，访问其",[25,2825,2826],{},".value","属性也不会触发",[25,2829,2830],{},"track","的依赖收集逻辑。最终，外层 effect 没有被收集到任何依赖里，即便改变了",[25,2833,2184],{},"，也不会重新执行外层 effect。",[13,2836,2837,2838,2840,2841,2843,2844,2846,2847,2849],{},"经过以上分析，不难得出结论：要使此例按预期工作，关键是需要在访问",[25,2839,2180],{},"时能够触发",[25,2842,2830],{},"的逻辑进行依赖收集。不妨手动调用",[25,2845,2830],{},"函数实现这一过程；此外前文已有叙述，当响应式数据发生变化时将调用副作用调度器函数，通过在调度器中手动调用",[25,2848,27],{},"，即可触发外层 effect 的重新执行。",[41,2851,2854],{"className":220,"code":2852,"highlights":2853,"language":222,"meta":46,"style":46},"function computed(getter: Function) {\n  let cache: any\n  let dirty = true\n\n  const effectFn = effect(getter, {\n    lazy: true,\n    scheduler() {\n      dirty = true\n      \u002F\u002F 当计算属性依赖的响应式数据发生变化时，手动调用 trigger 触发依赖的 effect 重新执行\n      trigger(obj, 'value')\n    }\n  })\n\n  const obj = {\n    get value() {\n      if (dirty) {\n        cache = effectFn()\n        dirty = false\n      }\n      \u002F\u002F 当访问计算属性的值时，手动调用 track 进行依赖收集\n      track(obj, 'value')\n      return cache\n    }\n  }\n\n  return obj\n}\n",[163,323,473,478],[25,2855,2856,2872,2882,2892,2896,2912,2922,2928,2936,2942,2959,2963,2967,2971,2979,2987,2997,3007,3015,3019,3025,3041,3047,3051,3055,3059,3065],{"__ignoreMap":46},[50,2857,2858,2860,2862,2864,2866,2868,2870],{"class":52,"line":53},[50,2859,331],{"class":56},[50,2861,1909],{"class":68},[50,2863,72],{"class":64},[50,2865,1914],{"class":68},[50,2867,258],{"class":64},[50,2869,261],{"class":60},[50,2871,881],{"class":64},[50,2873,2874,2876,2878,2880],{"class":52,"line":82},[50,2875,2240],{"class":56},[50,2877,2243],{"class":107},[50,2879,258],{"class":64},[50,2881,2248],{"class":60},[50,2883,2884,2886,2888,2890],{"class":52,"line":89},[50,2885,2240],{"class":56},[50,2887,2256],{"class":107},[50,2889,65],{"class":64},[50,2891,637],{"class":75},[50,2893,2894],{"class":52,"line":104},[50,2895,86],{"emptyLinePlaceholder":85},[50,2897,2898,2900,2902,2904,2906,2908,2910],{"class":52,"line":129},[50,2899,363],{"class":56},[50,2901,366],{"class":60},[50,2903,65],{"class":64},[50,2905,723],{"class":68},[50,2907,72],{"class":64},[50,2909,1914],{"class":107},[50,2911,2281],{"class":64},[50,2913,2914,2916,2918,2920],{"class":52,"line":135},[50,2915,2286],{"class":107},[50,2917,258],{"class":64},[50,2919,1359],{"class":75},[50,2921,2063],{"class":64},[50,2923,2924,2926],{"class":52,"line":140},[50,2925,2500],{"class":68},[50,2927,611],{"class":64},[50,2929,2930,2932,2934],{"class":52,"line":152},[50,2931,2507],{"class":107},[50,2933,65],{"class":64},[50,2935,637],{"class":75},[50,2937,2939],{"class":2938,"line":163},[52,1311],[50,2940,2941],{"class":229},"      \u002F\u002F 当计算属性依赖的响应式数据发生变化时，手动调用 trigger 触发依赖的 effect 重新执行\n",[50,2943,2945,2948,2950,2952,2954,2957],{"class":2944,"line":323},[52,1311],[50,2946,2947],{"class":68},"      trigger",[50,2949,72],{"class":64},[50,2951,2095],{"class":107},[50,2953,345],{"class":64},[50,2955,2956],{"class":75},"'value'",[50,2958,79],{"class":64},[50,2960,2961],{"class":52,"line":328},[50,2962,1027],{"class":64},[50,2964,2965],{"class":52,"line":360},[50,2966,710],{"class":64},[50,2968,2969],{"class":52,"line":376},[50,2970,86],{"emptyLinePlaceholder":85},[50,2972,2973,2975,2977],{"class":52,"line":389},[50,2974,363],{"class":56},[50,2976,1994],{"class":60},[50,2978,241],{"class":64},[50,2980,2981,2983,2985],{"class":52,"line":400},[50,2982,2001],{"class":56},[50,2984,2004],{"class":68},[50,2986,611],{"class":64},[50,2988,2989,2991,2993,2995],{"class":52,"line":417},[50,2990,2320],{"class":56},[50,2992,619],{"class":64},[50,2994,2199],{"class":107},[50,2996,881],{"class":64},[50,2998,2999,3001,3003,3005],{"class":52,"line":426},[50,3000,2332],{"class":107},[50,3002,65],{"class":64},[50,3004,384],{"class":68},[50,3006,423],{"class":64},[50,3008,3009,3011,3013],{"class":52,"line":438},[50,3010,2344],{"class":107},[50,3012,65],{"class":64},[50,3014,597],{"class":75},[50,3016,3017],{"class":52,"line":467},[50,3018,2354],{"class":64},[50,3020,3022],{"class":3021,"line":473},[52,1311],[50,3023,3024],{"class":229},"      \u002F\u002F 当访问计算属性的值时，手动调用 track 进行依赖收集\n",[50,3026,3028,3031,3033,3035,3037,3039],{"class":3027,"line":478},[52,1311],[50,3029,3030],{"class":68},"      track",[50,3032,72],{"class":64},[50,3034,2095],{"class":107},[50,3036,345],{"class":64},[50,3038,2956],{"class":75},[50,3040,79],{"class":64},[50,3042,3043,3045],{"class":52,"line":493},[50,3044,2011],{"class":56},[50,3046,2362],{"class":107},[50,3048,3049],{"class":52,"line":506},[50,3050,1027],{"class":64},[50,3052,3053],{"class":52,"line":513},[50,3054,470],{"class":64},[50,3056,3057],{"class":52,"line":790},[50,3058,86],{"emptyLinePlaceholder":85},[50,3060,3061,3063],{"class":52,"line":798},[50,3062,1589],{"class":56},[50,3064,2034],{"class":107},[50,3066,3067],{"class":52,"line":803},[50,3068,274],{"class":64},[13,3070,3071],{},"此时，再次执行本节中的例子，代码按预期工作。",[30,3073,3075,3076],{"id":3074},"侦听器watch","侦听器",[25,3077,3078],{},"watch",[13,3080,3081,3082,2212],{},"上面一节代码实现了计算属性，本节将实现侦听器",[25,3083,3078],{},[13,3085,3086],{},"回想侦听器的使用方法：",[41,3088,3090],{"className":220,"code":3089,"language":222,"meta":46,"style":46},"watch(target, (newVal, oldVal) => {\n  console.log('count changed from', oldVal, 'to', newVal)\n})\n",[25,3091,3092,3117,3145],{"__ignoreMap":46},[50,3093,3094,3096,3098,3100,3103,3106,3108,3111,3113,3115],{"class":52,"line":53},[50,3095,3078],{"class":68},[50,3097,72],{"class":64},[50,3099,863],{"class":107},[50,3101,3102],{"class":64},", (",[50,3104,3105],{"class":348},"newVal",[50,3107,345],{"class":64},[50,3109,3110],{"class":348},"oldVal",[50,3112,264],{"class":64},[50,3114,98],{"class":56},[50,3116,101],{"class":64},[50,3118,3119,3121,3123,3125,3127,3130,3132,3134,3136,3139,3141,3143],{"class":52,"line":82},[50,3120,108],{"class":107},[50,3122,111],{"class":64},[50,3124,114],{"class":68},[50,3126,72],{"class":64},[50,3128,3129],{"class":75},"'count changed from'",[50,3131,345],{"class":64},[50,3133,3110],{"class":107},[50,3135,345],{"class":64},[50,3137,3138],{"class":75},"'to'",[50,3140,345],{"class":64},[50,3142,3105],{"class":107},[50,3144,79],{"class":64},[50,3146,3147],{"class":52,"line":89},[50,3148,132],{"class":64},[13,3150,3151],{},"可以得出几个特性：",[3153,3154,3155,3158,3161,3164,3171],"ol",{},[1137,3156,3157],{},"侦听器侦听一个响应式数据或一个 getter；",[1137,3159,3160],{},"当侦听的目标发生变化时，执行传入的回调函数；",[1137,3162,3163],{},"传入回调时，可接收新值和旧值参数；",[1137,3165,3166,3167,3170],{},"可以传入",[25,3168,3169],{},"immediate","选项，在侦听器创建时立即执行回调；",[1137,3172,3166,3173,3176],{},[25,3174,3175],{},"flush","参数，指定回调函数的执行时机。",[13,3178,3179],{},"其中，第 5 条特性与 Vue 对 DOM 的更新机制相关。前 4 条特性目前可以被实现。",[1153,3181,3183],{"id":3182},"侦听对象执行回调","侦听对象，执行回调",[13,3185,3186,3187,3189,3190,3192,3193,3196,3197,3199],{},"Vue 中，",[25,3188,3078],{},"的第一个参数可以是响应式数据或一个 getter 函数。首先考虑响应式数据的情况：假设需要侦听的响应式数据是",[25,3191,742],{},"，当",[25,3194,3195],{},"proxyObj.count","被修改为 100 时应当执行回调函数。这天然符合前文中 effect 的调度器的特征（即在响应式数据发生变化时被调用）。因此要实现第 2 条功能，只需要在",[25,3198,3078],{},"的实现逻辑中，于调度器函数内调用传入的回调函数即可。",[41,3201,3203],{"className":220,"code":3202,"language":222,"meta":46,"style":46},"function watch(target, cb: () => void) {\n  effect(() => target.count, {\n    scheduler() {\n      cb()\n    }\n  })\n}\n\nwatch(proxyObj, () => {\n  console.log('count changed')\n})\n\nproxyObj.count ++\n",[25,3204,3205,3231,3249,3255,3262,3266,3270,3274,3278,3293,3308,3312,3316],{"__ignoreMap":46},[50,3206,3207,3209,3212,3214,3216,3218,3221,3224,3226,3229],{"class":52,"line":53},[50,3208,331],{"class":56},[50,3210,3211],{"class":68}," watch",[50,3213,72],{"class":64},[50,3215,863],{"class":348},[50,3217,345],{"class":64},[50,3219,3220],{"class":68},"cb",[50,3222,3223],{"class":64},": () ",[50,3225,98],{"class":56},[50,3227,3228],{"class":60}," void",[50,3230,881],{"class":64},[50,3232,3233,3236,3238,3240,3243,3245,3247],{"class":52,"line":82},[50,3234,3235],{"class":68},"  effect",[50,3237,95],{"class":64},[50,3239,98],{"class":56},[50,3241,3242],{"class":107}," target",[50,3244,111],{"class":64},[50,3246,119],{"class":107},[50,3248,2281],{"class":64},[50,3250,3251,3253],{"class":52,"line":89},[50,3252,2500],{"class":68},[50,3254,611],{"class":64},[50,3256,3257,3260],{"class":52,"line":104},[50,3258,3259],{"class":68},"      cb",[50,3261,423],{"class":64},[50,3263,3264],{"class":52,"line":129},[50,3265,1027],{"class":64},[50,3267,3268],{"class":52,"line":135},[50,3269,710],{"class":64},[50,3271,3272],{"class":52,"line":140},[50,3273,274],{"class":64},[50,3275,3276],{"class":52,"line":152},[50,3277,86],{"emptyLinePlaceholder":85},[50,3279,3280,3282,3284,3286,3289,3291],{"class":52,"line":163},[50,3281,3078],{"class":68},[50,3283,72],{"class":64},[50,3285,742],{"class":107},[50,3287,3288],{"class":64},", () ",[50,3290,98],{"class":56},[50,3292,101],{"class":64},[50,3294,3295,3297,3299,3301,3303,3306],{"class":52,"line":323},[50,3296,108],{"class":107},[50,3298,111],{"class":64},[50,3300,114],{"class":68},[50,3302,72],{"class":64},[50,3304,3305],{"class":75},"'count changed'",[50,3307,79],{"class":64},[50,3309,3310],{"class":52,"line":328},[50,3311,132],{"class":64},[50,3313,3314],{"class":52,"line":360},[50,3315,86],{"emptyLinePlaceholder":85},[50,3317,3318,3320,3322,3324],{"class":52,"line":376},[50,3319,742],{"class":107},[50,3321,111],{"class":64},[50,3323,119],{"class":107},[50,3325,3326],{"class":64}," ++\n",[13,3328,3329,3330,3333,3334,3336,3337,3339,3340,3342,3343,3345],{},"但是，代码中注册副作用的时候，硬编码了",[25,3331,3332],{},"target.count","，这使得",[25,3335,3078],{},"只能侦听",[25,3338,119],{},"属性。事实上，如果修改了",[25,3341,742],{},"的其他属性，我们也期望侦听器的回调可以执行。若要实现这一点，需要对 effect 传入的副作用函数进行封装，递归地访问",[25,3344,863],{},"中的所有属性：",[41,3347,3349],{"className":220,"code":3348,"language":222,"meta":46,"style":46},"function watch(target: object, cb: () => void) {\n  effect(() => traverse(target), {\n    scheduler() {\n      cb()\n    }\n  })\n}\n\nfunction traverse(value: any, seen = new Set\u003Cany>) {\n  \u002F\u002F 基本数据类型或已经被访问过，则不递归\n  if (typeof value !== 'object' || value === null || seen.has(value)) return\n  seen.add(value)\n  \u002F\u002F 暂不考虑数组等其他数据结构\n  \u002F\u002F value 作为普通对象，递归访问其所有属性\n  for (const k in value) {\n    traverse(value[k], seen)\n  }\n  return value\n}\n",[25,3350,3351,3377,3395,3401,3407,3411,3415,3419,3423,3456,3461,3506,3521,3526,3531,3550,3571,3575,3582],{"__ignoreMap":46},[50,3352,3353,3355,3357,3359,3361,3363,3365,3367,3369,3371,3373,3375],{"class":52,"line":53},[50,3354,331],{"class":56},[50,3356,3211],{"class":68},[50,3358,72],{"class":64},[50,3360,863],{"class":348},[50,3362,258],{"class":64},[50,3364,868],{"class":60},[50,3366,345],{"class":64},[50,3368,3220],{"class":68},[50,3370,3223],{"class":64},[50,3372,98],{"class":56},[50,3374,3228],{"class":60},[50,3376,881],{"class":64},[50,3378,3379,3381,3383,3385,3388,3390,3392],{"class":52,"line":82},[50,3380,3235],{"class":68},[50,3382,95],{"class":64},[50,3384,98],{"class":56},[50,3386,3387],{"class":68}," traverse",[50,3389,72],{"class":64},[50,3391,863],{"class":107},[50,3393,3394],{"class":64},"), {\n",[50,3396,3397,3399],{"class":52,"line":89},[50,3398,2500],{"class":68},[50,3400,611],{"class":64},[50,3402,3403,3405],{"class":52,"line":104},[50,3404,3259],{"class":68},[50,3406,423],{"class":64},[50,3408,3409],{"class":52,"line":129},[50,3410,1027],{"class":64},[50,3412,3413],{"class":52,"line":135},[50,3414,710],{"class":64},[50,3416,3417],{"class":52,"line":140},[50,3418,274],{"class":64},[50,3420,3421],{"class":52,"line":152},[50,3422,86],{"emptyLinePlaceholder":85},[50,3424,3425,3427,3429,3431,3433,3435,3438,3440,3443,3445,3447,3449,3451,3453],{"class":52,"line":163},[50,3426,331],{"class":56},[50,3428,3387],{"class":68},[50,3430,72],{"class":64},[50,3432,124],{"class":348},[50,3434,258],{"class":64},[50,3436,3437],{"class":60},"any",[50,3439,345],{"class":64},[50,3441,3442],{"class":348},"seen",[50,3444,65],{"class":64},[50,3446,544],{"class":56},[50,3448,547],{"class":107},[50,3450,550],{"class":64},[50,3452,3437],{"class":107},[50,3454,3455],{"class":64},">) {\n",[50,3457,3458],{"class":52,"line":323},[50,3459,3460],{"class":229},"  \u002F\u002F 基本数据类型或已经被访问过，则不递归\n",[50,3462,3463,3465,3467,3470,3472,3474,3477,3480,3482,3485,3488,3490,3492,3494,3497,3499,3501,3504],{"class":52,"line":328},[50,3464,616],{"class":56},[50,3466,619],{"class":64},[50,3468,3469],{"class":56},"typeof",[50,3471,2004],{"class":107},[50,3473,1002],{"class":64},[50,3475,3476],{"class":75},"'object'",[50,3478,3479],{"class":64}," || ",[50,3481,124],{"class":107},[50,3483,3484],{"class":64}," === ",[50,3486,3487],{"class":75},"null",[50,3489,3479],{"class":64},[50,3491,3442],{"class":107},[50,3493,111],{"class":64},[50,3495,3496],{"class":68},"has",[50,3498,72],{"class":64},[50,3500,124],{"class":107},[50,3502,3503],{"class":64},")) ",[50,3505,627],{"class":56},[50,3507,3508,3511,3513,3515,3517,3519],{"class":52,"line":360},[50,3509,3510],{"class":107},"  seen",[50,3512,111],{"class":64},[50,3514,781],{"class":68},[50,3516,72],{"class":64},[50,3518,124],{"class":107},[50,3520,79],{"class":64},[50,3522,3523],{"class":52,"line":376},[50,3524,3525],{"class":229},"  \u002F\u002F 暂不考虑数组等其他数据结构\n",[50,3527,3528],{"class":52,"line":389},[50,3529,3530],{"class":229},"  \u002F\u002F value 作为普通对象，递归访问其所有属性\n",[50,3532,3533,3536,3538,3540,3543,3546,3548],{"class":52,"line":400},[50,3534,3535],{"class":56},"  for",[50,3537,619],{"class":64},[50,3539,57],{"class":56},[50,3541,3542],{"class":60}," k",[50,3544,3545],{"class":56}," in",[50,3547,2004],{"class":107},[50,3549,881],{"class":64},[50,3551,3552,3555,3557,3559,3561,3564,3567,3569],{"class":52,"line":417},[50,3553,3554],{"class":68},"    traverse",[50,3556,72],{"class":64},[50,3558,124],{"class":107},[50,3560,448],{"class":64},[50,3562,3563],{"class":107},"k",[50,3565,3566],{"class":64},"], ",[50,3568,3442],{"class":107},[50,3570,79],{"class":64},[50,3572,3573],{"class":52,"line":426},[50,3574,470],{"class":64},[50,3576,3577,3579],{"class":52,"line":438},[50,3578,1589],{"class":56},[50,3580,3581],{"class":107}," value\n",[50,3583,3584],{"class":52,"line":467},[50,3585,274],{"class":64},[13,3587,3588,3589,3591,3592,2421,3594,3597],{},"接下来考虑传入的",[25,3590,863],{},"是一个 getter 函数的情况。如果用户直接传入一个 getter，那么就不需要在",[25,3593,723],{},[25,3595,3596],{},"traverse","函数，因为 getter 函数内部已经包含了对响应式数据的访问逻辑。此时需要增加一层判断：",[41,3599,3601],{"className":220,"code":3600,"language":222,"meta":46,"style":46},"function watch(target: object | Function, cb: () => void) {\n  let getter: Function;\n  if (typeof target === 'function') {\n    getter = target\n  } else {\n    getter = () => traverse(target)\n  }\n  effect(() => getter(), {\n    scheduler() {\n      cb()\n    }\n  })\n}\n",[25,3602,3603,3634,3647,3664,3674,3683,3699,3703,3716,3722,3728,3732,3736],{"__ignoreMap":46},[50,3604,3605,3607,3609,3611,3613,3615,3617,3620,3622,3624,3626,3628,3630,3632],{"class":52,"line":53},[50,3606,331],{"class":56},[50,3608,3211],{"class":68},[50,3610,72],{"class":64},[50,3612,863],{"class":348},[50,3614,258],{"class":64},[50,3616,868],{"class":60},[50,3618,3619],{"class":64}," | ",[50,3621,261],{"class":60},[50,3623,345],{"class":64},[50,3625,3220],{"class":68},[50,3627,3223],{"class":64},[50,3629,98],{"class":56},[50,3631,3228],{"class":60},[50,3633,881],{"class":64},[50,3635,3636,3638,3640,3642,3644],{"class":52,"line":82},[50,3637,2240],{"class":56},[50,3639,1966],{"class":68},[50,3641,258],{"class":64},[50,3643,261],{"class":60},[50,3645,3646],{"class":64},";\n",[50,3648,3649,3651,3653,3655,3657,3659,3662],{"class":52,"line":89},[50,3650,616],{"class":56},[50,3652,619],{"class":64},[50,3654,3469],{"class":56},[50,3656,3242],{"class":107},[50,3658,3484],{"class":64},[50,3660,3661],{"class":75},"'function'",[50,3663,881],{"class":64},[50,3665,3666,3669,3671],{"class":52,"line":104},[50,3667,3668],{"class":107},"    getter",[50,3670,65],{"class":64},[50,3672,3673],{"class":107},"target\n",[50,3675,3676,3679,3681],{"class":52,"line":129},[50,3677,3678],{"class":64},"  } ",[50,3680,1096],{"class":56},[50,3682,101],{"class":64},[50,3684,3685,3687,3689,3691,3693,3695,3697],{"class":52,"line":135},[50,3686,3668],{"class":68},[50,3688,369],{"class":64},[50,3690,98],{"class":56},[50,3692,3387],{"class":68},[50,3694,72],{"class":64},[50,3696,863],{"class":107},[50,3698,79],{"class":64},[50,3700,3701],{"class":52,"line":140},[50,3702,470],{"class":64},[50,3704,3705,3707,3709,3711,3713],{"class":52,"line":152},[50,3706,3235],{"class":68},[50,3708,95],{"class":64},[50,3710,98],{"class":56},[50,3712,1966],{"class":68},[50,3714,3715],{"class":64},"(), {\n",[50,3717,3718,3720],{"class":52,"line":163},[50,3719,2500],{"class":68},[50,3721,611],{"class":64},[50,3723,3724,3726],{"class":52,"line":323},[50,3725,3259],{"class":68},[50,3727,423],{"class":64},[50,3729,3730],{"class":52,"line":328},[50,3731,1027],{"class":64},[50,3733,3734],{"class":52,"line":360},[50,3735,710],{"class":64},[50,3737,3738],{"class":52,"line":376},[50,3739,274],{"class":64},[1153,3741,3742],{"id":3742},"支持回调参数",[13,3744,3745,3746,3748],{},"在第 3 条功能特性中，侦听器的回调函数支持包含两个参数，分别是侦听对象发生变化后的新值和变化前的旧值，这需要能够在执行 getter 的时候保存其返回值。在实现计算属性时，已经实现了类似的缓存功能，通过启用",[25,3747,1568],{},"来实现手动调用获取返回值。在此处，可以使用类似的思路：",[41,3750,3753],{"className":220,"code":3751,"highlights":3752,"language":222,"meta":46,"style":46},"function watch(target: object | Function, cb: (newVal?: any, oldVal?: any) => void) {\n  let getter: Function;\n  if (typeof target === 'function') {\n    getter = target\n  } else {\n    getter = () => traverse(target)\n  }\n  let newVal: any, oldVal: any\n  const effectFn = effect(() => getter(), {\n    lazy: true,\n    scheduler() {\n      \u002F\u002F 副作用执行时，产生新值\n      newVal = effectFn()\n      \u002F\u002F 调用回调函数\n      cb(newVal, oldVal)\n      \u002F\u002F 更新旧值\n      oldVal = newVal\n    }\n  })\n\n  \u002F\u002F 手动调用获取旧值\n  oldVal = effectFn()\n}\n\nwatch(() => proxyObj.count, (newVal, oldVal) => {\n  console.log('count changed from', oldVal, 'to', newVal)\n})\n",[360,376,389,400,417,426,478,493],[25,3754,3755,3805,3817,3833,3841,3849,3865,3869,3888,3906,3916,3922,3928,3940,3946,3961,3967,3978,3982,3986,3990,3996,4008,4012,4016,4044,4070],{"__ignoreMap":46},[50,3756,3757,3759,3761,3763,3765,3767,3769,3771,3773,3775,3777,3779,3781,3783,3785,3787,3789,3791,3793,3795,3797,3799,3801,3803],{"class":52,"line":53},[50,3758,331],{"class":56},[50,3760,3211],{"class":68},[50,3762,72],{"class":64},[50,3764,863],{"class":348},[50,3766,258],{"class":64},[50,3768,868],{"class":60},[50,3770,3619],{"class":64},[50,3772,261],{"class":60},[50,3774,345],{"class":64},[50,3776,3220],{"class":68},[50,3778,252],{"class":64},[50,3780,3105],{"class":348},[50,3782,249],{"class":56},[50,3784,258],{"class":64},[50,3786,3437],{"class":60},[50,3788,345],{"class":64},[50,3790,3110],{"class":348},[50,3792,249],{"class":56},[50,3794,258],{"class":64},[50,3796,3437],{"class":60},[50,3798,264],{"class":64},[50,3800,98],{"class":56},[50,3802,3228],{"class":60},[50,3804,881],{"class":64},[50,3806,3807,3809,3811,3813,3815],{"class":52,"line":82},[50,3808,2240],{"class":56},[50,3810,1966],{"class":68},[50,3812,258],{"class":64},[50,3814,261],{"class":60},[50,3816,3646],{"class":64},[50,3818,3819,3821,3823,3825,3827,3829,3831],{"class":52,"line":89},[50,3820,616],{"class":56},[50,3822,619],{"class":64},[50,3824,3469],{"class":56},[50,3826,3242],{"class":107},[50,3828,3484],{"class":64},[50,3830,3661],{"class":75},[50,3832,881],{"class":64},[50,3834,3835,3837,3839],{"class":52,"line":104},[50,3836,3668],{"class":107},[50,3838,65],{"class":64},[50,3840,3673],{"class":107},[50,3842,3843,3845,3847],{"class":52,"line":129},[50,3844,3678],{"class":64},[50,3846,1096],{"class":56},[50,3848,101],{"class":64},[50,3850,3851,3853,3855,3857,3859,3861,3863],{"class":52,"line":135},[50,3852,3668],{"class":68},[50,3854,369],{"class":64},[50,3856,98],{"class":56},[50,3858,3387],{"class":68},[50,3860,72],{"class":64},[50,3862,863],{"class":107},[50,3864,79],{"class":64},[50,3866,3867],{"class":52,"line":140},[50,3868,470],{"class":64},[50,3870,3871,3873,3876,3878,3880,3882,3884,3886],{"class":52,"line":152},[50,3872,2240],{"class":56},[50,3874,3875],{"class":107}," newVal",[50,3877,258],{"class":64},[50,3879,3437],{"class":60},[50,3881,345],{"class":64},[50,3883,3110],{"class":107},[50,3885,258],{"class":64},[50,3887,2248],{"class":60},[50,3889,3890,3892,3894,3896,3898,3900,3902,3904],{"class":52,"line":163},[50,3891,363],{"class":56},[50,3893,366],{"class":60},[50,3895,65],{"class":64},[50,3897,723],{"class":68},[50,3899,95],{"class":64},[50,3901,98],{"class":56},[50,3903,1966],{"class":68},[50,3905,3715],{"class":64},[50,3907,3908,3910,3912,3914],{"class":52,"line":323},[50,3909,2286],{"class":107},[50,3911,258],{"class":64},[50,3913,1359],{"class":75},[50,3915,2063],{"class":64},[50,3917,3918,3920],{"class":52,"line":328},[50,3919,2500],{"class":68},[50,3921,611],{"class":64},[50,3923,3925],{"class":3924,"line":360},[52,1311],[50,3926,3927],{"class":229},"      \u002F\u002F 副作用执行时，产生新值\n",[50,3929,3931,3934,3936,3938],{"class":3930,"line":376},[52,1311],[50,3932,3933],{"class":107},"      newVal",[50,3935,65],{"class":64},[50,3937,384],{"class":68},[50,3939,423],{"class":64},[50,3941,3943],{"class":3942,"line":389},[52,1311],[50,3944,3945],{"class":229},"      \u002F\u002F 调用回调函数\n",[50,3947,3949,3951,3953,3955,3957,3959],{"class":3948,"line":400},[52,1311],[50,3950,3259],{"class":68},[50,3952,72],{"class":64},[50,3954,3105],{"class":107},[50,3956,345],{"class":64},[50,3958,3110],{"class":107},[50,3960,79],{"class":64},[50,3962,3964],{"class":3963,"line":417},[52,1311],[50,3965,3966],{"class":229},"      \u002F\u002F 更新旧值\n",[50,3968,3970,3973,3975],{"class":3969,"line":426},[52,1311],[50,3971,3972],{"class":107},"      oldVal",[50,3974,65],{"class":64},[50,3976,3977],{"class":107},"newVal\n",[50,3979,3980],{"class":52,"line":438},[50,3981,1027],{"class":64},[50,3983,3984],{"class":52,"line":467},[50,3985,710],{"class":64},[50,3987,3988],{"class":52,"line":473},[50,3989,86],{"emptyLinePlaceholder":85},[50,3991,3993],{"class":3992,"line":478},[52,1311],[50,3994,3995],{"class":229},"  \u002F\u002F 手动调用获取旧值\n",[50,3997,3999,4002,4004,4006],{"class":3998,"line":493},[52,1311],[50,4000,4001],{"class":107},"  oldVal",[50,4003,65],{"class":64},[50,4005,384],{"class":68},[50,4007,423],{"class":64},[50,4009,4010],{"class":52,"line":506},[50,4011,274],{"class":64},[50,4013,4014],{"class":52,"line":513},[50,4015,86],{"emptyLinePlaceholder":85},[50,4017,4018,4020,4022,4024,4026,4028,4030,4032,4034,4036,4038,4040,4042],{"class":52,"line":790},[50,4019,3078],{"class":68},[50,4021,95],{"class":64},[50,4023,98],{"class":56},[50,4025,1656],{"class":107},[50,4027,111],{"class":64},[50,4029,119],{"class":107},[50,4031,3102],{"class":64},[50,4033,3105],{"class":348},[50,4035,345],{"class":64},[50,4037,3110],{"class":348},[50,4039,264],{"class":64},[50,4041,98],{"class":56},[50,4043,101],{"class":64},[50,4045,4046,4048,4050,4052,4054,4056,4058,4060,4062,4064,4066,4068],{"class":52,"line":798},[50,4047,108],{"class":107},[50,4049,111],{"class":64},[50,4051,114],{"class":68},[50,4053,72],{"class":64},[50,4055,3129],{"class":75},[50,4057,345],{"class":64},[50,4059,3110],{"class":107},[50,4061,345],{"class":64},[50,4063,3138],{"class":75},[50,4065,345],{"class":64},[50,4067,3105],{"class":107},[50,4069,79],{"class":64},[50,4071,4072],{"class":52,"line":803},[50,4073,132],{"class":64},[13,4075,4076,4077,4079,4080,4082,4083,4085,4086,4088,4089,4091],{},"在上面的代码中，已知调度器会在侦听对象发生变化时被调用，因此可以在调度器中执行",[25,4078,384],{},"获取响应式数据变化后的新值。在调用",[25,4081,3078],{},"时手动执行的",[25,4084,384],{},"发生于完成依赖收集后，此时响应式数据没有发生变化，获取到的就是初始值。此后，每次触发",[25,4087,3220],{},"后，都更新旧值，避免在下次触发",[25,4090,3220],{},"时得到到错误的旧值。",[1153,4093,4095,4096],{"id":4094},"立即执行的watch","立即执行的",[25,4097,3078],{},[13,4099,4100,4101,4103,4104,4106,4107,4109,4110,4112],{},"在 Vue 中，立即执行的",[25,4102,3078],{},"指在创建侦听器时立即执行一次回调函数。这个功能相对比较简单，只需要在",[25,4105,3078],{},"的实现逻辑中，增加一个判断：如果",[25,4108,3169],{},"选项为",[25,4111,1359],{},"，则在创建侦听器时手动调用一次回调函数即可。",[41,4114,4118],{"className":220,"code":4115,"highlights":4116,"language":222,"meta":46,"style":46},"type WatchOptions = {\n  immediate?: boolean\n}\n\nfunction watch(\n  target: object | Function,\n  cb: (newVal?: any, oldVal?: any) => void,\n  options: WatchOptions = {}\n) {\n  let getter: Function;\n  if (typeof target === 'function') {\n    getter = target\n  } else {\n    getter = () => traverse(target)\n  }\n  let newVal: any, oldVal: any\n\n  \u002F\u002F 将调度器函数封装为 job\n  const job = () => {\n    newVal = effectFn()\n    cb(newVal, oldVal)\n    oldVal = newVal\n  }\n\n  const effectFn = effect(() => getter(), {\n    lazy: true,\n    scheduler: job\n  })\n\n  \u002F\u002F 如果传入了 immediate 选项，立即调用 job 函数\n  if (options.immediate) {\n    job()\n  } else {\n    oldVal = effectFn()\n  }\n}\n",[798,803,4117],28,[25,4119,4120,4129,4140,4144,4148,4157,4172,4205,4217,4221,4233,4249,4257,4265,4281,4285,4303,4307,4312,4324,4335,4350,4359,4363,4367,4385,4396,4406,4411,4416,4422,4437,4445,4454,4465,4470],{"__ignoreMap":46},[50,4121,4122,4124,4127],{"class":52,"line":53},[50,4123,235],{"class":56},[50,4125,4126],{"class":60}," WatchOptions",[50,4128,241],{"class":64},[50,4130,4131,4134,4136,4138],{"class":52,"line":82},[50,4132,4133],{"class":107},"  immediate",[50,4135,249],{"class":56},[50,4137,258],{"class":64},[50,4139,1410],{"class":60},[50,4141,4142],{"class":52,"line":89},[50,4143,274],{"class":64},[50,4145,4146],{"class":52,"line":104},[50,4147,86],{"emptyLinePlaceholder":85},[50,4149,4150,4152,4154],{"class":52,"line":129},[50,4151,331],{"class":56},[50,4153,3211],{"class":68},[50,4155,4156],{"class":64},"(\n",[50,4158,4159,4162,4164,4166,4168,4170],{"class":52,"line":135},[50,4160,4161],{"class":348},"  target",[50,4163,258],{"class":64},[50,4165,868],{"class":60},[50,4167,3619],{"class":64},[50,4169,261],{"class":60},[50,4171,2063],{"class":64},[50,4173,4174,4177,4179,4181,4183,4185,4187,4189,4191,4193,4195,4197,4199,4201,4203],{"class":52,"line":140},[50,4175,4176],{"class":68},"  cb",[50,4178,252],{"class":64},[50,4180,3105],{"class":348},[50,4182,249],{"class":56},[50,4184,258],{"class":64},[50,4186,3437],{"class":60},[50,4188,345],{"class":64},[50,4190,3110],{"class":348},[50,4192,249],{"class":56},[50,4194,258],{"class":64},[50,4196,3437],{"class":60},[50,4198,264],{"class":64},[50,4200,98],{"class":56},[50,4202,3228],{"class":60},[50,4204,2063],{"class":64},[50,4206,4207,4209,4211,4214],{"class":52,"line":152},[50,4208,311],{"class":348},[50,4210,258],{"class":64},[50,4212,4213],{"class":60},"WatchOptions",[50,4215,4216],{"class":64}," = {}\n",[50,4218,4219],{"class":52,"line":163},[50,4220,881],{"class":64},[50,4222,4223,4225,4227,4229,4231],{"class":52,"line":323},[50,4224,2240],{"class":56},[50,4226,1966],{"class":68},[50,4228,258],{"class":64},[50,4230,261],{"class":60},[50,4232,3646],{"class":64},[50,4234,4235,4237,4239,4241,4243,4245,4247],{"class":52,"line":328},[50,4236,616],{"class":56},[50,4238,619],{"class":64},[50,4240,3469],{"class":56},[50,4242,3242],{"class":107},[50,4244,3484],{"class":64},[50,4246,3661],{"class":75},[50,4248,881],{"class":64},[50,4250,4251,4253,4255],{"class":52,"line":360},[50,4252,3668],{"class":107},[50,4254,65],{"class":64},[50,4256,3673],{"class":107},[50,4258,4259,4261,4263],{"class":52,"line":376},[50,4260,3678],{"class":64},[50,4262,1096],{"class":56},[50,4264,101],{"class":64},[50,4266,4267,4269,4271,4273,4275,4277,4279],{"class":52,"line":389},[50,4268,3668],{"class":68},[50,4270,369],{"class":64},[50,4272,98],{"class":56},[50,4274,3387],{"class":68},[50,4276,72],{"class":64},[50,4278,863],{"class":107},[50,4280,79],{"class":64},[50,4282,4283],{"class":52,"line":400},[50,4284,470],{"class":64},[50,4286,4287,4289,4291,4293,4295,4297,4299,4301],{"class":52,"line":417},[50,4288,2240],{"class":56},[50,4290,3875],{"class":107},[50,4292,258],{"class":64},[50,4294,3437],{"class":60},[50,4296,345],{"class":64},[50,4298,3110],{"class":107},[50,4300,258],{"class":64},[50,4302,2248],{"class":60},[50,4304,4305],{"class":52,"line":426},[50,4306,86],{"emptyLinePlaceholder":85},[50,4308,4309],{"class":52,"line":438},[50,4310,4311],{"class":229},"  \u002F\u002F 将调度器函数封装为 job\n",[50,4313,4314,4316,4318,4320,4322],{"class":52,"line":467},[50,4315,363],{"class":56},[50,4317,679],{"class":68},[50,4319,369],{"class":64},[50,4321,98],{"class":56},[50,4323,101],{"class":64},[50,4325,4326,4329,4331,4333],{"class":52,"line":473},[50,4327,4328],{"class":107},"    newVal",[50,4330,65],{"class":64},[50,4332,384],{"class":68},[50,4334,423],{"class":64},[50,4336,4337,4340,4342,4344,4346,4348],{"class":52,"line":478},[50,4338,4339],{"class":68},"    cb",[50,4341,72],{"class":64},[50,4343,3105],{"class":107},[50,4345,345],{"class":64},[50,4347,3110],{"class":107},[50,4349,79],{"class":64},[50,4351,4352,4355,4357],{"class":52,"line":493},[50,4353,4354],{"class":107},"    oldVal",[50,4356,65],{"class":64},[50,4358,3977],{"class":107},[50,4360,4361],{"class":52,"line":506},[50,4362,470],{"class":64},[50,4364,4365],{"class":52,"line":513},[50,4366,86],{"emptyLinePlaceholder":85},[50,4368,4369,4371,4373,4375,4377,4379,4381,4383],{"class":52,"line":790},[50,4370,363],{"class":56},[50,4372,366],{"class":60},[50,4374,65],{"class":64},[50,4376,723],{"class":68},[50,4378,95],{"class":64},[50,4380,98],{"class":56},[50,4382,1966],{"class":68},[50,4384,3715],{"class":64},[50,4386,4388,4390,4392,4394],{"class":4387,"line":798},[52,1311],[50,4389,2286],{"class":107},[50,4391,258],{"class":64},[50,4393,1359],{"class":75},[50,4395,2063],{"class":64},[50,4397,4399,4401,4403],{"class":4398,"line":803},[52,1311],[50,4400,2500],{"class":107},[50,4402,258],{"class":64},[50,4404,4405],{"class":107},"job\n",[50,4407,4409],{"class":4408,"line":4117},[52,1311],[50,4410,710],{"class":64},[50,4412,4414],{"class":52,"line":4413},29,[50,4415,86],{"emptyLinePlaceholder":85},[50,4417,4419],{"class":52,"line":4418},30,[50,4420,4421],{"class":229},"  \u002F\u002F 如果传入了 immediate 选项，立即调用 job 函数\n",[50,4423,4425,4427,4429,4431,4433,4435],{"class":52,"line":4424},31,[50,4426,616],{"class":56},[50,4428,619],{"class":64},[50,4430,349],{"class":107},[50,4432,111],{"class":64},[50,4434,3169],{"class":107},[50,4436,881],{"class":64},[50,4438,4440,4443],{"class":52,"line":4439},32,[50,4441,4442],{"class":68},"    job",[50,4444,423],{"class":64},[50,4446,4448,4450,4452],{"class":52,"line":4447},33,[50,4449,3678],{"class":64},[50,4451,1096],{"class":56},[50,4453,101],{"class":64},[50,4455,4457,4459,4461,4463],{"class":52,"line":4456},34,[50,4458,4354],{"class":107},[50,4460,65],{"class":64},[50,4462,384],{"class":68},[50,4464,423],{"class":64},[50,4466,4468],{"class":52,"line":4467},35,[50,4469,470],{"class":64},[50,4471,4473],{"class":52,"line":4472},36,[50,4474,274],{"class":64},[13,4476,4477,4478,4481,4482,2212],{},"值得注意的一点是，设置了立即执行并调用",[25,4479,4480],{},"job()","时，旧值应当是",[25,4483,4484],{},"undefined",[30,4486,4487],{"id":4487},"目前为止的完整代码",[13,4489,4490],{},"响应式系统核心：",[41,4492,4494],{"className":220,"code":4493,"language":222,"meta":46,"style":46},"\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 副作用函数注册时，允许传入`options`配置项，通过`options.scheduler`指定自定义调度器\ntype EffectRegisterOptions = {\n  scheduler?: (fn: Function) => void\n  lazy?: boolean\n}\n\u002F\u002F 更新副作用函数的类型，使用`options`存储注册时的配置项\ntype EffectFn = Function & {\n  deps: Deps[]\n  options: EffectRegisterOptions\n}\n\nconst obj: Record\u003CPropertyKey, any> = {\n  firstName: 'John',\n  lastName: 'Doe'\n}\n\nconst bucket: Bucket = new WeakMap()\nlet activeEffect: EffectFn\nconst effectStack: EffectFn[] = []\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, options: EffectRegisterOptions = {}) {\n  const effectFn: EffectFn = () => {\n    cleanup(effectFn)\n    activeEffect = effectFn\n    effectStack.push(effectFn)\n    const res = fn()\n    effectStack.pop()\n    activeEffect = effectStack[effectStack.length - 1]\n    return res\n  }\n  effectFn.deps = []\n  effectFn.options = options\n  if (!options.lazy) {\n    effectFn()\n  }\n  return 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  console.log(activeEffect)\n  \u002F\u002F 错误：activeEffect.deps 是 undefined，activeEffect 是一个函数，并非预期的`EffectFn`类型\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) => {\n    if (effectFn.options.scheduler) {\n      effectFn.options.scheduler(effectFn)\n    } else {\n      effectFn()\n    }\n  })\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",[25,4495,4496,4501,4525,4530,4552,4557,4575,4579,4587,4607,4617,4621,4625,4637,4647,4655,4659,4663,4685,4695,4703,4707,4711,4732,4744,4758,4762,4779,4820,4840,4856,4860,4877,4881,4885,4909,4925,4936,4945,4960,4973,4984,5007,5014,5019,5030,5043,5058,5065,5070,5077,5082,5087,5113,5126,5147,5158,5187,5192,5213,5224,5250,5255,5270,5285,5291,5311,5316,5321,5352,5373,5386,5407,5420,5439,5458,5473,5488,5493,5498,5518,5537,5556,5565,5572,5577,5582,5587,5592,5611,5635,5651,5664,5670,5698,5714,5730,5738,5743],{"__ignoreMap":46},[50,4497,4498],{"class":52,"line":53},[50,4499,4500],{"class":229},"\u002F\u002F 全局存储桶，保存每个对象的依赖关系\n",[50,4502,4503,4505,4508,4510,4513,4515,4517,4519,4522],{"class":52,"line":82},[50,4504,235],{"class":56},[50,4506,4507],{"class":60}," Bucket",[50,4509,65],{"class":64},[50,4511,4512],{"class":60},"WeakMap",[50,4514,550],{"class":64},[50,4516,868],{"class":60},[50,4518,345],{"class":64},[50,4520,4521],{"class":60},"DepsMap",[50,4523,4524],{"class":64},">\n",[50,4526,4527],{"class":52,"line":89},[50,4528,4529],{"class":229},"\u002F\u002F 响应式对象中，每个属性和其对应的副作用函数集合的依赖关系表\n",[50,4531,4532,4534,4537,4539,4542,4544,4546,4548,4550],{"class":52,"line":104},[50,4533,235],{"class":56},[50,4535,4536],{"class":60}," DepsMap",[50,4538,65],{"class":64},[50,4540,4541],{"class":60},"Map",[50,4543,550],{"class":64},[50,4545,878],{"class":60},[50,4547,345],{"class":64},[50,4549,303],{"class":60},[50,4551,4524],{"class":64},[50,4553,4554],{"class":52,"line":129},[50,4555,4556],{"class":229},"\u002F\u002F 每个属性的副作用函数集合\n",[50,4558,4559,4561,4564,4566,4569,4571,4573],{"class":52,"line":135},[50,4560,235],{"class":56},[50,4562,4563],{"class":60}," Deps",[50,4565,65],{"class":64},[50,4567,4568],{"class":60},"Set",[50,4570,550],{"class":64},[50,4572,969],{"class":60},[50,4574,4524],{"class":64},[50,4576,4577],{"class":52,"line":140},[50,4578,230],{"class":229},[50,4580,4581,4583,4585],{"class":52,"line":152},[50,4582,235],{"class":56},[50,4584,238],{"class":60},[50,4586,241],{"class":64},[50,4588,4589,4591,4593,4595,4597,4599,4601,4603,4605],{"class":52,"line":163},[50,4590,246],{"class":68},[50,4592,249],{"class":56},[50,4594,252],{"class":64},[50,4596,255],{"class":68},[50,4598,258],{"class":64},[50,4600,261],{"class":60},[50,4602,264],{"class":64},[50,4604,98],{"class":56},[50,4606,269],{"class":60},[50,4608,4609,4611,4613,4615],{"class":52,"line":323},[50,4610,1403],{"class":107},[50,4612,249],{"class":56},[50,4614,258],{"class":64},[50,4616,1410],{"class":60},[50,4618,4619],{"class":52,"line":328},[50,4620,274],{"class":64},[50,4622,4623],{"class":52,"line":360},[50,4624,279],{"class":229},[50,4626,4627,4629,4631,4633,4635],{"class":52,"line":376},[50,4628,235],{"class":56},[50,4630,286],{"class":60},[50,4632,65],{"class":64},[50,4634,261],{"class":60},[50,4636,293],{"class":64},[50,4638,4639,4641,4643,4645],{"class":52,"line":389},[50,4640,298],{"class":107},[50,4642,258],{"class":64},[50,4644,303],{"class":60},[50,4646,306],{"class":64},[50,4648,4649,4651,4653],{"class":52,"line":400},[50,4650,311],{"class":107},[50,4652,258],{"class":64},[50,4654,316],{"class":60},[50,4656,4657],{"class":52,"line":417},[50,4658,274],{"class":64},[50,4660,4661],{"class":52,"line":426},[50,4662,86],{"emptyLinePlaceholder":85},[50,4664,4665,4667,4669,4671,4674,4676,4678,4680,4682],{"class":52,"line":438},[50,4666,57],{"class":56},[50,4668,1994],{"class":60},[50,4670,258],{"class":64},[50,4672,4673],{"class":60},"Record",[50,4675,550],{"class":64},[50,4677,878],{"class":60},[50,4679,345],{"class":64},[50,4681,3437],{"class":60},[50,4683,4684],{"class":64},"> = {\n",[50,4686,4687,4689,4691,4693],{"class":52,"line":467},[50,4688,2055],{"class":107},[50,4690,258],{"class":64},[50,4692,2060],{"class":75},[50,4694,2063],{"class":64},[50,4696,4697,4699,4701],{"class":52,"line":473},[50,4698,2068],{"class":107},[50,4700,258],{"class":64},[50,4702,2073],{"class":75},[50,4704,4705],{"class":52,"line":478},[50,4706,274],{"class":64},[50,4708,4709],{"class":52,"line":493},[50,4710,86],{"emptyLinePlaceholder":85},[50,4712,4713,4715,4718,4720,4723,4725,4727,4730],{"class":52,"line":506},[50,4714,57],{"class":56},[50,4716,4717],{"class":60}," bucket",[50,4719,258],{"class":64},[50,4721,4722],{"class":60},"Bucket",[50,4724,65],{"class":64},[50,4726,544],{"class":56},[50,4728,4729],{"class":68}," WeakMap",[50,4731,423],{"class":64},[50,4733,4734,4736,4739,4741],{"class":52,"line":513},[50,4735,589],{"class":56},[50,4737,4738],{"class":107}," activeEffect",[50,4740,258],{"class":64},[50,4742,4743],{"class":60},"EffectFn\n",[50,4745,4746,4748,4751,4753,4755],{"class":52,"line":790},[50,4747,57],{"class":56},[50,4749,4750],{"class":60}," effectStack",[50,4752,258],{"class":64},[50,4754,969],{"class":60},[50,4756,4757],{"class":64},"[] = []\n",[50,4759,4760],{"class":52,"line":798},[50,4761,86],{"emptyLinePlaceholder":85},[50,4763,4764,4766,4769,4771,4773,4775,4777],{"class":52,"line":803},[50,4765,331],{"class":56},[50,4767,4768],{"class":68}," cleanup",[50,4770,72],{"class":64},[50,4772,384],{"class":348},[50,4774,258],{"class":64},[50,4776,969],{"class":60},[50,4778,881],{"class":64},[50,4780,4781,4783,4785,4787,4790,4792,4794,4797,4800,4803,4805,4807,4809,4811,4813,4815,4817],{"class":52,"line":4117},[50,4782,3535],{"class":56},[50,4784,619],{"class":64},[50,4786,589],{"class":56},[50,4788,4789],{"class":107}," i",[50,4791,65],{"class":64},[50,4793,76],{"class":75},[50,4795,4796],{"class":64},"; ",[50,4798,4799],{"class":107},"i",[50,4801,4802],{"class":64}," \u003C ",[50,4804,384],{"class":107},[50,4806,111],{"class":64},[50,4808,500],{"class":107},[50,4810,111],{"class":64},[50,4812,455],{"class":107},[50,4814,4796],{"class":64},[50,4816,4799],{"class":107},[50,4818,4819],{"class":64},"++) {\n",[50,4821,4822,4824,4826,4828,4830,4832,4834,4836,4838],{"class":52,"line":4413},[50,4823,1770],{"class":56},[50,4825,925],{"class":60},[50,4827,65],{"class":64},[50,4829,384],{"class":107},[50,4831,111],{"class":64},[50,4833,500],{"class":107},[50,4835,448],{"class":64},[50,4837,4799],{"class":107},[50,4839,464],{"class":64},[50,4841,4842,4845,4847,4850,4852,4854],{"class":52,"line":4418},[50,4843,4844],{"class":107},"    deps",[50,4846,111],{"class":64},[50,4848,4849],{"class":68},"delete",[50,4851,72],{"class":64},[50,4853,384],{"class":107},[50,4855,79],{"class":64},[50,4857,4858],{"class":52,"line":4424},[50,4859,470],{"class":64},[50,4861,4862,4864,4866,4868,4870,4872,4874],{"class":52,"line":4439},[50,4863,481],{"class":107},[50,4865,111],{"class":64},[50,4867,500],{"class":107},[50,4869,111],{"class":64},[50,4871,455],{"class":107},[50,4873,65],{"class":64},[50,4875,4876],{"class":75},"0\n",[50,4878,4879],{"class":52,"line":4447},[50,4880,274],{"class":64},[50,4882,4883],{"class":52,"line":4456},[50,4884,86],{"emptyLinePlaceholder":85},[50,4886,4887,4889,4891,4893,4895,4897,4899,4901,4903,4905,4907],{"class":52,"line":4467},[50,4888,331],{"class":56},[50,4890,334],{"class":68},[50,4892,72],{"class":64},[50,4894,255],{"class":68},[50,4896,258],{"class":64},[50,4898,261],{"class":60},[50,4900,345],{"class":64},[50,4902,349],{"class":348},[50,4904,258],{"class":64},[50,4906,354],{"class":60},[50,4908,357],{"class":64},[50,4910,4911,4913,4915,4917,4919,4921,4923],{"class":52,"line":4472},[50,4912,363],{"class":56},[50,4914,366],{"class":68},[50,4916,258],{"class":64},[50,4918,969],{"class":60},[50,4920,369],{"class":64},[50,4922,98],{"class":56},[50,4924,101],{"class":64},[50,4926,4928,4930,4932,4934],{"class":52,"line":4927},37,[50,4929,379],{"class":68},[50,4931,72],{"class":64},[50,4933,384],{"class":107},[50,4935,79],{"class":64},[50,4937,4939,4941,4943],{"class":52,"line":4938},38,[50,4940,392],{"class":107},[50,4942,65],{"class":64},[50,4944,397],{"class":107},[50,4946,4948,4950,4952,4954,4956,4958],{"class":52,"line":4947},39,[50,4949,403],{"class":107},[50,4951,111],{"class":64},[50,4953,408],{"class":68},[50,4955,72],{"class":64},[50,4957,384],{"class":107},[50,4959,79],{"class":64},[50,4961,4963,4965,4967,4969,4971],{"class":52,"line":4962},40,[50,4964,1770],{"class":56},[50,4966,1773],{"class":60},[50,4968,65],{"class":64},[50,4970,255],{"class":68},[50,4972,423],{"class":64},[50,4974,4976,4978,4980,4982],{"class":52,"line":4975},41,[50,4977,403],{"class":107},[50,4979,111],{"class":64},[50,4981,433],{"class":68},[50,4983,423],{"class":64},[50,4985,4987,4989,4991,4993,4995,4997,4999,5001,5003,5005],{"class":52,"line":4986},42,[50,4988,392],{"class":107},[50,4990,65],{"class":64},[50,4992,445],{"class":107},[50,4994,448],{"class":64},[50,4996,445],{"class":107},[50,4998,111],{"class":64},[50,5000,455],{"class":107},[50,5002,458],{"class":64},[50,5004,461],{"class":75},[50,5006,464],{"class":64},[50,5008,5010,5012],{"class":52,"line":5009},43,[50,5011,1823],{"class":56},[50,5013,1826],{"class":107},[50,5015,5017],{"class":52,"line":5016},44,[50,5018,470],{"class":64},[50,5020,5022,5024,5026,5028],{"class":52,"line":5021},45,[50,5023,481],{"class":107},[50,5025,111],{"class":64},[50,5027,500],{"class":107},[50,5029,503],{"class":64},[50,5031,5033,5035,5037,5039,5041],{"class":52,"line":5032},46,[50,5034,481],{"class":107},[50,5036,111],{"class":64},[50,5038,349],{"class":107},[50,5040,65],{"class":64},[50,5042,490],{"class":107},[50,5044,5046,5048,5050,5052,5054,5056],{"class":52,"line":5045},47,[50,5047,616],{"class":56},[50,5049,911],{"class":64},[50,5051,349],{"class":107},[50,5053,111],{"class":64},[50,5055,1568],{"class":107},[50,5057,881],{"class":64},[50,5059,5061,5063],{"class":52,"line":5060},48,[50,5062,1576],{"class":68},[50,5064,423],{"class":64},[50,5066,5068],{"class":52,"line":5067},49,[50,5069,470],{"class":64},[50,5071,5073,5075],{"class":52,"line":5072},50,[50,5074,1589],{"class":56},[50,5076,1592],{"class":107},[50,5078,5080],{"class":52,"line":5079},51,[50,5081,274],{"class":64},[50,5083,5085],{"class":52,"line":5084},52,[50,5086,86],{"emptyLinePlaceholder":85},[50,5088,5090,5092,5095,5097,5099,5101,5103,5105,5107,5109,5111],{"class":52,"line":5089},53,[50,5091,331],{"class":56},[50,5093,5094],{"class":68}," track",[50,5096,72],{"class":64},[50,5098,863],{"class":348},[50,5100,258],{"class":64},[50,5102,868],{"class":60},[50,5104,345],{"class":64},[50,5106,873],{"class":348},[50,5108,258],{"class":64},[50,5110,878],{"class":60},[50,5112,881],{"class":64},[50,5114,5116,5118,5120,5122,5124],{"class":52,"line":5115},54,[50,5117,616],{"class":56},[50,5119,911],{"class":64},[50,5121,1005],{"class":107},[50,5123,264],{"class":64},[50,5125,627],{"class":56},[50,5127,5129,5131,5133,5135,5137,5139,5141,5143,5145],{"class":52,"line":5128},55,[50,5130,2240],{"class":56},[50,5132,888],{"class":107},[50,5134,65],{"class":64},[50,5136,893],{"class":107},[50,5138,111],{"class":64},[50,5140,898],{"class":68},[50,5142,72],{"class":64},[50,5144,863],{"class":107},[50,5146,79],{"class":64},[50,5148,5150,5152,5154,5156],{"class":52,"line":5149},56,[50,5151,616],{"class":56},[50,5153,911],{"class":64},[50,5155,914],{"class":107},[50,5157,881],{"class":64},[50,5159,5161,5164,5166,5169,5171,5173,5175,5177,5179,5181,5184],{"class":52,"line":5160},57,[50,5162,5163],{"class":107},"    bucket",[50,5165,111],{"class":64},[50,5167,5168],{"class":68},"set",[50,5170,72],{"class":64},[50,5172,863],{"class":107},[50,5174,3102],{"class":64},[50,5176,914],{"class":107},[50,5178,65],{"class":64},[50,5180,544],{"class":56},[50,5182,5183],{"class":68}," Map",[50,5185,5186],{"class":64},"()))\n",[50,5188,5190],{"class":52,"line":5189},58,[50,5191,470],{"class":64},[50,5193,5195,5197,5199,5201,5203,5205,5207,5209,5211],{"class":52,"line":5194},59,[50,5196,2240],{"class":56},[50,5198,925],{"class":107},[50,5200,65],{"class":64},[50,5202,914],{"class":107},[50,5204,111],{"class":64},[50,5206,898],{"class":68},[50,5208,72],{"class":64},[50,5210,873],{"class":107},[50,5212,79],{"class":64},[50,5214,5216,5218,5220,5222],{"class":52,"line":5215},60,[50,5217,616],{"class":56},[50,5219,911],{"class":64},[50,5221,500],{"class":107},[50,5223,881],{"class":64},[50,5225,5227,5230,5232,5234,5236,5238,5240,5242,5244,5246,5248],{"class":52,"line":5226},61,[50,5228,5229],{"class":107},"    depsMap",[50,5231,111],{"class":64},[50,5233,5168],{"class":68},[50,5235,72],{"class":64},[50,5237,873],{"class":107},[50,5239,3102],{"class":64},[50,5241,500],{"class":107},[50,5243,65],{"class":64},[50,5245,544],{"class":56},[50,5247,547],{"class":68},[50,5249,5186],{"class":64},[50,5251,5253],{"class":52,"line":5252},62,[50,5254,470],{"class":64},[50,5256,5258,5260,5262,5264,5266,5268],{"class":52,"line":5257},63,[50,5259,298],{"class":107},[50,5261,111],{"class":64},[50,5263,781],{"class":68},[50,5265,72],{"class":64},[50,5267,1005],{"class":107},[50,5269,79],{"class":64},[50,5271,5273,5275,5277,5279,5281,5283],{"class":52,"line":5272},64,[50,5274,108],{"class":107},[50,5276,111],{"class":64},[50,5278,114],{"class":68},[50,5280,72],{"class":64},[50,5282,1005],{"class":107},[50,5284,79],{"class":64},[50,5286,5288],{"class":52,"line":5287},65,[50,5289,5290],{"class":229},"  \u002F\u002F 错误：activeEffect.deps 是 undefined，activeEffect 是一个函数，并非预期的`EffectFn`类型\n",[50,5292,5294,5297,5299,5301,5303,5305,5307,5309],{"class":52,"line":5293},66,[50,5295,5296],{"class":107},"  activeEffect",[50,5298,111],{"class":64},[50,5300,500],{"class":107},[50,5302,111],{"class":64},[50,5304,408],{"class":68},[50,5306,72],{"class":64},[50,5308,500],{"class":107},[50,5310,79],{"class":64},[50,5312,5314],{"class":52,"line":5313},67,[50,5315,274],{"class":64},[50,5317,5319],{"class":52,"line":5318},68,[50,5320,86],{"emptyLinePlaceholder":85},[50,5322,5324,5326,5328,5330,5332,5334,5336,5338,5340,5342,5344,5347,5350],{"class":52,"line":5323},69,[50,5325,331],{"class":56},[50,5327,858],{"class":68},[50,5329,72],{"class":64},[50,5331,863],{"class":348},[50,5333,258],{"class":64},[50,5335,868],{"class":60},[50,5337,345],{"class":64},[50,5339,873],{"class":348},[50,5341,258],{"class":64},[50,5343,878],{"class":60},[50,5345,5346],{"class":64},"): ",[50,5348,5349],{"class":60},"void",[50,5351,101],{"class":64},[50,5353,5355,5357,5359,5361,5363,5365,5367,5369,5371],{"class":52,"line":5354},70,[50,5356,363],{"class":56},[50,5358,888],{"class":60},[50,5360,65],{"class":64},[50,5362,893],{"class":107},[50,5364,111],{"class":64},[50,5366,898],{"class":68},[50,5368,72],{"class":64},[50,5370,863],{"class":107},[50,5372,79],{"class":64},[50,5374,5376,5378,5380,5382,5384],{"class":52,"line":5375},71,[50,5377,616],{"class":56},[50,5379,911],{"class":64},[50,5381,914],{"class":107},[50,5383,264],{"class":64},[50,5385,627],{"class":56},[50,5387,5389,5391,5393,5395,5397,5399,5401,5403,5405],{"class":52,"line":5388},72,[50,5390,363],{"class":56},[50,5392,925],{"class":60},[50,5394,65],{"class":64},[50,5396,914],{"class":107},[50,5398,111],{"class":64},[50,5400,898],{"class":68},[50,5402,72],{"class":64},[50,5404,873],{"class":107},[50,5406,79],{"class":64},[50,5408,5410,5412,5414,5416,5418],{"class":52,"line":5409},73,[50,5411,616],{"class":56},[50,5413,911],{"class":64},[50,5415,500],{"class":107},[50,5417,264],{"class":64},[50,5419,627],{"class":56},[50,5421,5423,5425,5427,5429,5431,5433,5435,5437],{"class":52,"line":5422},74,[50,5424,363],{"class":56},[50,5426,958],{"class":60},[50,5428,65],{"class":64},[50,5430,544],{"class":56},[50,5432,547],{"class":68},[50,5434,550],{"class":64},[50,5436,969],{"class":60},[50,5438,555],{"class":64},[50,5440,5442,5444,5446,5448,5450,5452,5454,5456],{"class":52,"line":5441},75,[50,5443,298],{"class":107},[50,5445,111],{"class":64},[50,5447,668],{"class":68},[50,5449,982],{"class":64},[50,5451,384],{"class":348},[50,5453,264],{"class":64},[50,5455,98],{"class":56},[50,5457,101],{"class":64},[50,5459,5461,5463,5465,5467,5469,5471],{"class":52,"line":5460},76,[50,5462,995],{"class":56},[50,5464,619],{"class":64},[50,5466,384],{"class":107},[50,5468,1002],{"class":64},[50,5470,1005],{"class":107},[50,5472,881],{"class":64},[50,5474,5476,5478,5480,5482,5484,5486],{"class":52,"line":5475},77,[50,5477,1012],{"class":107},[50,5479,111],{"class":64},[50,5481,781],{"class":68},[50,5483,72],{"class":64},[50,5485,384],{"class":107},[50,5487,79],{"class":64},[50,5489,5491],{"class":52,"line":5490},78,[50,5492,1027],{"class":64},[50,5494,5496],{"class":52,"line":5495},79,[50,5497,710],{"class":64},[50,5499,5501,5504,5506,5508,5510,5512,5514,5516],{"class":52,"line":5500},80,[50,5502,5503],{"class":107},"    effectsToRun",[50,5505,111],{"class":64},[50,5507,668],{"class":68},[50,5509,982],{"class":64},[50,5511,384],{"class":348},[50,5513,264],{"class":64},[50,5515,98],{"class":56},[50,5517,101],{"class":64},[50,5519,5521,5523,5525,5527,5529,5531,5533,5535],{"class":52,"line":5520},81,[50,5522,995],{"class":56},[50,5524,619],{"class":64},[50,5526,384],{"class":107},[50,5528,111],{"class":64},[50,5530,349],{"class":107},[50,5532,111],{"class":64},[50,5534,1067],{"class":107},[50,5536,881],{"class":64},[50,5538,5540,5542,5544,5546,5548,5550,5552,5554],{"class":52,"line":5539},82,[50,5541,1074],{"class":107},[50,5543,111],{"class":64},[50,5545,349],{"class":107},[50,5547,111],{"class":64},[50,5549,1067],{"class":68},[50,5551,72],{"class":64},[50,5553,384],{"class":107},[50,5555,79],{"class":64},[50,5557,5559,5561,5563],{"class":52,"line":5558},83,[50,5560,1093],{"class":64},[50,5562,1096],{"class":56},[50,5564,101],{"class":64},[50,5566,5568,5570],{"class":52,"line":5567},84,[50,5569,1074],{"class":68},[50,5571,423],{"class":64},[50,5573,5575],{"class":52,"line":5574},85,[50,5576,1027],{"class":64},[50,5578,5580],{"class":52,"line":5579},86,[50,5581,710],{"class":64},[50,5583,5585],{"class":52,"line":5584},87,[50,5586,274],{"class":64},[50,5588,5590],{"class":52,"line":5589},88,[50,5591,86],{"emptyLinePlaceholder":85},[50,5593,5595,5597,5599,5601,5603,5605,5607,5609],{"class":52,"line":5594},89,[50,5596,57],{"class":56},[50,5598,1656],{"class":60},[50,5600,65],{"class":64},[50,5602,544],{"class":56},[50,5604,2090],{"class":68},[50,5606,72],{"class":64},[50,5608,2095],{"class":107},[50,5610,2281],{"class":64},[50,5612,5614,5617,5619,5621,5623,5625,5627,5629,5631,5633],{"class":52,"line":5613},90,[50,5615,5616],{"class":68},"  get",[50,5618,252],{"class":64},[50,5620,863],{"class":348},[50,5622,345],{"class":64},[50,5624,873],{"class":348},[50,5626,258],{"class":64},[50,5628,878],{"class":60},[50,5630,264],{"class":64},[50,5632,98],{"class":56},[50,5634,101],{"class":64},[50,5636,5638,5641,5643,5645,5647,5649],{"class":52,"line":5637},91,[50,5639,5640],{"class":68},"    track",[50,5642,72],{"class":64},[50,5644,863],{"class":107},[50,5646,345],{"class":64},[50,5648,873],{"class":107},[50,5650,79],{"class":64},[50,5652,5654,5656,5658,5660,5662],{"class":52,"line":5653},92,[50,5655,1823],{"class":56},[50,5657,3242],{"class":107},[50,5659,448],{"class":64},[50,5661,873],{"class":107},[50,5663,464],{"class":64},[50,5665,5667],{"class":52,"line":5666},93,[50,5668,5669],{"class":64},"  },\n",[50,5671,5673,5676,5678,5680,5682,5684,5686,5688,5690,5692,5694,5696],{"class":52,"line":5672},94,[50,5674,5675],{"class":68},"  set",[50,5677,252],{"class":64},[50,5679,863],{"class":348},[50,5681,345],{"class":64},[50,5683,873],{"class":348},[50,5685,258],{"class":64},[50,5687,878],{"class":60},[50,5689,345],{"class":64},[50,5691,124],{"class":348},[50,5693,264],{"class":64},[50,5695,98],{"class":56},[50,5697,101],{"class":64},[50,5699,5701,5704,5706,5708,5711],{"class":52,"line":5700},95,[50,5702,5703],{"class":107},"    target",[50,5705,448],{"class":64},[50,5707,873],{"class":107},[50,5709,5710],{"class":64},"] = ",[50,5712,5713],{"class":107},"value\n",[50,5715,5717,5720,5722,5724,5726,5728],{"class":52,"line":5716},96,[50,5718,5719],{"class":68},"    trigger",[50,5721,72],{"class":64},[50,5723,863],{"class":107},[50,5725,345],{"class":64},[50,5727,873],{"class":107},[50,5729,79],{"class":64},[50,5731,5733,5735],{"class":52,"line":5732},97,[50,5734,1823],{"class":56},[50,5736,5737],{"class":75}," true\n",[50,5739,5741],{"class":52,"line":5740},98,[50,5742,470],{"class":64},[50,5744,5746],{"class":52,"line":5745},99,[50,5747,132],{"class":64},[13,5749,5750],{},"计算属性：",[41,5752,5754],{"className":220,"code":5753,"language":222,"meta":46,"style":46},"function computed(getter: Function) {\n  let dirty = true\n  let cache: any = undefined\n\n  const effectFn = effect(() => {\n    console.log('effectFn invoked')\n    return getter()\n  }, {\n    lazy: true,\n    scheduler() {\n      dirty = true\n      trigger(obj, 'value')\n    }\n  })\n  \n  const obj = {\n    get value() {\n      if (dirty) {\n        cache = effectFn()\n        dirty = false\n      }\n      track(obj, 'value')\n      return cache\n    }\n  }\n\n  return obj\n}\n",[25,5755,5756,5772,5782,5797,5801,5817,5831,5839,5844,5854,5860,5868,5882,5886,5890,5894,5902,5910,5920,5930,5938,5942,5956,5962,5966,5970,5974,5980],{"__ignoreMap":46},[50,5757,5758,5760,5762,5764,5766,5768,5770],{"class":52,"line":53},[50,5759,331],{"class":56},[50,5761,1909],{"class":68},[50,5763,72],{"class":64},[50,5765,1914],{"class":68},[50,5767,258],{"class":64},[50,5769,261],{"class":60},[50,5771,881],{"class":64},[50,5773,5774,5776,5778,5780],{"class":52,"line":82},[50,5775,2240],{"class":56},[50,5777,2256],{"class":107},[50,5779,65],{"class":64},[50,5781,637],{"class":75},[50,5783,5784,5786,5788,5790,5792,5794],{"class":52,"line":89},[50,5785,2240],{"class":56},[50,5787,2243],{"class":107},[50,5789,258],{"class":64},[50,5791,3437],{"class":60},[50,5793,65],{"class":64},[50,5795,5796],{"class":75},"undefined\n",[50,5798,5799],{"class":52,"line":104},[50,5800,86],{"emptyLinePlaceholder":85},[50,5802,5803,5805,5807,5809,5811,5813,5815],{"class":52,"line":129},[50,5804,363],{"class":56},[50,5806,366],{"class":60},[50,5808,65],{"class":64},[50,5810,723],{"class":68},[50,5812,95],{"class":64},[50,5814,98],{"class":56},[50,5816,101],{"class":64},[50,5818,5819,5821,5823,5825,5827,5829],{"class":52,"line":135},[50,5820,1948],{"class":107},[50,5822,111],{"class":64},[50,5824,114],{"class":68},[50,5826,72],{"class":64},[50,5828,1957],{"class":75},[50,5830,79],{"class":64},[50,5832,5833,5835,5837],{"class":52,"line":140},[50,5834,1823],{"class":56},[50,5836,1966],{"class":68},[50,5838,423],{"class":64},[50,5840,5841],{"class":52,"line":152},[50,5842,5843],{"class":64},"  }, {\n",[50,5845,5846,5848,5850,5852],{"class":52,"line":163},[50,5847,2286],{"class":107},[50,5849,258],{"class":64},[50,5851,1359],{"class":75},[50,5853,2063],{"class":64},[50,5855,5856,5858],{"class":52,"line":323},[50,5857,2500],{"class":68},[50,5859,611],{"class":64},[50,5861,5862,5864,5866],{"class":52,"line":328},[50,5863,2507],{"class":107},[50,5865,65],{"class":64},[50,5867,637],{"class":75},[50,5869,5870,5872,5874,5876,5878,5880],{"class":52,"line":360},[50,5871,2947],{"class":68},[50,5873,72],{"class":64},[50,5875,2095],{"class":107},[50,5877,345],{"class":64},[50,5879,2956],{"class":75},[50,5881,79],{"class":64},[50,5883,5884],{"class":52,"line":376},[50,5885,1027],{"class":64},[50,5887,5888],{"class":52,"line":389},[50,5889,710],{"class":64},[50,5891,5892],{"class":52,"line":400},[50,5893,1987],{"class":64},[50,5895,5896,5898,5900],{"class":52,"line":417},[50,5897,363],{"class":56},[50,5899,1994],{"class":60},[50,5901,241],{"class":64},[50,5903,5904,5906,5908],{"class":52,"line":426},[50,5905,2001],{"class":56},[50,5907,2004],{"class":68},[50,5909,611],{"class":64},[50,5911,5912,5914,5916,5918],{"class":52,"line":438},[50,5913,2320],{"class":56},[50,5915,619],{"class":64},[50,5917,2199],{"class":107},[50,5919,881],{"class":64},[50,5921,5922,5924,5926,5928],{"class":52,"line":467},[50,5923,2332],{"class":107},[50,5925,65],{"class":64},[50,5927,384],{"class":68},[50,5929,423],{"class":64},[50,5931,5932,5934,5936],{"class":52,"line":473},[50,5933,2344],{"class":107},[50,5935,65],{"class":64},[50,5937,597],{"class":75},[50,5939,5940],{"class":52,"line":478},[50,5941,2354],{"class":64},[50,5943,5944,5946,5948,5950,5952,5954],{"class":52,"line":493},[50,5945,3030],{"class":68},[50,5947,72],{"class":64},[50,5949,2095],{"class":107},[50,5951,345],{"class":64},[50,5953,2956],{"class":75},[50,5955,79],{"class":64},[50,5957,5958,5960],{"class":52,"line":506},[50,5959,2011],{"class":56},[50,5961,2362],{"class":107},[50,5963,5964],{"class":52,"line":513},[50,5965,1027],{"class":64},[50,5967,5968],{"class":52,"line":790},[50,5969,470],{"class":64},[50,5971,5972],{"class":52,"line":798},[50,5973,86],{"emptyLinePlaceholder":85},[50,5975,5976,5978],{"class":52,"line":803},[50,5977,1589],{"class":56},[50,5979,2034],{"class":107},[50,5981,5982],{"class":52,"line":4117},[50,5983,274],{"class":64},[13,5985,5986],{},"侦听器：",[41,5988,5990],{"className":220,"code":5989,"language":222,"meta":46,"style":46},"type WatchOptions = {\n  immediate?: boolean\n}\n\nfunction watch(\n  target: object | Function,\n  cb: (newVal?: any, oldVal?: any) => void,\n  options: WatchOptions = {}\n) {\n  let getter: Function;\n  if (typeof target === 'function') {\n    getter = target\n  } else {\n    getter = () => traverse(target)\n  }\n  let newVal: any, oldVal: any\n\n  const job = () => {\n    newVal = effectFn()\n    cb(newVal, oldVal)\n    oldVal = newVal\n  }\n\n  const effectFn = effect(() => getter(), {\n    lazy: true,\n    scheduler: job\n  })\n\n  if (options.immediate) {\n    job()\n  } else {\n    oldVal = effectFn()\n  }\n}\n\nfunction traverse(value: any, seen = new Set\u003Cany>) {\n  if (typeof value !== 'object' || value === null || seen.has(value)) return\n  seen.add(value)\n  for (const k in value) {\n    traverse(value[k], seen)\n  }\n\n  return value\n}\n",[25,5991,5992,6000,6010,6014,6018,6026,6040,6072,6082,6086,6098,6114,6122,6130,6146,6150,6168,6172,6184,6194,6208,6216,6220,6224,6242,6252,6260,6264,6268,6282,6288,6296,6306,6310,6314,6318,6348,6386,6400,6416,6434,6438,6442,6448],{"__ignoreMap":46},[50,5993,5994,5996,5998],{"class":52,"line":53},[50,5995,235],{"class":56},[50,5997,4126],{"class":60},[50,5999,241],{"class":64},[50,6001,6002,6004,6006,6008],{"class":52,"line":82},[50,6003,4133],{"class":107},[50,6005,249],{"class":56},[50,6007,258],{"class":64},[50,6009,1410],{"class":60},[50,6011,6012],{"class":52,"line":89},[50,6013,274],{"class":64},[50,6015,6016],{"class":52,"line":104},[50,6017,86],{"emptyLinePlaceholder":85},[50,6019,6020,6022,6024],{"class":52,"line":129},[50,6021,331],{"class":56},[50,6023,3211],{"class":68},[50,6025,4156],{"class":64},[50,6027,6028,6030,6032,6034,6036,6038],{"class":52,"line":135},[50,6029,4161],{"class":348},[50,6031,258],{"class":64},[50,6033,868],{"class":60},[50,6035,3619],{"class":64},[50,6037,261],{"class":60},[50,6039,2063],{"class":64},[50,6041,6042,6044,6046,6048,6050,6052,6054,6056,6058,6060,6062,6064,6066,6068,6070],{"class":52,"line":140},[50,6043,4176],{"class":68},[50,6045,252],{"class":64},[50,6047,3105],{"class":348},[50,6049,249],{"class":56},[50,6051,258],{"class":64},[50,6053,3437],{"class":60},[50,6055,345],{"class":64},[50,6057,3110],{"class":348},[50,6059,249],{"class":56},[50,6061,258],{"class":64},[50,6063,3437],{"class":60},[50,6065,264],{"class":64},[50,6067,98],{"class":56},[50,6069,3228],{"class":60},[50,6071,2063],{"class":64},[50,6073,6074,6076,6078,6080],{"class":52,"line":152},[50,6075,311],{"class":348},[50,6077,258],{"class":64},[50,6079,4213],{"class":60},[50,6081,4216],{"class":64},[50,6083,6084],{"class":52,"line":163},[50,6085,881],{"class":64},[50,6087,6088,6090,6092,6094,6096],{"class":52,"line":323},[50,6089,2240],{"class":56},[50,6091,1966],{"class":68},[50,6093,258],{"class":64},[50,6095,261],{"class":60},[50,6097,3646],{"class":64},[50,6099,6100,6102,6104,6106,6108,6110,6112],{"class":52,"line":328},[50,6101,616],{"class":56},[50,6103,619],{"class":64},[50,6105,3469],{"class":56},[50,6107,3242],{"class":107},[50,6109,3484],{"class":64},[50,6111,3661],{"class":75},[50,6113,881],{"class":64},[50,6115,6116,6118,6120],{"class":52,"line":360},[50,6117,3668],{"class":107},[50,6119,65],{"class":64},[50,6121,3673],{"class":107},[50,6123,6124,6126,6128],{"class":52,"line":376},[50,6125,3678],{"class":64},[50,6127,1096],{"class":56},[50,6129,101],{"class":64},[50,6131,6132,6134,6136,6138,6140,6142,6144],{"class":52,"line":389},[50,6133,3668],{"class":68},[50,6135,369],{"class":64},[50,6137,98],{"class":56},[50,6139,3387],{"class":68},[50,6141,72],{"class":64},[50,6143,863],{"class":107},[50,6145,79],{"class":64},[50,6147,6148],{"class":52,"line":400},[50,6149,470],{"class":64},[50,6151,6152,6154,6156,6158,6160,6162,6164,6166],{"class":52,"line":417},[50,6153,2240],{"class":56},[50,6155,3875],{"class":107},[50,6157,258],{"class":64},[50,6159,3437],{"class":60},[50,6161,345],{"class":64},[50,6163,3110],{"class":107},[50,6165,258],{"class":64},[50,6167,2248],{"class":60},[50,6169,6170],{"class":52,"line":426},[50,6171,86],{"emptyLinePlaceholder":85},[50,6173,6174,6176,6178,6180,6182],{"class":52,"line":438},[50,6175,363],{"class":56},[50,6177,679],{"class":68},[50,6179,369],{"class":64},[50,6181,98],{"class":56},[50,6183,101],{"class":64},[50,6185,6186,6188,6190,6192],{"class":52,"line":467},[50,6187,4328],{"class":107},[50,6189,65],{"class":64},[50,6191,384],{"class":68},[50,6193,423],{"class":64},[50,6195,6196,6198,6200,6202,6204,6206],{"class":52,"line":473},[50,6197,4339],{"class":68},[50,6199,72],{"class":64},[50,6201,3105],{"class":107},[50,6203,345],{"class":64},[50,6205,3110],{"class":107},[50,6207,79],{"class":64},[50,6209,6210,6212,6214],{"class":52,"line":478},[50,6211,4354],{"class":107},[50,6213,65],{"class":64},[50,6215,3977],{"class":107},[50,6217,6218],{"class":52,"line":493},[50,6219,470],{"class":64},[50,6221,6222],{"class":52,"line":506},[50,6223,86],{"emptyLinePlaceholder":85},[50,6225,6226,6228,6230,6232,6234,6236,6238,6240],{"class":52,"line":513},[50,6227,363],{"class":56},[50,6229,366],{"class":60},[50,6231,65],{"class":64},[50,6233,723],{"class":68},[50,6235,95],{"class":64},[50,6237,98],{"class":56},[50,6239,1966],{"class":68},[50,6241,3715],{"class":64},[50,6243,6244,6246,6248,6250],{"class":52,"line":790},[50,6245,2286],{"class":107},[50,6247,258],{"class":64},[50,6249,1359],{"class":75},[50,6251,2063],{"class":64},[50,6253,6254,6256,6258],{"class":52,"line":798},[50,6255,2500],{"class":107},[50,6257,258],{"class":64},[50,6259,4405],{"class":107},[50,6261,6262],{"class":52,"line":803},[50,6263,710],{"class":64},[50,6265,6266],{"class":52,"line":4117},[50,6267,86],{"emptyLinePlaceholder":85},[50,6269,6270,6272,6274,6276,6278,6280],{"class":52,"line":4413},[50,6271,616],{"class":56},[50,6273,619],{"class":64},[50,6275,349],{"class":107},[50,6277,111],{"class":64},[50,6279,3169],{"class":107},[50,6281,881],{"class":64},[50,6283,6284,6286],{"class":52,"line":4418},[50,6285,4442],{"class":68},[50,6287,423],{"class":64},[50,6289,6290,6292,6294],{"class":52,"line":4424},[50,6291,3678],{"class":64},[50,6293,1096],{"class":56},[50,6295,101],{"class":64},[50,6297,6298,6300,6302,6304],{"class":52,"line":4439},[50,6299,4354],{"class":107},[50,6301,65],{"class":64},[50,6303,384],{"class":68},[50,6305,423],{"class":64},[50,6307,6308],{"class":52,"line":4447},[50,6309,470],{"class":64},[50,6311,6312],{"class":52,"line":4456},[50,6313,274],{"class":64},[50,6315,6316],{"class":52,"line":4467},[50,6317,86],{"emptyLinePlaceholder":85},[50,6319,6320,6322,6324,6326,6328,6330,6332,6334,6336,6338,6340,6342,6344,6346],{"class":52,"line":4472},[50,6321,331],{"class":56},[50,6323,3387],{"class":68},[50,6325,72],{"class":64},[50,6327,124],{"class":348},[50,6329,258],{"class":64},[50,6331,3437],{"class":60},[50,6333,345],{"class":64},[50,6335,3442],{"class":348},[50,6337,65],{"class":64},[50,6339,544],{"class":56},[50,6341,547],{"class":107},[50,6343,550],{"class":64},[50,6345,3437],{"class":107},[50,6347,3455],{"class":64},[50,6349,6350,6352,6354,6356,6358,6360,6362,6364,6366,6368,6370,6372,6374,6376,6378,6380,6382,6384],{"class":52,"line":4927},[50,6351,616],{"class":56},[50,6353,619],{"class":64},[50,6355,3469],{"class":56},[50,6357,2004],{"class":107},[50,6359,1002],{"class":64},[50,6361,3476],{"class":75},[50,6363,3479],{"class":64},[50,6365,124],{"class":107},[50,6367,3484],{"class":64},[50,6369,3487],{"class":75},[50,6371,3479],{"class":64},[50,6373,3442],{"class":107},[50,6375,111],{"class":64},[50,6377,3496],{"class":68},[50,6379,72],{"class":64},[50,6381,124],{"class":107},[50,6383,3503],{"class":64},[50,6385,627],{"class":56},[50,6387,6388,6390,6392,6394,6396,6398],{"class":52,"line":4938},[50,6389,3510],{"class":107},[50,6391,111],{"class":64},[50,6393,781],{"class":68},[50,6395,72],{"class":64},[50,6397,124],{"class":107},[50,6399,79],{"class":64},[50,6401,6402,6404,6406,6408,6410,6412,6414],{"class":52,"line":4947},[50,6403,3535],{"class":56},[50,6405,619],{"class":64},[50,6407,57],{"class":56},[50,6409,3542],{"class":60},[50,6411,3545],{"class":56},[50,6413,2004],{"class":107},[50,6415,881],{"class":64},[50,6417,6418,6420,6422,6424,6426,6428,6430,6432],{"class":52,"line":4962},[50,6419,3554],{"class":68},[50,6421,72],{"class":64},[50,6423,124],{"class":107},[50,6425,448],{"class":64},[50,6427,3563],{"class":107},[50,6429,3566],{"class":64},[50,6431,3442],{"class":107},[50,6433,79],{"class":64},[50,6435,6436],{"class":52,"line":4975},[50,6437,470],{"class":64},[50,6439,6440],{"class":52,"line":4986},[50,6441,86],{"emptyLinePlaceholder":85},[50,6443,6444,6446],{"class":52,"line":5009},[50,6445,1589],{"class":56},[50,6447,3581],{"class":107},[50,6449,6450],{"class":52,"line":5016},[50,6451,274],{"class":64},[6453,6454,6455],"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 .stHQG, html code.shiki .stHQG{--shiki-default:#00DAEF}html pre.shiki code .se2J0, html code.shiki .se2J0{--shiki-default:#FFD493}html pre.shiki code .sb16X, html code.shiki .sb16X{--shiki-default:#4BF3C8}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 .sy89t, html code.shiki .sy89t{--shiki-default:#EEF0F98F;--shiki-default-font-style:italic}html pre.shiki code .smONe, html code.shiki .smONe{--shiki-default:#4BF3C8;--shiki-default-font-style:italic}",{"title":46,"searchDepth":82,"depth":82,"links":6457},[6458,6459,6460,6465,6470],{"id":32,"depth":82,"text":33},{"id":211,"depth":82,"text":211},{"id":1122,"depth":82,"text":1122,"children":6461},[6462,6463,6464],{"id":1155,"depth":89,"text":1156},{"id":2174,"depth":89,"text":2174},{"id":2701,"depth":89,"text":2701},{"id":3074,"depth":82,"text":3074,"children":6466},[6467,6468,6469],{"id":3182,"depth":89,"text":3183},{"id":3742,"depth":89,"text":3742},{"id":4094,"depth":89,"text":4094},{"id":4487,"depth":82,"text":4487},"2024.12.18","md","如果说响应式系统中依赖收集解决了「谁依赖谁」的问题，那么调度执行机制就解决了「在何时、以何顺序」进行更新的问题",{},"\u002Fwriting\u002Fvue-scheduler",{"title":5,"description":46},"writing\u002Fvue-scheduler",[6479,6480],"Vue","ES6","Cxr3_QXN8lgpFxBcGfFXzaIKN7ppAkFljF5fy_ZWF5k",1774950409695]