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