[{"data":1,"prerenderedAt":3767},["ShallowReactive",2],{"blog-\u002Fblog\u002Fvuex-source-code-analysis":3,"blog-siblings-\u002Fblog\u002Fvuex-source-code-analysis":3758},{"id":4,"title":5,"body":6,"category":3743,"date":3744,"description":3745,"draft":3746,"extension":3747,"meta":3748,"navigation":235,"path":3749,"seo":3750,"source":3751,"stem":3752,"tags":3753,"__hash__":3757},"blog\u002Fblog\u002Fvuex-source-code-analysis.md","Vuex 源码深度解析",{"type":7,"value":8,"toc":3735},"minimark",[9,14,18,26,30,35,38,53,58,75,497,501,508,513,1026,1032,1190,1225,1714,1720,1725,2339,2345,2358,2680,2684,2688,2697,2989,2993,2999,3241,3244,3255,3731],[10,11,13],"h2",{"id":12},"vuex-思想","Vuex 思想",[15,16,17],"p",{},"在解读源码之前，先来简单了解下 Vuex 的思想。",[15,19,20,21,25],{},"Vuex 全局维护着一个对象，使用到了单例设计模式。在这个全局对象中，所有属性都是响应式的，任意属性进行了改变，都会造成使用到该属性的组件进行更新。并且只能通过 ",[22,23,24],"code",{},"commit"," 的方式改变状态，实现了单向数据流模式。",[10,27,29],{"id":28},"vuex-解析","Vuex 解析",[31,32,34],"h3",{"id":33},"vuex-安装","Vuex 安装",[15,36,37],{},"在看接下来的内容前，推荐本地 clone 一份 Vuex 源码对照着看，便于理解。",[15,39,40,41,44,45,48,49,52],{},"在使用 Vuex 之前，我们都需要调用 ",[22,42,43],{},"Vue.use(Vuex)"," 。在调用 ",[22,46,47],{},"use"," 的过程中，Vue 会调用到 Vuex 的 ",[22,50,51],{},"install"," 函数",[15,54,55,57],{},[22,56,51],{}," 函数作用很简单",[59,60,61,65],"ul",{},[62,63,64],"li",{},"确保 Vuex 只安装一次",[62,66,67,68,71,72],{},"混入 ",[22,69,70],{},"beforeCreate"," 钩子函数，可以在组件中使用 ",[22,73,74],{},"this.$store",[76,77,82],"pre",{"className":78,"code":79,"language":80,"meta":81,"style":81},"language-js shiki shiki-themes github-light github-dark","export function install(_Vue) {\n  \u002F\u002F 确保 Vuex 只安装一次\n  if (Vue && _Vue === Vue) {\n    if (process.env.NODE_ENV !== 'production') {\n      console.error(\n        '[vuex] already installed. Vue.use(Vuex) should be called only once.'\n      )\n    }\n    return\n  }\n  Vue = _Vue\n  applyMixin(Vue)\n}\n\n\u002F\u002F applyMixin\nexport default function(Vue) {\n  \u002F\u002F 获得 Vue 版本号\n  const version = Number(Vue.version.split('.')[0])\n  \u002F\u002F Vue 2.0 以上会混入 beforeCreate 函数\n  if (version >= 2) {\n    Vue.mixin({ beforeCreate: vuexInit })\n  } else {\n    \u002F\u002F ...\n  }\n  \u002F\u002F 作用很简单，就是能让我们在组件中\n  \u002F\u002F 使用到 this.$store\n  function vuexInit() {\n    const options = this.$options\n    if (options.store) {\n      this.$store =\n        typeof options.store === 'function' ? options.store() : options.store\n    } else if (options.parent && options.parent.$store) {\n      this.$store = options.parent.$store\n    }\n  }\n}\n","js","",[22,83,84,111,118,139,161,173,179,185,191,197,203,215,224,230,237,243,260,266,301,307,323,335,347,353,358,364,370,382,399,407,419,451,470,482,487,492],{"__ignoreMap":81},[85,86,89,93,96,100,104,108],"span",{"class":87,"line":88},"line",1,[85,90,92],{"class":91},"szBVR","export",[85,94,95],{"class":91}," function",[85,97,99],{"class":98},"sScJk"," install",[85,101,103],{"class":102},"sVt8B","(",[85,105,107],{"class":106},"s4XuR","_Vue",[85,109,110],{"class":102},") {\n",[85,112,114],{"class":87,"line":113},2,[85,115,117],{"class":116},"sJ8bj","  \u002F\u002F 确保 Vuex 只安装一次\n",[85,119,121,124,127,130,133,136],{"class":87,"line":120},3,[85,122,123],{"class":91},"  if",[85,125,126],{"class":102}," (Vue ",[85,128,129],{"class":91},"&&",[85,131,132],{"class":102}," _Vue ",[85,134,135],{"class":91},"===",[85,137,138],{"class":102}," Vue) {\n",[85,140,142,145,148,152,155,159],{"class":87,"line":141},4,[85,143,144],{"class":91},"    if",[85,146,147],{"class":102}," (process.env.",[85,149,151],{"class":150},"sj4cs","NODE_ENV",[85,153,154],{"class":91}," !==",[85,156,158],{"class":157},"sZZnC"," 'production'",[85,160,110],{"class":102},[85,162,164,167,170],{"class":87,"line":163},5,[85,165,166],{"class":102},"      console.",[85,168,169],{"class":98},"error",[85,171,172],{"class":102},"(\n",[85,174,176],{"class":87,"line":175},6,[85,177,178],{"class":157},"        '[vuex] already installed. Vue.use(Vuex) should be called only once.'\n",[85,180,182],{"class":87,"line":181},7,[85,183,184],{"class":102},"      )\n",[85,186,188],{"class":87,"line":187},8,[85,189,190],{"class":102},"    }\n",[85,192,194],{"class":87,"line":193},9,[85,195,196],{"class":91},"    return\n",[85,198,200],{"class":87,"line":199},10,[85,201,202],{"class":102},"  }\n",[85,204,206,209,212],{"class":87,"line":205},11,[85,207,208],{"class":102},"  Vue ",[85,210,211],{"class":91},"=",[85,213,214],{"class":102}," _Vue\n",[85,216,218,221],{"class":87,"line":217},12,[85,219,220],{"class":98},"  applyMixin",[85,222,223],{"class":102},"(Vue)\n",[85,225,227],{"class":87,"line":226},13,[85,228,229],{"class":102},"}\n",[85,231,233],{"class":87,"line":232},14,[85,234,236],{"emptyLinePlaceholder":235},true,"\n",[85,238,240],{"class":87,"line":239},15,[85,241,242],{"class":116},"\u002F\u002F applyMixin\n",[85,244,246,248,251,253,255,258],{"class":87,"line":245},16,[85,247,92],{"class":91},[85,249,250],{"class":91}," default",[85,252,95],{"class":91},[85,254,103],{"class":102},[85,256,257],{"class":106},"Vue",[85,259,110],{"class":102},[85,261,263],{"class":87,"line":262},17,[85,264,265],{"class":116},"  \u002F\u002F 获得 Vue 版本号\n",[85,267,269,272,275,278,281,284,287,289,292,295,298],{"class":87,"line":268},18,[85,270,271],{"class":91},"  const",[85,273,274],{"class":150}," version",[85,276,277],{"class":91}," =",[85,279,280],{"class":98}," Number",[85,282,283],{"class":102},"(Vue.version.",[85,285,286],{"class":98},"split",[85,288,103],{"class":102},[85,290,291],{"class":157},"'.'",[85,293,294],{"class":102},")[",[85,296,297],{"class":150},"0",[85,299,300],{"class":102},"])\n",[85,302,304],{"class":87,"line":303},19,[85,305,306],{"class":116},"  \u002F\u002F Vue 2.0 以上会混入 beforeCreate 函数\n",[85,308,310,312,315,318,321],{"class":87,"line":309},20,[85,311,123],{"class":91},[85,313,314],{"class":102}," (version ",[85,316,317],{"class":91},">=",[85,319,320],{"class":150}," 2",[85,322,110],{"class":102},[85,324,326,329,332],{"class":87,"line":325},21,[85,327,328],{"class":102},"    Vue.",[85,330,331],{"class":98},"mixin",[85,333,334],{"class":102},"({ beforeCreate: vuexInit })\n",[85,336,338,341,344],{"class":87,"line":337},22,[85,339,340],{"class":102},"  } ",[85,342,343],{"class":91},"else",[85,345,346],{"class":102}," {\n",[85,348,350],{"class":87,"line":349},23,[85,351,352],{"class":116},"    \u002F\u002F ...\n",[85,354,356],{"class":87,"line":355},24,[85,357,202],{"class":102},[85,359,361],{"class":87,"line":360},25,[85,362,363],{"class":116},"  \u002F\u002F 作用很简单，就是能让我们在组件中\n",[85,365,367],{"class":87,"line":366},26,[85,368,369],{"class":116},"  \u002F\u002F 使用到 this.$store\n",[85,371,373,376,379],{"class":87,"line":372},27,[85,374,375],{"class":91},"  function",[85,377,378],{"class":98}," vuexInit",[85,380,381],{"class":102},"() {\n",[85,383,385,388,391,393,396],{"class":87,"line":384},28,[85,386,387],{"class":91},"    const",[85,389,390],{"class":150}," options",[85,392,277],{"class":91},[85,394,395],{"class":150}," this",[85,397,398],{"class":102},".$options\n",[85,400,402,404],{"class":87,"line":401},29,[85,403,144],{"class":91},[85,405,406],{"class":102}," (options.store) {\n",[85,408,410,413,416],{"class":87,"line":409},30,[85,411,412],{"class":150},"      this",[85,414,415],{"class":102},".$store ",[85,417,418],{"class":91},"=\n",[85,420,422,425,428,430,433,436,439,442,445,448],{"class":87,"line":421},31,[85,423,424],{"class":91},"        typeof",[85,426,427],{"class":102}," options.store ",[85,429,135],{"class":91},[85,431,432],{"class":157}," 'function'",[85,434,435],{"class":91}," ?",[85,437,438],{"class":102}," options.",[85,440,441],{"class":98},"store",[85,443,444],{"class":102},"() ",[85,446,447],{"class":91},":",[85,449,450],{"class":102}," options.store\n",[85,452,454,457,459,462,465,467],{"class":87,"line":453},32,[85,455,456],{"class":102},"    } ",[85,458,343],{"class":91},[85,460,461],{"class":91}," if",[85,463,464],{"class":102}," (options.parent ",[85,466,129],{"class":91},[85,468,469],{"class":102}," options.parent.$store) {\n",[85,471,473,475,477,479],{"class":87,"line":472},33,[85,474,412],{"class":150},[85,476,415],{"class":102},[85,478,211],{"class":91},[85,480,481],{"class":102}," options.parent.$store\n",[85,483,485],{"class":87,"line":484},34,[85,486,190],{"class":102},[85,488,490],{"class":87,"line":489},35,[85,491,202],{"class":102},[85,493,495],{"class":87,"line":494},36,[85,496,229],{"class":102},[31,498,500],{"id":499},"vuex-初始化","Vuex 初始化",[502,503,505],"h5",{"id":504},"this_modules",[22,506,507],{},"this._modules",[15,509,510,511],{},"本小节内容主要解析如何初始化 ",[22,512,507],{},[76,514,516],{"className":78,"code":515,"language":80,"meta":81,"style":81},"export class Store {\n  constructor (options = {}) {\n    \u002F\u002F 引入 Vue 的方式，自动安装\n    if (!Vue && typeof window !== 'undefined' && window.Vue) {\n      install(window.Vue)\n    }\n    \u002F\u002F 在开发环境中断言\n    if (process.env.NODE_ENV !== 'production') {\n      assert(Vue, `must call Vue.use(Vuex) before creating a store instance.`)\n      assert(typeof Promise !== 'undefined', `vuex requires a Promise polyfill in this browser.`)\n      assert(this instanceof Store, `store must be called with the new operator.`)\n    }\n    \u002F\u002F 获取 options 中的属性\n    const {\n      plugins = [],\n      strict = false\n    } = options\n\n    \u002F\u002F store 内部的状态，重点关注 this._modules\n    this._committing = false\n    this._actions = Object.create(null)\n    this._actionSubscribers = []\n    this._mutations = Object.create(null)\n    this._wrappedGetters = Object.create(null)\n    this._modules = new ModuleCollection(options)\n    this._modulesNamespaceMap = Object.create(null)\n    this._subscribers = []\n    this._watcherVM = new Vue()\n\n\n    const store = this\n    const { dispatch, commit } = this\n    \u002F\u002F bind 以下两个函数上 this 上\n    \u002F\u002F 便于 this.$store.dispatch\n    this.dispatch = function boundDispatch (type, payload) {\n      return dispatch.call(store, type, payload)\n    }\n    this.commit = function boundCommit (type, payload, options) {\n      return commit.call(store, type, payload, options)\n    }\n}\n",[22,517,518,530,546,551,583,591,595,600,614,628,652,673,677,682,688,698,708,717,721,726,738,760,772,791,810,828,847,858,875,879,883,895,916,921,926,954,968,973,1003,1016,1021],{"__ignoreMap":81},[85,519,520,522,525,528],{"class":87,"line":88},[85,521,92],{"class":91},[85,523,524],{"class":91}," class",[85,526,527],{"class":98}," Store",[85,529,346],{"class":102},[85,531,532,535,538,541,543],{"class":87,"line":113},[85,533,534],{"class":91},"  constructor",[85,536,537],{"class":102}," (",[85,539,540],{"class":106},"options",[85,542,277],{"class":91},[85,544,545],{"class":102}," {}) {\n",[85,547,548],{"class":87,"line":120},[85,549,550],{"class":116},"    \u002F\u002F 引入 Vue 的方式，自动安装\n",[85,552,553,555,557,560,563,565,568,571,574,577,580],{"class":87,"line":141},[85,554,144],{"class":91},[85,556,537],{"class":102},[85,558,559],{"class":91},"!",[85,561,562],{"class":102},"Vue ",[85,564,129],{"class":91},[85,566,567],{"class":91}," typeof",[85,569,570],{"class":102}," window ",[85,572,573],{"class":91},"!==",[85,575,576],{"class":157}," 'undefined'",[85,578,579],{"class":91}," &&",[85,581,582],{"class":102}," window.Vue) {\n",[85,584,585,588],{"class":87,"line":163},[85,586,587],{"class":98},"      install",[85,589,590],{"class":102},"(window.Vue)\n",[85,592,593],{"class":87,"line":175},[85,594,190],{"class":102},[85,596,597],{"class":87,"line":181},[85,598,599],{"class":116},"    \u002F\u002F 在开发环境中断言\n",[85,601,602,604,606,608,610,612],{"class":87,"line":187},[85,603,144],{"class":91},[85,605,147],{"class":102},[85,607,151],{"class":150},[85,609,154],{"class":91},[85,611,158],{"class":157},[85,613,110],{"class":102},[85,615,616,619,622,625],{"class":87,"line":193},[85,617,618],{"class":98},"      assert",[85,620,621],{"class":102},"(Vue, ",[85,623,624],{"class":157},"`must call Vue.use(Vuex) before creating a store instance.`",[85,626,627],{"class":102},")\n",[85,629,630,632,634,637,640,642,644,647,650],{"class":87,"line":199},[85,631,618],{"class":98},[85,633,103],{"class":102},[85,635,636],{"class":91},"typeof",[85,638,639],{"class":150}," Promise",[85,641,154],{"class":91},[85,643,576],{"class":157},[85,645,646],{"class":102},", ",[85,648,649],{"class":157},"`vuex requires a Promise polyfill in this browser.`",[85,651,627],{"class":102},[85,653,654,656,658,661,664,666,668,671],{"class":87,"line":205},[85,655,618],{"class":98},[85,657,103],{"class":102},[85,659,660],{"class":150},"this",[85,662,663],{"class":91}," instanceof",[85,665,527],{"class":98},[85,667,646],{"class":102},[85,669,670],{"class":157},"`store must be called with the new operator.`",[85,672,627],{"class":102},[85,674,675],{"class":87,"line":217},[85,676,190],{"class":102},[85,678,679],{"class":87,"line":226},[85,680,681],{"class":116},"    \u002F\u002F 获取 options 中的属性\n",[85,683,684,686],{"class":87,"line":232},[85,685,387],{"class":91},[85,687,346],{"class":102},[85,689,690,693,695],{"class":87,"line":239},[85,691,692],{"class":150},"      plugins",[85,694,277],{"class":91},[85,696,697],{"class":102}," [],\n",[85,699,700,703,705],{"class":87,"line":245},[85,701,702],{"class":150},"      strict",[85,704,277],{"class":91},[85,706,707],{"class":150}," false\n",[85,709,710,712,714],{"class":87,"line":262},[85,711,456],{"class":102},[85,713,211],{"class":91},[85,715,716],{"class":102}," options\n",[85,718,719],{"class":87,"line":268},[85,720,236],{"emptyLinePlaceholder":235},[85,722,723],{"class":87,"line":303},[85,724,725],{"class":116},"    \u002F\u002F store 内部的状态，重点关注 this._modules\n",[85,727,728,731,734,736],{"class":87,"line":309},[85,729,730],{"class":150},"    this",[85,732,733],{"class":102},"._committing ",[85,735,211],{"class":91},[85,737,707],{"class":150},[85,739,740,742,745,747,750,753,755,758],{"class":87,"line":325},[85,741,730],{"class":150},[85,743,744],{"class":102},"._actions ",[85,746,211],{"class":91},[85,748,749],{"class":102}," Object.",[85,751,752],{"class":98},"create",[85,754,103],{"class":102},[85,756,757],{"class":150},"null",[85,759,627],{"class":102},[85,761,762,764,767,769],{"class":87,"line":337},[85,763,730],{"class":150},[85,765,766],{"class":102},"._actionSubscribers ",[85,768,211],{"class":91},[85,770,771],{"class":102}," []\n",[85,773,774,776,779,781,783,785,787,789],{"class":87,"line":349},[85,775,730],{"class":150},[85,777,778],{"class":102},"._mutations ",[85,780,211],{"class":91},[85,782,749],{"class":102},[85,784,752],{"class":98},[85,786,103],{"class":102},[85,788,757],{"class":150},[85,790,627],{"class":102},[85,792,793,795,798,800,802,804,806,808],{"class":87,"line":355},[85,794,730],{"class":150},[85,796,797],{"class":102},"._wrappedGetters ",[85,799,211],{"class":91},[85,801,749],{"class":102},[85,803,752],{"class":98},[85,805,103],{"class":102},[85,807,757],{"class":150},[85,809,627],{"class":102},[85,811,812,814,817,819,822,825],{"class":87,"line":360},[85,813,730],{"class":150},[85,815,816],{"class":102},"._modules ",[85,818,211],{"class":91},[85,820,821],{"class":91}," new",[85,823,824],{"class":98}," ModuleCollection",[85,826,827],{"class":102},"(options)\n",[85,829,830,832,835,837,839,841,843,845],{"class":87,"line":366},[85,831,730],{"class":150},[85,833,834],{"class":102},"._modulesNamespaceMap ",[85,836,211],{"class":91},[85,838,749],{"class":102},[85,840,752],{"class":98},[85,842,103],{"class":102},[85,844,757],{"class":150},[85,846,627],{"class":102},[85,848,849,851,854,856],{"class":87,"line":372},[85,850,730],{"class":150},[85,852,853],{"class":102},"._subscribers ",[85,855,211],{"class":91},[85,857,771],{"class":102},[85,859,860,862,865,867,869,872],{"class":87,"line":384},[85,861,730],{"class":150},[85,863,864],{"class":102},"._watcherVM ",[85,866,211],{"class":91},[85,868,821],{"class":91},[85,870,871],{"class":98}," Vue",[85,873,874],{"class":102},"()\n",[85,876,877],{"class":87,"line":401},[85,878,236],{"emptyLinePlaceholder":235},[85,880,881],{"class":87,"line":409},[85,882,236],{"emptyLinePlaceholder":235},[85,884,885,887,890,892],{"class":87,"line":421},[85,886,387],{"class":91},[85,888,889],{"class":150}," store",[85,891,277],{"class":91},[85,893,894],{"class":150}," this\n",[85,896,897,899,902,905,907,909,912,914],{"class":87,"line":453},[85,898,387],{"class":91},[85,900,901],{"class":102}," { ",[85,903,904],{"class":150},"dispatch",[85,906,646],{"class":102},[85,908,24],{"class":150},[85,910,911],{"class":102}," } ",[85,913,211],{"class":91},[85,915,894],{"class":150},[85,917,918],{"class":87,"line":472},[85,919,920],{"class":116},"    \u002F\u002F bind 以下两个函数上 this 上\n",[85,922,923],{"class":87,"line":484},[85,924,925],{"class":116},"    \u002F\u002F 便于 this.$store.dispatch\n",[85,927,928,930,933,935,937,939,942,944,947,949,952],{"class":87,"line":489},[85,929,730],{"class":150},[85,931,932],{"class":102},".",[85,934,904],{"class":98},[85,936,277],{"class":91},[85,938,95],{"class":91},[85,940,941],{"class":98}," boundDispatch",[85,943,537],{"class":102},[85,945,946],{"class":106},"type",[85,948,646],{"class":102},[85,950,951],{"class":106},"payload",[85,953,110],{"class":102},[85,955,956,959,962,965],{"class":87,"line":494},[85,957,958],{"class":91},"      return",[85,960,961],{"class":102}," dispatch.",[85,963,964],{"class":98},"call",[85,966,967],{"class":102},"(store, type, payload)\n",[85,969,971],{"class":87,"line":970},37,[85,972,190],{"class":102},[85,974,976,978,980,982,984,986,989,991,993,995,997,999,1001],{"class":87,"line":975},38,[85,977,730],{"class":150},[85,979,932],{"class":102},[85,981,24],{"class":98},[85,983,277],{"class":91},[85,985,95],{"class":91},[85,987,988],{"class":98}," boundCommit",[85,990,537],{"class":102},[85,992,946],{"class":106},[85,994,646],{"class":102},[85,996,951],{"class":106},[85,998,646],{"class":102},[85,1000,540],{"class":106},[85,1002,110],{"class":102},[85,1004,1006,1008,1011,1013],{"class":87,"line":1005},39,[85,1007,958],{"class":91},[85,1009,1010],{"class":102}," commit.",[85,1012,964],{"class":98},[85,1014,1015],{"class":102},"(store, type, payload, options)\n",[85,1017,1019],{"class":87,"line":1018},40,[85,1020,190],{"class":102},[85,1022,1024],{"class":87,"line":1023},41,[85,1025,229],{"class":102},[15,1027,1028,1029,1031],{},"接下来看 ",[22,1030,507],{}," 的过程，以 以下代码为例",[76,1033,1035],{"className":78,"code":1034,"language":80,"meta":81,"style":81},"const moduleA = {\n  state: { ... },\n  mutations: { ... },\n  actions: { ... },\n  getters: { ... }\n}\n\nconst moduleB = {\n  state: { ... },\n  mutations: { ... },\n  actions: { ... }\n}\n\nconst store = new Vuex.Store({\n  state: { ... },\n  modules: {\n    a: moduleA,\n    b: moduleB\n  }\n})\n",[22,1036,1037,1049,1060,1069,1078,1088,1092,1096,1107,1115,1123,1131,1135,1139,1158,1166,1171,1176,1181,1185],{"__ignoreMap":81},[85,1038,1039,1042,1045,1047],{"class":87,"line":88},[85,1040,1041],{"class":91},"const",[85,1043,1044],{"class":150}," moduleA",[85,1046,277],{"class":91},[85,1048,346],{"class":102},[85,1050,1051,1054,1057],{"class":87,"line":113},[85,1052,1053],{"class":102},"  state: { ",[85,1055,1056],{"class":91},"...",[85,1058,1059],{"class":102}," },\n",[85,1061,1062,1065,1067],{"class":87,"line":120},[85,1063,1064],{"class":102},"  mutations: { ",[85,1066,1056],{"class":91},[85,1068,1059],{"class":102},[85,1070,1071,1074,1076],{"class":87,"line":141},[85,1072,1073],{"class":102},"  actions: { ",[85,1075,1056],{"class":91},[85,1077,1059],{"class":102},[85,1079,1080,1083,1085],{"class":87,"line":163},[85,1081,1082],{"class":102},"  getters: { ",[85,1084,1056],{"class":91},[85,1086,1087],{"class":102}," }\n",[85,1089,1090],{"class":87,"line":175},[85,1091,229],{"class":102},[85,1093,1094],{"class":87,"line":181},[85,1095,236],{"emptyLinePlaceholder":235},[85,1097,1098,1100,1103,1105],{"class":87,"line":187},[85,1099,1041],{"class":91},[85,1101,1102],{"class":150}," moduleB",[85,1104,277],{"class":91},[85,1106,346],{"class":102},[85,1108,1109,1111,1113],{"class":87,"line":193},[85,1110,1053],{"class":102},[85,1112,1056],{"class":91},[85,1114,1059],{"class":102},[85,1116,1117,1119,1121],{"class":87,"line":199},[85,1118,1064],{"class":102},[85,1120,1056],{"class":91},[85,1122,1059],{"class":102},[85,1124,1125,1127,1129],{"class":87,"line":205},[85,1126,1073],{"class":102},[85,1128,1056],{"class":91},[85,1130,1087],{"class":102},[85,1132,1133],{"class":87,"line":217},[85,1134,229],{"class":102},[85,1136,1137],{"class":87,"line":226},[85,1138,236],{"emptyLinePlaceholder":235},[85,1140,1141,1143,1145,1147,1149,1152,1155],{"class":87,"line":232},[85,1142,1041],{"class":91},[85,1144,889],{"class":150},[85,1146,277],{"class":91},[85,1148,821],{"class":91},[85,1150,1151],{"class":102}," Vuex.",[85,1153,1154],{"class":98},"Store",[85,1156,1157],{"class":102},"({\n",[85,1159,1160,1162,1164],{"class":87,"line":239},[85,1161,1053],{"class":102},[85,1163,1056],{"class":91},[85,1165,1059],{"class":102},[85,1167,1168],{"class":87,"line":245},[85,1169,1170],{"class":102},"  modules: {\n",[85,1172,1173],{"class":87,"line":262},[85,1174,1175],{"class":102},"    a: moduleA,\n",[85,1177,1178],{"class":87,"line":268},[85,1179,1180],{"class":102},"    b: moduleB\n",[85,1182,1183],{"class":87,"line":303},[85,1184,202],{"class":102},[85,1186,1187],{"class":87,"line":309},[85,1188,1189],{"class":102},"})\n",[15,1191,1192,1193,1195,1196,1199,1200,1203,1204,1206,1207,1210,1211,1214,1215,1218,1219,1221,1222,1224],{},"对于以上代码，",[22,1194,441],{}," 可以看成 ",[22,1197,1198],{},"root"," 。在第一次执行时，会初始化一个 ",[22,1201,1202],{},"rootModule","，然后判断 ",[22,1205,1198],{}," 中是否存在 ",[22,1208,1209],{},"modules"," 属性，然后递归注册 ",[22,1212,1213],{},"module"," 。对于 child 来说，会获取到他所属的 ",[22,1216,1217],{},"parent",", 然后在 ",[22,1220,1217],{}," 中添加 ",[22,1223,1213],{}," 。",[76,1226,1228],{"className":78,"code":1227,"language":80,"meta":81,"style":81},"export default class ModuleCollection {\n  constructor (rawRootModule) {\n    \u002F\u002F register root module (Vuex.Store options)\n    this.register([], rawRootModule, false)\n  }\n  register (path, rawModule, runtime = true) {\n    \u002F\u002F 开发环境断言\n    if (process.env.NODE_ENV !== 'production') {\n      assertRawModule(path, rawModule)\n    }\n    \u002F\u002F 初始化 Module\n    const newModule = new Module(rawModule, runtime)\n    \u002F\u002F 对于第一次初始化 ModuleCollection 时\n    \u002F\u002F 会走第一个 if 条件，因为当前是 root\n    if (path.length === 0) {\n      this.root = newModule\n    } else {\n      \u002F\u002F 获取当前 Module 的 parent\n      const parent = this.get(path.slice(0, -1))\n      \u002F\u002F 添加 child，第一个参数是\n      \u002F\u002F 当前 Module 的 key 值\n      parent.addChild(path[path.length - 1], newModule)\n    }\n\n    \u002F\u002F 递归注册\n    if (rawModule.modules) {\n      forEachValue(rawModule.modules, (rawChildModule, key) => {\n        this.register(path.concat(key), rawChildModule, runtime)\n      })\n    }\n  }\n}\n\nexport default class Module {\n  constructor (rawModule, runtime) {\n    this.runtime = runtime\n    \u002F\u002F 用于存储 children\n    this._children = Object.create(null)\n    \u002F\u002F 用于存储原始的 rawModule\n    this._rawModule = rawModule\n    const rawState = rawModule.state\n\n    \u002F\u002F 用于存储 state\n    this.state = (typeof rawState === 'function' ? rawState() : rawState) || {}\n  }\n}\n",[22,1229,1230,1242,1253,1258,1275,1279,1306,1311,1325,1333,1337,1342,1359,1364,1369,1387,1399,1407,1412,1450,1455,1460,1482,1486,1490,1495,1502,1526,1543,1548,1552,1556,1560,1564,1576,1590,1602,1607,1626,1631,1643,1655,1660,1666,1704,1709],{"__ignoreMap":81},[85,1231,1232,1234,1236,1238,1240],{"class":87,"line":88},[85,1233,92],{"class":91},[85,1235,250],{"class":91},[85,1237,524],{"class":91},[85,1239,824],{"class":98},[85,1241,346],{"class":102},[85,1243,1244,1246,1248,1251],{"class":87,"line":113},[85,1245,534],{"class":91},[85,1247,537],{"class":102},[85,1249,1250],{"class":106},"rawRootModule",[85,1252,110],{"class":102},[85,1254,1255],{"class":87,"line":120},[85,1256,1257],{"class":116},"    \u002F\u002F register root module (Vuex.Store options)\n",[85,1259,1260,1262,1264,1267,1270,1273],{"class":87,"line":141},[85,1261,730],{"class":150},[85,1263,932],{"class":102},[85,1265,1266],{"class":98},"register",[85,1268,1269],{"class":102},"([], rawRootModule, ",[85,1271,1272],{"class":150},"false",[85,1274,627],{"class":102},[85,1276,1277],{"class":87,"line":163},[85,1278,202],{"class":102},[85,1280,1281,1284,1286,1289,1291,1294,1296,1299,1301,1304],{"class":87,"line":175},[85,1282,1283],{"class":98},"  register",[85,1285,537],{"class":102},[85,1287,1288],{"class":106},"path",[85,1290,646],{"class":102},[85,1292,1293],{"class":106},"rawModule",[85,1295,646],{"class":102},[85,1297,1298],{"class":106},"runtime",[85,1300,277],{"class":91},[85,1302,1303],{"class":150}," true",[85,1305,110],{"class":102},[85,1307,1308],{"class":87,"line":181},[85,1309,1310],{"class":116},"    \u002F\u002F 开发环境断言\n",[85,1312,1313,1315,1317,1319,1321,1323],{"class":87,"line":187},[85,1314,144],{"class":91},[85,1316,147],{"class":102},[85,1318,151],{"class":150},[85,1320,154],{"class":91},[85,1322,158],{"class":157},[85,1324,110],{"class":102},[85,1326,1327,1330],{"class":87,"line":193},[85,1328,1329],{"class":98},"      assertRawModule",[85,1331,1332],{"class":102},"(path, rawModule)\n",[85,1334,1335],{"class":87,"line":199},[85,1336,190],{"class":102},[85,1338,1339],{"class":87,"line":205},[85,1340,1341],{"class":116},"    \u002F\u002F 初始化 Module\n",[85,1343,1344,1346,1349,1351,1353,1356],{"class":87,"line":217},[85,1345,387],{"class":91},[85,1347,1348],{"class":150}," newModule",[85,1350,277],{"class":91},[85,1352,821],{"class":91},[85,1354,1355],{"class":98}," Module",[85,1357,1358],{"class":102},"(rawModule, runtime)\n",[85,1360,1361],{"class":87,"line":226},[85,1362,1363],{"class":116},"    \u002F\u002F 对于第一次初始化 ModuleCollection 时\n",[85,1365,1366],{"class":87,"line":232},[85,1367,1368],{"class":116},"    \u002F\u002F 会走第一个 if 条件，因为当前是 root\n",[85,1370,1371,1373,1376,1379,1382,1385],{"class":87,"line":239},[85,1372,144],{"class":91},[85,1374,1375],{"class":102}," (path.",[85,1377,1378],{"class":150},"length",[85,1380,1381],{"class":91}," ===",[85,1383,1384],{"class":150}," 0",[85,1386,110],{"class":102},[85,1388,1389,1391,1394,1396],{"class":87,"line":245},[85,1390,412],{"class":150},[85,1392,1393],{"class":102},".root ",[85,1395,211],{"class":91},[85,1397,1398],{"class":102}," newModule\n",[85,1400,1401,1403,1405],{"class":87,"line":262},[85,1402,456],{"class":102},[85,1404,343],{"class":91},[85,1406,346],{"class":102},[85,1408,1409],{"class":87,"line":268},[85,1410,1411],{"class":116},"      \u002F\u002F 获取当前 Module 的 parent\n",[85,1413,1414,1417,1420,1422,1424,1426,1429,1432,1435,1437,1439,1441,1444,1447],{"class":87,"line":303},[85,1415,1416],{"class":91},"      const",[85,1418,1419],{"class":150}," parent",[85,1421,277],{"class":91},[85,1423,395],{"class":150},[85,1425,932],{"class":102},[85,1427,1428],{"class":98},"get",[85,1430,1431],{"class":102},"(path.",[85,1433,1434],{"class":98},"slice",[85,1436,103],{"class":102},[85,1438,297],{"class":150},[85,1440,646],{"class":102},[85,1442,1443],{"class":91},"-",[85,1445,1446],{"class":150},"1",[85,1448,1449],{"class":102},"))\n",[85,1451,1452],{"class":87,"line":309},[85,1453,1454],{"class":116},"      \u002F\u002F 添加 child，第一个参数是\n",[85,1456,1457],{"class":87,"line":325},[85,1458,1459],{"class":116},"      \u002F\u002F 当前 Module 的 key 值\n",[85,1461,1462,1465,1468,1471,1473,1476,1479],{"class":87,"line":337},[85,1463,1464],{"class":102},"      parent.",[85,1466,1467],{"class":98},"addChild",[85,1469,1470],{"class":102},"(path[path.",[85,1472,1378],{"class":150},[85,1474,1475],{"class":91}," -",[85,1477,1478],{"class":150}," 1",[85,1480,1481],{"class":102},"], newModule)\n",[85,1483,1484],{"class":87,"line":349},[85,1485,190],{"class":102},[85,1487,1488],{"class":87,"line":355},[85,1489,236],{"emptyLinePlaceholder":235},[85,1491,1492],{"class":87,"line":360},[85,1493,1494],{"class":116},"    \u002F\u002F 递归注册\n",[85,1496,1497,1499],{"class":87,"line":366},[85,1498,144],{"class":91},[85,1500,1501],{"class":102}," (rawModule.modules) {\n",[85,1503,1504,1507,1510,1513,1515,1518,1521,1524],{"class":87,"line":372},[85,1505,1506],{"class":98},"      forEachValue",[85,1508,1509],{"class":102},"(rawModule.modules, (",[85,1511,1512],{"class":106},"rawChildModule",[85,1514,646],{"class":102},[85,1516,1517],{"class":106},"key",[85,1519,1520],{"class":102},") ",[85,1522,1523],{"class":91},"=>",[85,1525,346],{"class":102},[85,1527,1528,1531,1533,1535,1537,1540],{"class":87,"line":384},[85,1529,1530],{"class":150},"        this",[85,1532,932],{"class":102},[85,1534,1266],{"class":98},[85,1536,1431],{"class":102},[85,1538,1539],{"class":98},"concat",[85,1541,1542],{"class":102},"(key), rawChildModule, runtime)\n",[85,1544,1545],{"class":87,"line":401},[85,1546,1547],{"class":102},"      })\n",[85,1549,1550],{"class":87,"line":409},[85,1551,190],{"class":102},[85,1553,1554],{"class":87,"line":421},[85,1555,202],{"class":102},[85,1557,1558],{"class":87,"line":453},[85,1559,229],{"class":102},[85,1561,1562],{"class":87,"line":472},[85,1563,236],{"emptyLinePlaceholder":235},[85,1565,1566,1568,1570,1572,1574],{"class":87,"line":484},[85,1567,92],{"class":91},[85,1569,250],{"class":91},[85,1571,524],{"class":91},[85,1573,1355],{"class":98},[85,1575,346],{"class":102},[85,1577,1578,1580,1582,1584,1586,1588],{"class":87,"line":489},[85,1579,534],{"class":91},[85,1581,537],{"class":102},[85,1583,1293],{"class":106},[85,1585,646],{"class":102},[85,1587,1298],{"class":106},[85,1589,110],{"class":102},[85,1591,1592,1594,1597,1599],{"class":87,"line":494},[85,1593,730],{"class":150},[85,1595,1596],{"class":102},".runtime ",[85,1598,211],{"class":91},[85,1600,1601],{"class":102}," runtime\n",[85,1603,1604],{"class":87,"line":970},[85,1605,1606],{"class":116},"    \u002F\u002F 用于存储 children\n",[85,1608,1609,1611,1614,1616,1618,1620,1622,1624],{"class":87,"line":975},[85,1610,730],{"class":150},[85,1612,1613],{"class":102},"._children ",[85,1615,211],{"class":91},[85,1617,749],{"class":102},[85,1619,752],{"class":98},[85,1621,103],{"class":102},[85,1623,757],{"class":150},[85,1625,627],{"class":102},[85,1627,1628],{"class":87,"line":1005},[85,1629,1630],{"class":116},"    \u002F\u002F 用于存储原始的 rawModule\n",[85,1632,1633,1635,1638,1640],{"class":87,"line":1018},[85,1634,730],{"class":150},[85,1636,1637],{"class":102},"._rawModule ",[85,1639,211],{"class":91},[85,1641,1642],{"class":102}," rawModule\n",[85,1644,1645,1647,1650,1652],{"class":87,"line":1023},[85,1646,387],{"class":91},[85,1648,1649],{"class":150}," rawState",[85,1651,277],{"class":91},[85,1653,1654],{"class":102}," rawModule.state\n",[85,1656,1658],{"class":87,"line":1657},42,[85,1659,236],{"emptyLinePlaceholder":235},[85,1661,1663],{"class":87,"line":1662},43,[85,1664,1665],{"class":116},"    \u002F\u002F 用于存储 state\n",[85,1667,1669,1671,1674,1676,1678,1680,1683,1685,1687,1689,1691,1693,1695,1698,1701],{"class":87,"line":1668},44,[85,1670,730],{"class":150},[85,1672,1673],{"class":102},".state ",[85,1675,211],{"class":91},[85,1677,537],{"class":102},[85,1679,636],{"class":91},[85,1681,1682],{"class":102}," rawState ",[85,1684,135],{"class":91},[85,1686,432],{"class":157},[85,1688,435],{"class":91},[85,1690,1649],{"class":98},[85,1692,444],{"class":102},[85,1694,447],{"class":91},[85,1696,1697],{"class":102}," rawState) ",[85,1699,1700],{"class":91},"||",[85,1702,1703],{"class":102}," {}\n",[85,1705,1707],{"class":87,"line":1706},45,[85,1708,202],{"class":102},[85,1710,1712],{"class":87,"line":1711},46,[85,1713,229],{"class":102},[502,1715,1717],{"id":1716},"installmodule",[22,1718,1719],{},"installModule",[15,1721,1028,1722,1724],{},[22,1723,1719],{}," 的实现",[76,1726,1728],{"className":78,"code":1727,"language":80,"meta":81,"style":81},"\u002F\u002F installModule(this, state, [], this._modules.root)\nfunction installModule(store, rootState, path, module, hot) {\n  \u002F\u002F 判断是否为 rootModule\n  const isRoot = !path.length\n  \u002F\u002F 获取 namespace，root 没有 namespace\n  \u002F\u002F 对于 modules: {a: moduleA} 来说\n  \u002F\u002F namespace = 'a\u002F'\n  const namespace = store._modules.getNamespace(path)\n\n  \u002F\u002F 为 namespace 缓存 module\n  if (module.namespaced) {\n    store._modulesNamespaceMap[namespace] = module\n  }\n\n  \u002F\u002F 设置 state\n  if (!isRoot && !hot) {\n    \u002F\u002F 以下逻辑就是给 store.state 添加属性\n    \u002F\u002F 根据模块添加\n    \u002F\u002F state: { xxx: 1, a: {...}, b: {...} }\n    const parentState = getNestedState(rootState, path.slice(0, -1))\n    const moduleName = path[path.length - 1]\n    store._withCommit(() => {\n      Vue.set(parentState, moduleName, module.state)\n    })\n  }\n  \u002F\u002F 该方法其实是在重写 dispatch 和 commit 函数\n  \u002F\u002F 你是否有疑问模块中的 dispatch 和 commit\n  \u002F\u002F 是如何找到对应模块中的函数的\n  \u002F\u002F 假如模块 A 中有一个名为 add 的 mutation\n  \u002F\u002F 通过 makeLocalContext 函数，会将 add 变成\n  \u002F\u002F a\u002Fadd，这样就可以找到模块 A 中对应函数了\n  const local = (module.context = makeLocalContext(store, namespace, path))\n\n  \u002F\u002F 以下几个函数遍历，都是在\n  \u002F\u002F 注册模块中的 mutation、action 和 getter\n  \u002F\u002F 假如模块 A 中有名为 add 的 mutation 函数\n  \u002F\u002F 在注册过程中会变成 a\u002Fadd\n  module.forEachMutation((mutation, key) => {\n    const namespacedType = namespace + key\n    registerMutation(store, namespacedType, mutation, local)\n  })\n\n  module.forEachAction((action, key) => {\n    const type = action.root ? key : namespace + key\n    const handler = action.handler || action\n    registerAction(store, type, handler, local)\n  })\n\n  \u002F\u002F 这里会生成一个 _wrappedGetters 属性\n  \u002F\u002F 用于缓存 getter，便于下次使用\n  module.forEachGetter((getter, key) => {\n    const namespacedType = namespace + key\n    registerGetter(store, namespacedType, getter, local)\n  })\n\n  \u002F\u002F 递归安装模块\n  module.forEachChild((child, key) => {\n    installModule(store, rootState, path.concat(key), child, hot)\n  })\n}\n",[22,1729,1730,1735,1767,1772,1790,1795,1800,1805,1823,1827,1832,1843,1853,1857,1861,1866,1884,1889,1894,1899,1928,1949,1964,1980,1985,1989,1994,1999,2004,2009,2014,2019,2043,2047,2052,2057,2062,2067,2093,2111,2119,2124,2128,2152,2178,2195,2203,2208,2213,2219,2225,2250,2265,2274,2279,2284,2290,2315,2329,2334],{"__ignoreMap":81},[85,1731,1732],{"class":87,"line":88},[85,1733,1734],{"class":116},"\u002F\u002F installModule(this, state, [], this._modules.root)\n",[85,1736,1737,1740,1743,1745,1747,1749,1752,1754,1756,1758,1760,1762,1765],{"class":87,"line":113},[85,1738,1739],{"class":91},"function",[85,1741,1742],{"class":98}," installModule",[85,1744,103],{"class":102},[85,1746,441],{"class":106},[85,1748,646],{"class":102},[85,1750,1751],{"class":106},"rootState",[85,1753,646],{"class":102},[85,1755,1288],{"class":106},[85,1757,646],{"class":102},[85,1759,1213],{"class":106},[85,1761,646],{"class":102},[85,1763,1764],{"class":106},"hot",[85,1766,110],{"class":102},[85,1768,1769],{"class":87,"line":120},[85,1770,1771],{"class":116},"  \u002F\u002F 判断是否为 rootModule\n",[85,1773,1774,1776,1779,1781,1784,1787],{"class":87,"line":141},[85,1775,271],{"class":91},[85,1777,1778],{"class":150}," isRoot",[85,1780,277],{"class":91},[85,1782,1783],{"class":91}," !",[85,1785,1786],{"class":102},"path.",[85,1788,1789],{"class":150},"length\n",[85,1791,1792],{"class":87,"line":163},[85,1793,1794],{"class":116},"  \u002F\u002F 获取 namespace，root 没有 namespace\n",[85,1796,1797],{"class":87,"line":175},[85,1798,1799],{"class":116},"  \u002F\u002F 对于 modules: {a: moduleA} 来说\n",[85,1801,1802],{"class":87,"line":181},[85,1803,1804],{"class":116},"  \u002F\u002F namespace = 'a\u002F'\n",[85,1806,1807,1809,1812,1814,1817,1820],{"class":87,"line":187},[85,1808,271],{"class":91},[85,1810,1811],{"class":150}," namespace",[85,1813,277],{"class":91},[85,1815,1816],{"class":102}," store._modules.",[85,1818,1819],{"class":98},"getNamespace",[85,1821,1822],{"class":102},"(path)\n",[85,1824,1825],{"class":87,"line":193},[85,1826,236],{"emptyLinePlaceholder":235},[85,1828,1829],{"class":87,"line":199},[85,1830,1831],{"class":116},"  \u002F\u002F 为 namespace 缓存 module\n",[85,1833,1834,1836,1838,1840],{"class":87,"line":205},[85,1835,123],{"class":91},[85,1837,537],{"class":102},[85,1839,1213],{"class":150},[85,1841,1842],{"class":102},".namespaced) {\n",[85,1844,1845,1848,1850],{"class":87,"line":217},[85,1846,1847],{"class":102},"    store._modulesNamespaceMap[namespace] ",[85,1849,211],{"class":91},[85,1851,1852],{"class":150}," module\n",[85,1854,1855],{"class":87,"line":226},[85,1856,202],{"class":102},[85,1858,1859],{"class":87,"line":232},[85,1860,236],{"emptyLinePlaceholder":235},[85,1862,1863],{"class":87,"line":239},[85,1864,1865],{"class":116},"  \u002F\u002F 设置 state\n",[85,1867,1868,1870,1872,1874,1877,1879,1881],{"class":87,"line":245},[85,1869,123],{"class":91},[85,1871,537],{"class":102},[85,1873,559],{"class":91},[85,1875,1876],{"class":102},"isRoot ",[85,1878,129],{"class":91},[85,1880,1783],{"class":91},[85,1882,1883],{"class":102},"hot) {\n",[85,1885,1886],{"class":87,"line":262},[85,1887,1888],{"class":116},"    \u002F\u002F 以下逻辑就是给 store.state 添加属性\n",[85,1890,1891],{"class":87,"line":268},[85,1892,1893],{"class":116},"    \u002F\u002F 根据模块添加\n",[85,1895,1896],{"class":87,"line":303},[85,1897,1898],{"class":116},"    \u002F\u002F state: { xxx: 1, a: {...}, b: {...} }\n",[85,1900,1901,1903,1906,1908,1911,1914,1916,1918,1920,1922,1924,1926],{"class":87,"line":309},[85,1902,387],{"class":91},[85,1904,1905],{"class":150}," parentState",[85,1907,277],{"class":91},[85,1909,1910],{"class":98}," getNestedState",[85,1912,1913],{"class":102},"(rootState, path.",[85,1915,1434],{"class":98},[85,1917,103],{"class":102},[85,1919,297],{"class":150},[85,1921,646],{"class":102},[85,1923,1443],{"class":91},[85,1925,1446],{"class":150},[85,1927,1449],{"class":102},[85,1929,1930,1932,1935,1937,1940,1942,1944,1946],{"class":87,"line":325},[85,1931,387],{"class":91},[85,1933,1934],{"class":150}," moduleName",[85,1936,277],{"class":91},[85,1938,1939],{"class":102}," path[path.",[85,1941,1378],{"class":150},[85,1943,1475],{"class":91},[85,1945,1478],{"class":150},[85,1947,1948],{"class":102},"]\n",[85,1950,1951,1954,1957,1960,1962],{"class":87,"line":337},[85,1952,1953],{"class":102},"    store.",[85,1955,1956],{"class":98},"_withCommit",[85,1958,1959],{"class":102},"(() ",[85,1961,1523],{"class":91},[85,1963,346],{"class":102},[85,1965,1966,1969,1972,1975,1977],{"class":87,"line":349},[85,1967,1968],{"class":102},"      Vue.",[85,1970,1971],{"class":98},"set",[85,1973,1974],{"class":102},"(parentState, moduleName, ",[85,1976,1213],{"class":150},[85,1978,1979],{"class":102},".state)\n",[85,1981,1982],{"class":87,"line":355},[85,1983,1984],{"class":102},"    })\n",[85,1986,1987],{"class":87,"line":360},[85,1988,202],{"class":102},[85,1990,1991],{"class":87,"line":366},[85,1992,1993],{"class":116},"  \u002F\u002F 该方法其实是在重写 dispatch 和 commit 函数\n",[85,1995,1996],{"class":87,"line":372},[85,1997,1998],{"class":116},"  \u002F\u002F 你是否有疑问模块中的 dispatch 和 commit\n",[85,2000,2001],{"class":87,"line":384},[85,2002,2003],{"class":116},"  \u002F\u002F 是如何找到对应模块中的函数的\n",[85,2005,2006],{"class":87,"line":401},[85,2007,2008],{"class":116},"  \u002F\u002F 假如模块 A 中有一个名为 add 的 mutation\n",[85,2010,2011],{"class":87,"line":409},[85,2012,2013],{"class":116},"  \u002F\u002F 通过 makeLocalContext 函数，会将 add 变成\n",[85,2015,2016],{"class":87,"line":421},[85,2017,2018],{"class":116},"  \u002F\u002F a\u002Fadd，这样就可以找到模块 A 中对应函数了\n",[85,2020,2021,2023,2026,2028,2030,2032,2035,2037,2040],{"class":87,"line":453},[85,2022,271],{"class":91},[85,2024,2025],{"class":150}," local",[85,2027,277],{"class":91},[85,2029,537],{"class":102},[85,2031,1213],{"class":150},[85,2033,2034],{"class":102},".context ",[85,2036,211],{"class":91},[85,2038,2039],{"class":98}," makeLocalContext",[85,2041,2042],{"class":102},"(store, namespace, path))\n",[85,2044,2045],{"class":87,"line":472},[85,2046,236],{"emptyLinePlaceholder":235},[85,2048,2049],{"class":87,"line":484},[85,2050,2051],{"class":116},"  \u002F\u002F 以下几个函数遍历，都是在\n",[85,2053,2054],{"class":87,"line":489},[85,2055,2056],{"class":116},"  \u002F\u002F 注册模块中的 mutation、action 和 getter\n",[85,2058,2059],{"class":87,"line":494},[85,2060,2061],{"class":116},"  \u002F\u002F 假如模块 A 中有名为 add 的 mutation 函数\n",[85,2063,2064],{"class":87,"line":970},[85,2065,2066],{"class":116},"  \u002F\u002F 在注册过程中会变成 a\u002Fadd\n",[85,2068,2069,2072,2074,2077,2080,2083,2085,2087,2089,2091],{"class":87,"line":975},[85,2070,2071],{"class":150},"  module",[85,2073,932],{"class":102},[85,2075,2076],{"class":98},"forEachMutation",[85,2078,2079],{"class":102},"((",[85,2081,2082],{"class":106},"mutation",[85,2084,646],{"class":102},[85,2086,1517],{"class":106},[85,2088,1520],{"class":102},[85,2090,1523],{"class":91},[85,2092,346],{"class":102},[85,2094,2095,2097,2100,2102,2105,2108],{"class":87,"line":1005},[85,2096,387],{"class":91},[85,2098,2099],{"class":150}," namespacedType",[85,2101,277],{"class":91},[85,2103,2104],{"class":102}," namespace ",[85,2106,2107],{"class":91},"+",[85,2109,2110],{"class":102}," key\n",[85,2112,2113,2116],{"class":87,"line":1018},[85,2114,2115],{"class":98},"    registerMutation",[85,2117,2118],{"class":102},"(store, namespacedType, mutation, local)\n",[85,2120,2121],{"class":87,"line":1023},[85,2122,2123],{"class":102},"  })\n",[85,2125,2126],{"class":87,"line":1657},[85,2127,236],{"emptyLinePlaceholder":235},[85,2129,2130,2132,2134,2137,2139,2142,2144,2146,2148,2150],{"class":87,"line":1662},[85,2131,2071],{"class":150},[85,2133,932],{"class":102},[85,2135,2136],{"class":98},"forEachAction",[85,2138,2079],{"class":102},[85,2140,2141],{"class":106},"action",[85,2143,646],{"class":102},[85,2145,1517],{"class":106},[85,2147,1520],{"class":102},[85,2149,1523],{"class":91},[85,2151,346],{"class":102},[85,2153,2154,2156,2159,2161,2164,2167,2170,2172,2174,2176],{"class":87,"line":1668},[85,2155,387],{"class":91},[85,2157,2158],{"class":150}," type",[85,2160,277],{"class":91},[85,2162,2163],{"class":102}," action.root ",[85,2165,2166],{"class":91},"?",[85,2168,2169],{"class":102}," key ",[85,2171,447],{"class":91},[85,2173,2104],{"class":102},[85,2175,2107],{"class":91},[85,2177,2110],{"class":102},[85,2179,2180,2182,2185,2187,2190,2192],{"class":87,"line":1706},[85,2181,387],{"class":91},[85,2183,2184],{"class":150}," handler",[85,2186,277],{"class":91},[85,2188,2189],{"class":102}," action.handler ",[85,2191,1700],{"class":91},[85,2193,2194],{"class":102}," action\n",[85,2196,2197,2200],{"class":87,"line":1711},[85,2198,2199],{"class":98},"    registerAction",[85,2201,2202],{"class":102},"(store, type, handler, local)\n",[85,2204,2206],{"class":87,"line":2205},47,[85,2207,2123],{"class":102},[85,2209,2211],{"class":87,"line":2210},48,[85,2212,236],{"emptyLinePlaceholder":235},[85,2214,2216],{"class":87,"line":2215},49,[85,2217,2218],{"class":116},"  \u002F\u002F 这里会生成一个 _wrappedGetters 属性\n",[85,2220,2222],{"class":87,"line":2221},50,[85,2223,2224],{"class":116},"  \u002F\u002F 用于缓存 getter，便于下次使用\n",[85,2226,2228,2230,2232,2235,2237,2240,2242,2244,2246,2248],{"class":87,"line":2227},51,[85,2229,2071],{"class":150},[85,2231,932],{"class":102},[85,2233,2234],{"class":98},"forEachGetter",[85,2236,2079],{"class":102},[85,2238,2239],{"class":106},"getter",[85,2241,646],{"class":102},[85,2243,1517],{"class":106},[85,2245,1520],{"class":102},[85,2247,1523],{"class":91},[85,2249,346],{"class":102},[85,2251,2253,2255,2257,2259,2261,2263],{"class":87,"line":2252},52,[85,2254,387],{"class":91},[85,2256,2099],{"class":150},[85,2258,277],{"class":91},[85,2260,2104],{"class":102},[85,2262,2107],{"class":91},[85,2264,2110],{"class":102},[85,2266,2268,2271],{"class":87,"line":2267},53,[85,2269,2270],{"class":98},"    registerGetter",[85,2272,2273],{"class":102},"(store, namespacedType, getter, local)\n",[85,2275,2277],{"class":87,"line":2276},54,[85,2278,2123],{"class":102},[85,2280,2282],{"class":87,"line":2281},55,[85,2283,236],{"emptyLinePlaceholder":235},[85,2285,2287],{"class":87,"line":2286},56,[85,2288,2289],{"class":116},"  \u002F\u002F 递归安装模块\n",[85,2291,2293,2295,2297,2300,2302,2305,2307,2309,2311,2313],{"class":87,"line":2292},57,[85,2294,2071],{"class":150},[85,2296,932],{"class":102},[85,2298,2299],{"class":98},"forEachChild",[85,2301,2079],{"class":102},[85,2303,2304],{"class":106},"child",[85,2306,646],{"class":102},[85,2308,1517],{"class":106},[85,2310,1520],{"class":102},[85,2312,1523],{"class":91},[85,2314,346],{"class":102},[85,2316,2318,2321,2324,2326],{"class":87,"line":2317},58,[85,2319,2320],{"class":98},"    installModule",[85,2322,2323],{"class":102},"(store, rootState, path.",[85,2325,1539],{"class":98},[85,2327,2328],{"class":102},"(key), child, hot)\n",[85,2330,2332],{"class":87,"line":2331},59,[85,2333,2123],{"class":102},[85,2335,2337],{"class":87,"line":2336},60,[85,2338,229],{"class":102},[502,2340,2342],{"id":2341},"resetstorevm",[22,2343,2344],{},"resetStoreVM",[15,2346,1028,2347,2349,2350,2353,2354,2357],{},[22,2348,2344],{}," 的实现，该属性实现了状态的响应式，并且将 ",[22,2351,2352],{},"_wrappedGetters"," 作为 ",[22,2355,2356],{},"computed"," 属性。",[76,2359,2361],{"className":78,"code":2360,"language":80,"meta":81,"style":81},"\u002F\u002F resetStoreVM(this, state)\nfunction resetStoreVM(store, state, hot) {\n  const oldVm = store._vm\n\n  \u002F\u002F 设置 getters 属性\n  store.getters = {}\n  const wrappedGetters = store._wrappedGetters\n  const computed = {}\n  \u002F\u002F 遍历 _wrappedGetters 属性\n  forEachValue(wrappedGetters, (fn, key) => {\n    \u002F\u002F 给 computed 对象添加属性\n    computed[key] = () => fn(store)\n    \u002F\u002F 重写 get 方法\n    \u002F\u002F store.getters.xx 其实是访问了\n    \u002F\u002F store._vm[xx]\n    \u002F\u002F 也就是 computed 中的属性\n    Object.defineProperty(store.getters, key, {\n      get: () => store._vm[key],\n      enumerable: true, \u002F\u002F for local getters\n    })\n  })\n\n  \u002F\u002F 使用 Vue 来保存 state 树\n  \u002F\u002F 同时也让 state 变成响应式\n  const silent = Vue.config.silent\n  Vue.config.silent = true\n  \u002F\u002F 当访问 store.state 时\n  \u002F\u002F 其实是访问了 store._vm._data.$$state\n  store._vm = new Vue({\n    data: {\n      $$state: state,\n    },\n    computed,\n  })\n  Vue.config.silent = silent\n\n  \u002F\u002F 确保只能通过 commit 的方式改变状态\n  if (store.strict) {\n    enableStrictMode(store)\n  }\n}\n",[22,2362,2363,2368,2390,2402,2406,2411,2420,2432,2443,2448,2469,2474,2492,2497,2502,2507,2512,2523,2536,2549,2553,2557,2561,2566,2571,2583,2593,2598,2603,2616,2621,2626,2631,2636,2640,2649,2653,2658,2665,2672,2676],{"__ignoreMap":81},[85,2364,2365],{"class":87,"line":88},[85,2366,2367],{"class":116},"\u002F\u002F resetStoreVM(this, state)\n",[85,2369,2370,2372,2375,2377,2379,2381,2384,2386,2388],{"class":87,"line":113},[85,2371,1739],{"class":91},[85,2373,2374],{"class":98}," resetStoreVM",[85,2376,103],{"class":102},[85,2378,441],{"class":106},[85,2380,646],{"class":102},[85,2382,2383],{"class":106},"state",[85,2385,646],{"class":102},[85,2387,1764],{"class":106},[85,2389,110],{"class":102},[85,2391,2392,2394,2397,2399],{"class":87,"line":120},[85,2393,271],{"class":91},[85,2395,2396],{"class":150}," oldVm",[85,2398,277],{"class":91},[85,2400,2401],{"class":102}," store._vm\n",[85,2403,2404],{"class":87,"line":141},[85,2405,236],{"emptyLinePlaceholder":235},[85,2407,2408],{"class":87,"line":163},[85,2409,2410],{"class":116},"  \u002F\u002F 设置 getters 属性\n",[85,2412,2413,2416,2418],{"class":87,"line":175},[85,2414,2415],{"class":102},"  store.getters ",[85,2417,211],{"class":91},[85,2419,1703],{"class":102},[85,2421,2422,2424,2427,2429],{"class":87,"line":181},[85,2423,271],{"class":91},[85,2425,2426],{"class":150}," wrappedGetters",[85,2428,277],{"class":91},[85,2430,2431],{"class":102}," store._wrappedGetters\n",[85,2433,2434,2436,2439,2441],{"class":87,"line":187},[85,2435,271],{"class":91},[85,2437,2438],{"class":150}," computed",[85,2440,277],{"class":91},[85,2442,1703],{"class":102},[85,2444,2445],{"class":87,"line":193},[85,2446,2447],{"class":116},"  \u002F\u002F 遍历 _wrappedGetters 属性\n",[85,2449,2450,2453,2456,2459,2461,2463,2465,2467],{"class":87,"line":199},[85,2451,2452],{"class":98},"  forEachValue",[85,2454,2455],{"class":102},"(wrappedGetters, (",[85,2457,2458],{"class":106},"fn",[85,2460,646],{"class":102},[85,2462,1517],{"class":106},[85,2464,1520],{"class":102},[85,2466,1523],{"class":91},[85,2468,346],{"class":102},[85,2470,2471],{"class":87,"line":205},[85,2472,2473],{"class":116},"    \u002F\u002F 给 computed 对象添加属性\n",[85,2475,2476,2479,2481,2484,2486,2489],{"class":87,"line":217},[85,2477,2478],{"class":102},"    computed[key] ",[85,2480,211],{"class":91},[85,2482,2483],{"class":102}," () ",[85,2485,1523],{"class":91},[85,2487,2488],{"class":98}," fn",[85,2490,2491],{"class":102},"(store)\n",[85,2493,2494],{"class":87,"line":226},[85,2495,2496],{"class":116},"    \u002F\u002F 重写 get 方法\n",[85,2498,2499],{"class":87,"line":232},[85,2500,2501],{"class":116},"    \u002F\u002F store.getters.xx 其实是访问了\n",[85,2503,2504],{"class":87,"line":239},[85,2505,2506],{"class":116},"    \u002F\u002F store._vm[xx]\n",[85,2508,2509],{"class":87,"line":245},[85,2510,2511],{"class":116},"    \u002F\u002F 也就是 computed 中的属性\n",[85,2513,2514,2517,2520],{"class":87,"line":262},[85,2515,2516],{"class":102},"    Object.",[85,2518,2519],{"class":98},"defineProperty",[85,2521,2522],{"class":102},"(store.getters, key, {\n",[85,2524,2525,2528,2531,2533],{"class":87,"line":268},[85,2526,2527],{"class":98},"      get",[85,2529,2530],{"class":102},": () ",[85,2532,1523],{"class":91},[85,2534,2535],{"class":102}," store._vm[key],\n",[85,2537,2538,2541,2544,2546],{"class":87,"line":303},[85,2539,2540],{"class":102},"      enumerable: ",[85,2542,2543],{"class":150},"true",[85,2545,646],{"class":102},[85,2547,2548],{"class":116},"\u002F\u002F for local getters\n",[85,2550,2551],{"class":87,"line":309},[85,2552,1984],{"class":102},[85,2554,2555],{"class":87,"line":325},[85,2556,2123],{"class":102},[85,2558,2559],{"class":87,"line":337},[85,2560,236],{"emptyLinePlaceholder":235},[85,2562,2563],{"class":87,"line":349},[85,2564,2565],{"class":116},"  \u002F\u002F 使用 Vue 来保存 state 树\n",[85,2567,2568],{"class":87,"line":355},[85,2569,2570],{"class":116},"  \u002F\u002F 同时也让 state 变成响应式\n",[85,2572,2573,2575,2578,2580],{"class":87,"line":360},[85,2574,271],{"class":91},[85,2576,2577],{"class":150}," silent",[85,2579,277],{"class":91},[85,2581,2582],{"class":102}," Vue.config.silent\n",[85,2584,2585,2588,2590],{"class":87,"line":366},[85,2586,2587],{"class":102},"  Vue.config.silent ",[85,2589,211],{"class":91},[85,2591,2592],{"class":150}," true\n",[85,2594,2595],{"class":87,"line":372},[85,2596,2597],{"class":116},"  \u002F\u002F 当访问 store.state 时\n",[85,2599,2600],{"class":87,"line":384},[85,2601,2602],{"class":116},"  \u002F\u002F 其实是访问了 store._vm._data.$$state\n",[85,2604,2605,2608,2610,2612,2614],{"class":87,"line":401},[85,2606,2607],{"class":102},"  store._vm ",[85,2609,211],{"class":91},[85,2611,821],{"class":91},[85,2613,871],{"class":98},[85,2615,1157],{"class":102},[85,2617,2618],{"class":87,"line":409},[85,2619,2620],{"class":102},"    data: {\n",[85,2622,2623],{"class":87,"line":421},[85,2624,2625],{"class":102},"      $$state: state,\n",[85,2627,2628],{"class":87,"line":453},[85,2629,2630],{"class":102},"    },\n",[85,2632,2633],{"class":87,"line":472},[85,2634,2635],{"class":102},"    computed,\n",[85,2637,2638],{"class":87,"line":484},[85,2639,2123],{"class":102},[85,2641,2642,2644,2646],{"class":87,"line":489},[85,2643,2587],{"class":102},[85,2645,211],{"class":91},[85,2647,2648],{"class":102}," silent\n",[85,2650,2651],{"class":87,"line":494},[85,2652,236],{"emptyLinePlaceholder":235},[85,2654,2655],{"class":87,"line":970},[85,2656,2657],{"class":116},"  \u002F\u002F 确保只能通过 commit 的方式改变状态\n",[85,2659,2660,2662],{"class":87,"line":975},[85,2661,123],{"class":91},[85,2663,2664],{"class":102}," (store.strict) {\n",[85,2666,2667,2670],{"class":87,"line":1005},[85,2668,2669],{"class":98},"    enableStrictMode",[85,2671,2491],{"class":102},[85,2673,2674],{"class":87,"line":1018},[85,2675,202],{"class":102},[85,2677,2678],{"class":87,"line":1023},[85,2679,229],{"class":102},[31,2681,2683],{"id":2682},"常用-api","常用 API",[502,2685,2687],{"id":2686},"commit-解析","commit 解析",[15,2689,2690,2691,2693,2694,2696],{},"如果需要改变状态的话，一般都会使用 ",[22,2692,24],{}," 去操作，接下来让我们来看看 ",[22,2695,24],{}," 是如何实现状态的改变的",[76,2698,2700],{"className":78,"code":2699,"language":80,"meta":81,"style":81},"commit(_type, _payload, _options) {\n  \u002F\u002F 检查传入的参数\n  const { type, payload, options } = unifyObjectStyle(\n    _type,\n    _payload,\n    _options\n  )\n\n  const mutation = { type, payload }\n  \u002F\u002F 找到对应的 mutation 函数\n  const entry = this._mutations[type]\n  \u002F\u002F 判断是否找到\n  if (!entry) {\n    if (process.env.NODE_ENV !== 'production') {\n      console.error(`[vuex] unknown mutation type: ${type}`)\n    }\n    return\n  }\n  \u002F\u002F _withCommit 函数将 _committing\n  \u002F\u002F 设置为 TRUE，保证在 strict 模式下\n  \u002F\u002F 只能 commit 改变状态\n  this._withCommit(() => {\n    entry.forEach(function commitIterator(handler) {\n      \u002F\u002F entry.push(function wrappedMutationHandler(payload) {\n      \u002F\u002F   handler.call(store, local.state, payload)\n      \u002F\u002F })\n      \u002F\u002F handle 就是 wrappedMutationHandler 函数\n      \u002F\u002F wrappedMutationHandler 内部就是调用\n      \u002F\u002F 对于的 mutation 函数\n      handler(payload)\n    })\n  })\n  \u002F\u002F 执行订阅函数\n  this._subscribers.forEach(sub => sub(mutation, this.state))\n}\n",[22,2701,2702,2709,2714,2739,2744,2749,2754,2759,2763,2775,2780,2794,2799,2810,2824,2842,2846,2850,2854,2859,2864,2869,2884,2906,2911,2916,2921,2926,2931,2936,2944,2948,2952,2957,2985],{"__ignoreMap":81},[85,2703,2704,2706],{"class":87,"line":88},[85,2705,24],{"class":98},[85,2707,2708],{"class":102},"(_type, _payload, _options) {\n",[85,2710,2711],{"class":87,"line":113},[85,2712,2713],{"class":116},"  \u002F\u002F 检查传入的参数\n",[85,2715,2716,2718,2720,2722,2724,2726,2728,2730,2732,2734,2737],{"class":87,"line":120},[85,2717,271],{"class":91},[85,2719,901],{"class":102},[85,2721,946],{"class":150},[85,2723,646],{"class":102},[85,2725,951],{"class":150},[85,2727,646],{"class":102},[85,2729,540],{"class":150},[85,2731,911],{"class":102},[85,2733,211],{"class":91},[85,2735,2736],{"class":98}," unifyObjectStyle",[85,2738,172],{"class":102},[85,2740,2741],{"class":87,"line":141},[85,2742,2743],{"class":102},"    _type,\n",[85,2745,2746],{"class":87,"line":163},[85,2747,2748],{"class":102},"    _payload,\n",[85,2750,2751],{"class":87,"line":175},[85,2752,2753],{"class":102},"    _options\n",[85,2755,2756],{"class":87,"line":181},[85,2757,2758],{"class":102},"  )\n",[85,2760,2761],{"class":87,"line":187},[85,2762,236],{"emptyLinePlaceholder":235},[85,2764,2765,2767,2770,2772],{"class":87,"line":193},[85,2766,271],{"class":91},[85,2768,2769],{"class":150}," mutation",[85,2771,277],{"class":91},[85,2773,2774],{"class":102}," { type, payload }\n",[85,2776,2777],{"class":87,"line":199},[85,2778,2779],{"class":116},"  \u002F\u002F 找到对应的 mutation 函数\n",[85,2781,2782,2784,2787,2789,2791],{"class":87,"line":205},[85,2783,271],{"class":91},[85,2785,2786],{"class":150}," entry",[85,2788,277],{"class":91},[85,2790,395],{"class":150},[85,2792,2793],{"class":102},"._mutations[type]\n",[85,2795,2796],{"class":87,"line":217},[85,2797,2798],{"class":116},"  \u002F\u002F 判断是否找到\n",[85,2800,2801,2803,2805,2807],{"class":87,"line":226},[85,2802,123],{"class":91},[85,2804,537],{"class":102},[85,2806,559],{"class":91},[85,2808,2809],{"class":102},"entry) {\n",[85,2811,2812,2814,2816,2818,2820,2822],{"class":87,"line":232},[85,2813,144],{"class":91},[85,2815,147],{"class":102},[85,2817,151],{"class":150},[85,2819,154],{"class":91},[85,2821,158],{"class":157},[85,2823,110],{"class":102},[85,2825,2826,2828,2830,2832,2835,2837,2840],{"class":87,"line":239},[85,2827,166],{"class":102},[85,2829,169],{"class":98},[85,2831,103],{"class":102},[85,2833,2834],{"class":157},"`[vuex] unknown mutation type: ${",[85,2836,946],{"class":102},[85,2838,2839],{"class":157},"}`",[85,2841,627],{"class":102},[85,2843,2844],{"class":87,"line":245},[85,2845,190],{"class":102},[85,2847,2848],{"class":87,"line":262},[85,2849,196],{"class":91},[85,2851,2852],{"class":87,"line":268},[85,2853,202],{"class":102},[85,2855,2856],{"class":87,"line":303},[85,2857,2858],{"class":116},"  \u002F\u002F _withCommit 函数将 _committing\n",[85,2860,2861],{"class":87,"line":309},[85,2862,2863],{"class":116},"  \u002F\u002F 设置为 TRUE，保证在 strict 模式下\n",[85,2865,2866],{"class":87,"line":325},[85,2867,2868],{"class":116},"  \u002F\u002F 只能 commit 改变状态\n",[85,2870,2871,2874,2876,2878,2880,2882],{"class":87,"line":337},[85,2872,2873],{"class":150},"  this",[85,2875,932],{"class":102},[85,2877,1956],{"class":98},[85,2879,1959],{"class":102},[85,2881,1523],{"class":91},[85,2883,346],{"class":102},[85,2885,2886,2889,2892,2894,2896,2899,2901,2904],{"class":87,"line":349},[85,2887,2888],{"class":102},"    entry.",[85,2890,2891],{"class":98},"forEach",[85,2893,103],{"class":102},[85,2895,1739],{"class":91},[85,2897,2898],{"class":98}," commitIterator",[85,2900,103],{"class":102},[85,2902,2903],{"class":106},"handler",[85,2905,110],{"class":102},[85,2907,2908],{"class":87,"line":355},[85,2909,2910],{"class":116},"      \u002F\u002F entry.push(function wrappedMutationHandler(payload) {\n",[85,2912,2913],{"class":87,"line":360},[85,2914,2915],{"class":116},"      \u002F\u002F   handler.call(store, local.state, payload)\n",[85,2917,2918],{"class":87,"line":366},[85,2919,2920],{"class":116},"      \u002F\u002F })\n",[85,2922,2923],{"class":87,"line":372},[85,2924,2925],{"class":116},"      \u002F\u002F handle 就是 wrappedMutationHandler 函数\n",[85,2927,2928],{"class":87,"line":384},[85,2929,2930],{"class":116},"      \u002F\u002F wrappedMutationHandler 内部就是调用\n",[85,2932,2933],{"class":87,"line":401},[85,2934,2935],{"class":116},"      \u002F\u002F 对于的 mutation 函数\n",[85,2937,2938,2941],{"class":87,"line":409},[85,2939,2940],{"class":98},"      handler",[85,2942,2943],{"class":102},"(payload)\n",[85,2945,2946],{"class":87,"line":421},[85,2947,1984],{"class":102},[85,2949,2950],{"class":87,"line":453},[85,2951,2123],{"class":102},[85,2953,2954],{"class":87,"line":472},[85,2955,2956],{"class":116},"  \u002F\u002F 执行订阅函数\n",[85,2958,2959,2961,2964,2966,2968,2971,2974,2977,2980,2982],{"class":87,"line":484},[85,2960,2873],{"class":150},[85,2962,2963],{"class":102},"._subscribers.",[85,2965,2891],{"class":98},[85,2967,103],{"class":102},[85,2969,2970],{"class":106},"sub",[85,2972,2973],{"class":91}," =>",[85,2975,2976],{"class":98}," sub",[85,2978,2979],{"class":102},"(mutation, ",[85,2981,660],{"class":150},[85,2983,2984],{"class":102},".state))\n",[85,2986,2987],{"class":87,"line":489},[85,2988,229],{"class":102},[502,2990,2992],{"id":2991},"dispatch-解析","dispatch 解析",[15,2994,2995,2996,2998],{},"如果需要异步改变状态，就需要通过 dispatch 的方式去实现。在 dispatch 调用的 ",[22,2997,24],{}," 函数都是重写过的，会找到模块内的 mutation 函数。",[76,3000,3002],{"className":78,"code":3001,"language":80,"meta":81,"style":81},"dispatch(_type, _payload) {\n  \u002F\u002F 检查传入的参数\n  const { type, payload } = unifyObjectStyle(_type, _payload)\n\n  const action = { type, payload }\n  \u002F\u002F 找到对于的 action 函数\n  const entry = this._actions[type]\n  \u002F\u002F 判断是否找到\n  if (!entry) {\n    if (process.env.NODE_ENV !== 'production') {\n      console.error(`[vuex] unknown action type: ${type}`)\n    }\n    return\n  }\n  \u002F\u002F 触发订阅函数\n  this._actionSubscribers.forEach(sub => sub(action, this.state))\n\n  \u002F\u002F 在注册 action 的时候，会将函数返回值\n  \u002F\u002F 处理成 promise，当 promise 全部\n  \u002F\u002F resolve 后，就会执行 Promise.all\n  \u002F\u002F 里的函数\n  return entry.length > 1\n    ? Promise.all(entry.map(handler => handler(payload)))\n    : entry[0](payload)\n}\n",[22,3003,3004,3011,3015,3036,3040,3051,3056,3069,3073,3083,3097,3114,3118,3122,3126,3131,3155,3159,3164,3169,3174,3179,3195,3224,3237],{"__ignoreMap":81},[85,3005,3006,3008],{"class":87,"line":88},[85,3007,904],{"class":98},[85,3009,3010],{"class":102},"(_type, _payload) {\n",[85,3012,3013],{"class":87,"line":113},[85,3014,2713],{"class":116},[85,3016,3017,3019,3021,3023,3025,3027,3029,3031,3033],{"class":87,"line":120},[85,3018,271],{"class":91},[85,3020,901],{"class":102},[85,3022,946],{"class":150},[85,3024,646],{"class":102},[85,3026,951],{"class":150},[85,3028,911],{"class":102},[85,3030,211],{"class":91},[85,3032,2736],{"class":98},[85,3034,3035],{"class":102},"(_type, _payload)\n",[85,3037,3038],{"class":87,"line":141},[85,3039,236],{"emptyLinePlaceholder":235},[85,3041,3042,3044,3047,3049],{"class":87,"line":163},[85,3043,271],{"class":91},[85,3045,3046],{"class":150}," action",[85,3048,277],{"class":91},[85,3050,2774],{"class":102},[85,3052,3053],{"class":87,"line":175},[85,3054,3055],{"class":116},"  \u002F\u002F 找到对于的 action 函数\n",[85,3057,3058,3060,3062,3064,3066],{"class":87,"line":181},[85,3059,271],{"class":91},[85,3061,2786],{"class":150},[85,3063,277],{"class":91},[85,3065,395],{"class":150},[85,3067,3068],{"class":102},"._actions[type]\n",[85,3070,3071],{"class":87,"line":187},[85,3072,2798],{"class":116},[85,3074,3075,3077,3079,3081],{"class":87,"line":193},[85,3076,123],{"class":91},[85,3078,537],{"class":102},[85,3080,559],{"class":91},[85,3082,2809],{"class":102},[85,3084,3085,3087,3089,3091,3093,3095],{"class":87,"line":199},[85,3086,144],{"class":91},[85,3088,147],{"class":102},[85,3090,151],{"class":150},[85,3092,154],{"class":91},[85,3094,158],{"class":157},[85,3096,110],{"class":102},[85,3098,3099,3101,3103,3105,3108,3110,3112],{"class":87,"line":205},[85,3100,166],{"class":102},[85,3102,169],{"class":98},[85,3104,103],{"class":102},[85,3106,3107],{"class":157},"`[vuex] unknown action type: ${",[85,3109,946],{"class":102},[85,3111,2839],{"class":157},[85,3113,627],{"class":102},[85,3115,3116],{"class":87,"line":217},[85,3117,190],{"class":102},[85,3119,3120],{"class":87,"line":226},[85,3121,196],{"class":91},[85,3123,3124],{"class":87,"line":232},[85,3125,202],{"class":102},[85,3127,3128],{"class":87,"line":239},[85,3129,3130],{"class":116},"  \u002F\u002F 触发订阅函数\n",[85,3132,3133,3135,3138,3140,3142,3144,3146,3148,3151,3153],{"class":87,"line":245},[85,3134,2873],{"class":150},[85,3136,3137],{"class":102},"._actionSubscribers.",[85,3139,2891],{"class":98},[85,3141,103],{"class":102},[85,3143,2970],{"class":106},[85,3145,2973],{"class":91},[85,3147,2976],{"class":98},[85,3149,3150],{"class":102},"(action, ",[85,3152,660],{"class":150},[85,3154,2984],{"class":102},[85,3156,3157],{"class":87,"line":262},[85,3158,236],{"emptyLinePlaceholder":235},[85,3160,3161],{"class":87,"line":268},[85,3162,3163],{"class":116},"  \u002F\u002F 在注册 action 的时候，会将函数返回值\n",[85,3165,3166],{"class":87,"line":303},[85,3167,3168],{"class":116},"  \u002F\u002F 处理成 promise，当 promise 全部\n",[85,3170,3171],{"class":87,"line":309},[85,3172,3173],{"class":116},"  \u002F\u002F resolve 后，就会执行 Promise.all\n",[85,3175,3176],{"class":87,"line":325},[85,3177,3178],{"class":116},"  \u002F\u002F 里的函数\n",[85,3180,3181,3184,3187,3189,3192],{"class":87,"line":337},[85,3182,3183],{"class":91},"  return",[85,3185,3186],{"class":102}," entry.",[85,3188,1378],{"class":150},[85,3190,3191],{"class":91}," >",[85,3193,3194],{"class":150}," 1\n",[85,3196,3197,3200,3202,3204,3207,3210,3213,3215,3217,3219,3221],{"class":87,"line":349},[85,3198,3199],{"class":91},"    ?",[85,3201,639],{"class":150},[85,3203,932],{"class":102},[85,3205,3206],{"class":98},"all",[85,3208,3209],{"class":102},"(entry.",[85,3211,3212],{"class":98},"map",[85,3214,103],{"class":102},[85,3216,2903],{"class":106},[85,3218,2973],{"class":91},[85,3220,2184],{"class":98},[85,3222,3223],{"class":102},"(payload)))\n",[85,3225,3226,3229,3232,3234],{"class":87,"line":355},[85,3227,3228],{"class":91},"    :",[85,3230,3231],{"class":102}," entry[",[85,3233,297],{"class":150},[85,3235,3236],{"class":102},"](payload)\n",[85,3238,3239],{"class":87,"line":360},[85,3240,229],{"class":102},[502,3242,3243],{"id":3243},"各种语法糖",[15,3245,3246,3247,3250,3251,3254],{},"在组件中，如果想正常使用 Vuex 的功能，经常需要这样调用 ",[22,3248,3249],{},"this.$store.state.xxx"," 的方式，引来了很多的不便。为此，Vuex 引入了语法糖的功能，让我们可以通过简单的方式来实现上述的功能。以下以 ",[22,3252,3253],{},"mapState"," 为例，其他的几个 map 都是差不多的原理，就不一一解析了。",[76,3256,3258],{"className":78,"code":3257,"language":80,"meta":81,"style":81},"function normalizeNamespace(fn) {\n  return (namespace, map) => {\n    \u002F\u002F 函数作用很简单\n    \u002F\u002F 根据参数生成 namespace\n    if (typeof namespace !== 'string') {\n      map = namespace\n      namespace = ''\n    } else if (namespace.charAt(namespace.length - 1) !== '\u002F') {\n      namespace += '\u002F'\n    }\n    return fn(namespace, map)\n  }\n}\n\u002F\u002F 执行 mapState 就是执行\n\u002F\u002F normalizeNamespace 返回的函数\nexport const mapState = normalizeNamespace((namespace, states) => {\n  const res = {}\n  \u002F\u002F normalizeMap([1, 2, 3]) => [ { key: 1, val: 1 }, { key: 2, val: 2 }, { key: 3, val: 3 } ]\n  \u002F\u002F normalizeMap({a: 1, b: 2, c: 3}) => [ { key: 'a', val: 1 }, { key: 'b', val: 2 }, { key: 'c', val: 3 } ]\n  \u002F\u002F function normalizeMap(map) {\n  \u002F\u002F   return Array.isArray(map)\n  \u002F\u002F     ? map.map(key => ({ key, val: key }))\n  \u002F\u002F     : Object.keys(map).map(key => ({ key, val: map[key] }))\n  \u002F\u002F }\n  \u002F\u002F states 参数可以参入数组或者对象类型\n  normalizeMap(states).forEach(({ key, val }) => {\n    res[key] = function mappedState() {\n      let state = this.$store.state\n      let getters = this.$store.getters\n      if (namespace) {\n        \u002F\u002F 获得对应的模块\n        const module = getModuleByNamespace(this.$store, 'mapState', namespace)\n        if (!module) {\n          return\n        }\n        state = module.context.state\n        getters = module.context.getters\n      }\n      \u002F\u002F 返回 State\n      return typeof val === 'function'\n        ? val.call(this, state, getters)\n        : state[val]\n    }\n    \u002F\u002F mark vuex getter for devtools\n    res[key].vuex = true\n  })\n  return res\n})\n",[22,3259,3260,3273,3292,3297,3302,3319,3329,3339,3371,3381,3385,3395,3399,3403,3408,3413,3442,3453,3458,3463,3468,3473,3478,3483,3488,3493,3520,3534,3549,3563,3571,3576,3602,3615,3620,3625,3637,3649,3654,3659,3673,3690,3698,3702,3707,3716,3720,3727],{"__ignoreMap":81},[85,3261,3262,3264,3267,3269,3271],{"class":87,"line":88},[85,3263,1739],{"class":91},[85,3265,3266],{"class":98}," normalizeNamespace",[85,3268,103],{"class":102},[85,3270,2458],{"class":106},[85,3272,110],{"class":102},[85,3274,3275,3277,3279,3282,3284,3286,3288,3290],{"class":87,"line":113},[85,3276,3183],{"class":91},[85,3278,537],{"class":102},[85,3280,3281],{"class":106},"namespace",[85,3283,646],{"class":102},[85,3285,3212],{"class":106},[85,3287,1520],{"class":102},[85,3289,1523],{"class":91},[85,3291,346],{"class":102},[85,3293,3294],{"class":87,"line":120},[85,3295,3296],{"class":116},"    \u002F\u002F 函数作用很简单\n",[85,3298,3299],{"class":87,"line":141},[85,3300,3301],{"class":116},"    \u002F\u002F 根据参数生成 namespace\n",[85,3303,3304,3306,3308,3310,3312,3314,3317],{"class":87,"line":163},[85,3305,144],{"class":91},[85,3307,537],{"class":102},[85,3309,636],{"class":91},[85,3311,2104],{"class":102},[85,3313,573],{"class":91},[85,3315,3316],{"class":157}," 'string'",[85,3318,110],{"class":102},[85,3320,3321,3324,3326],{"class":87,"line":175},[85,3322,3323],{"class":102},"      map ",[85,3325,211],{"class":91},[85,3327,3328],{"class":102}," namespace\n",[85,3330,3331,3334,3336],{"class":87,"line":181},[85,3332,3333],{"class":102},"      namespace ",[85,3335,211],{"class":91},[85,3337,3338],{"class":157}," ''\n",[85,3340,3341,3343,3345,3347,3350,3353,3356,3358,3360,3362,3364,3366,3369],{"class":87,"line":187},[85,3342,456],{"class":102},[85,3344,343],{"class":91},[85,3346,461],{"class":91},[85,3348,3349],{"class":102}," (namespace.",[85,3351,3352],{"class":98},"charAt",[85,3354,3355],{"class":102},"(namespace.",[85,3357,1378],{"class":150},[85,3359,1475],{"class":91},[85,3361,1478],{"class":150},[85,3363,1520],{"class":102},[85,3365,573],{"class":91},[85,3367,3368],{"class":157}," '\u002F'",[85,3370,110],{"class":102},[85,3372,3373,3375,3378],{"class":87,"line":193},[85,3374,3333],{"class":102},[85,3376,3377],{"class":91},"+=",[85,3379,3380],{"class":157}," '\u002F'\n",[85,3382,3383],{"class":87,"line":199},[85,3384,190],{"class":102},[85,3386,3387,3390,3392],{"class":87,"line":205},[85,3388,3389],{"class":91},"    return",[85,3391,2488],{"class":98},[85,3393,3394],{"class":102},"(namespace, map)\n",[85,3396,3397],{"class":87,"line":217},[85,3398,202],{"class":102},[85,3400,3401],{"class":87,"line":226},[85,3402,229],{"class":102},[85,3404,3405],{"class":87,"line":232},[85,3406,3407],{"class":116},"\u002F\u002F 执行 mapState 就是执行\n",[85,3409,3410],{"class":87,"line":239},[85,3411,3412],{"class":116},"\u002F\u002F normalizeNamespace 返回的函数\n",[85,3414,3415,3417,3420,3423,3425,3427,3429,3431,3433,3436,3438,3440],{"class":87,"line":245},[85,3416,92],{"class":91},[85,3418,3419],{"class":91}," const",[85,3421,3422],{"class":150}," mapState",[85,3424,277],{"class":91},[85,3426,3266],{"class":98},[85,3428,2079],{"class":102},[85,3430,3281],{"class":106},[85,3432,646],{"class":102},[85,3434,3435],{"class":106},"states",[85,3437,1520],{"class":102},[85,3439,1523],{"class":91},[85,3441,346],{"class":102},[85,3443,3444,3446,3449,3451],{"class":87,"line":262},[85,3445,271],{"class":91},[85,3447,3448],{"class":150}," res",[85,3450,277],{"class":91},[85,3452,1703],{"class":102},[85,3454,3455],{"class":87,"line":268},[85,3456,3457],{"class":116},"  \u002F\u002F normalizeMap([1, 2, 3]) => [ { key: 1, val: 1 }, { key: 2, val: 2 }, { key: 3, val: 3 } ]\n",[85,3459,3460],{"class":87,"line":303},[85,3461,3462],{"class":116},"  \u002F\u002F normalizeMap({a: 1, b: 2, c: 3}) => [ { key: 'a', val: 1 }, { key: 'b', val: 2 }, { key: 'c', val: 3 } ]\n",[85,3464,3465],{"class":87,"line":309},[85,3466,3467],{"class":116},"  \u002F\u002F function normalizeMap(map) {\n",[85,3469,3470],{"class":87,"line":325},[85,3471,3472],{"class":116},"  \u002F\u002F   return Array.isArray(map)\n",[85,3474,3475],{"class":87,"line":337},[85,3476,3477],{"class":116},"  \u002F\u002F     ? map.map(key => ({ key, val: key }))\n",[85,3479,3480],{"class":87,"line":349},[85,3481,3482],{"class":116},"  \u002F\u002F     : Object.keys(map).map(key => ({ key, val: map[key] }))\n",[85,3484,3485],{"class":87,"line":355},[85,3486,3487],{"class":116},"  \u002F\u002F }\n",[85,3489,3490],{"class":87,"line":360},[85,3491,3492],{"class":116},"  \u002F\u002F states 参数可以参入数组或者对象类型\n",[85,3494,3495,3498,3501,3503,3506,3508,3510,3513,3516,3518],{"class":87,"line":366},[85,3496,3497],{"class":98},"  normalizeMap",[85,3499,3500],{"class":102},"(states).",[85,3502,2891],{"class":98},[85,3504,3505],{"class":102},"(({ ",[85,3507,1517],{"class":106},[85,3509,646],{"class":102},[85,3511,3512],{"class":106},"val",[85,3514,3515],{"class":102}," }) ",[85,3517,1523],{"class":91},[85,3519,346],{"class":102},[85,3521,3522,3525,3527,3529,3532],{"class":87,"line":372},[85,3523,3524],{"class":102},"    res[key] ",[85,3526,211],{"class":91},[85,3528,95],{"class":91},[85,3530,3531],{"class":98}," mappedState",[85,3533,381],{"class":102},[85,3535,3536,3539,3542,3544,3546],{"class":87,"line":384},[85,3537,3538],{"class":91},"      let",[85,3540,3541],{"class":102}," state ",[85,3543,211],{"class":91},[85,3545,395],{"class":150},[85,3547,3548],{"class":102},".$store.state\n",[85,3550,3551,3553,3556,3558,3560],{"class":87,"line":401},[85,3552,3538],{"class":91},[85,3554,3555],{"class":102}," getters ",[85,3557,211],{"class":91},[85,3559,395],{"class":150},[85,3561,3562],{"class":102},".$store.getters\n",[85,3564,3565,3568],{"class":87,"line":409},[85,3566,3567],{"class":91},"      if",[85,3569,3570],{"class":102}," (namespace) {\n",[85,3572,3573],{"class":87,"line":421},[85,3574,3575],{"class":116},"        \u002F\u002F 获得对应的模块\n",[85,3577,3578,3581,3584,3586,3589,3591,3593,3596,3599],{"class":87,"line":453},[85,3579,3580],{"class":91},"        const",[85,3582,3583],{"class":150}," module",[85,3585,277],{"class":91},[85,3587,3588],{"class":98}," getModuleByNamespace",[85,3590,103],{"class":102},[85,3592,660],{"class":150},[85,3594,3595],{"class":102},".$store, ",[85,3597,3598],{"class":157},"'mapState'",[85,3600,3601],{"class":102},", namespace)\n",[85,3603,3604,3607,3609,3611,3613],{"class":87,"line":472},[85,3605,3606],{"class":91},"        if",[85,3608,537],{"class":102},[85,3610,559],{"class":91},[85,3612,1213],{"class":150},[85,3614,110],{"class":102},[85,3616,3617],{"class":87,"line":484},[85,3618,3619],{"class":91},"          return\n",[85,3621,3622],{"class":87,"line":489},[85,3623,3624],{"class":102},"        }\n",[85,3626,3627,3630,3632,3634],{"class":87,"line":494},[85,3628,3629],{"class":102},"        state ",[85,3631,211],{"class":91},[85,3633,3583],{"class":150},[85,3635,3636],{"class":102},".context.state\n",[85,3638,3639,3642,3644,3646],{"class":87,"line":970},[85,3640,3641],{"class":102},"        getters ",[85,3643,211],{"class":91},[85,3645,3583],{"class":150},[85,3647,3648],{"class":102},".context.getters\n",[85,3650,3651],{"class":87,"line":975},[85,3652,3653],{"class":102},"      }\n",[85,3655,3656],{"class":87,"line":1005},[85,3657,3658],{"class":116},"      \u002F\u002F 返回 State\n",[85,3660,3661,3663,3665,3668,3670],{"class":87,"line":1018},[85,3662,958],{"class":91},[85,3664,567],{"class":91},[85,3666,3667],{"class":102}," val ",[85,3669,135],{"class":91},[85,3671,3672],{"class":157}," 'function'\n",[85,3674,3675,3678,3681,3683,3685,3687],{"class":87,"line":1023},[85,3676,3677],{"class":91},"        ?",[85,3679,3680],{"class":102}," val.",[85,3682,964],{"class":98},[85,3684,103],{"class":102},[85,3686,660],{"class":150},[85,3688,3689],{"class":102},", state, getters)\n",[85,3691,3692,3695],{"class":87,"line":1657},[85,3693,3694],{"class":91},"        :",[85,3696,3697],{"class":102}," state[val]\n",[85,3699,3700],{"class":87,"line":1662},[85,3701,190],{"class":102},[85,3703,3704],{"class":87,"line":1668},[85,3705,3706],{"class":116},"    \u002F\u002F mark vuex getter for devtools\n",[85,3708,3709,3712,3714],{"class":87,"line":1706},[85,3710,3711],{"class":102},"    res[key].vuex ",[85,3713,211],{"class":91},[85,3715,2592],{"class":150},[85,3717,3718],{"class":87,"line":1711},[85,3719,2123],{"class":102},[85,3721,3722,3724],{"class":87,"line":2205},[85,3723,3183],{"class":91},[85,3725,3726],{"class":102}," res\n",[85,3728,3729],{"class":87,"line":2210},[85,3730,1189],{"class":102},[3732,3733,3734],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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":81,"searchDepth":120,"depth":120,"links":3736},[3737,3738],{"id":12,"depth":113,"text":13},{"id":28,"depth":113,"text":29,"children":3739},[3740,3741,3742],{"id":33,"depth":120,"text":34},{"id":499,"depth":120,"text":500},{"id":2682,"depth":120,"text":2683},"source-code","2025-03-08","从单例模式与单向数据流的设计思想入手，跟读 install 函数、store 构造与响应式状态的实现细节。",false,"md",{},"\u002Fblog\u002Fvuex-source-code-analysis",{"title":5,"description":3745},null,"blog\u002Fvuex-source-code-analysis",[3754,3755,3743,3756],"vue","vuex","design-pattern","F5YjIJ1ccLZSxr2znwimwzuY84We6F06DYubzT58Bv4",{"prev":3759,"next":3763},{"path":3760,"title":3761,"description":3762},"\u002Fblog\u002Fvue-router-source-code-analysis","VueRouter 源码深度解析","拆解 hash 与 history 两种路由模式的底层差异，跟读路由注册、匹配与导航守卫的源码实现。",{"path":3764,"title":3765,"description":3766},"\u002Fblog\u002Fwsl2-clash-huorong-troubleshooting","WSL2 + Clash + 火绒 踩坑排查记录","代理开着 WSL2 就断网，关掉又访问不了外网。记录一次从 ARP 拦截日志追到 TUN 模式冲突的完整排查过程，以及重建 Hyper-V 网络栈的正确恢复步骤。",1788337377922]