[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Freactivity\u002Fv2-v3":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Freactivity\u002Fv2-v3":1122,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Freactivity\u002Fv2-v3":1148},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":15,"pinned":16,"draft":16,"body":17,"seo":1118,"stem":1119,"id":1120,"extension":1121},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Freactivity\u002Fv2-v3","Vue 2 与 Vue 3 响应式差异","Vue 2 与 Vue 3 响应式实现的核心差异如下。基础概念见 Vue 基础。","技能小册",[12,13,14],"vue","reactivity","v2-v3","2022-07-06",false,{"type":18,"value":19,"toc":1103},"minimark",[20,24,34,37,42,50,55,61,206,228,306,310,342,396,407,471,475,481,485,496,500,509,622,626,637,707,711,718,740,853,857,981,985,1040,1043,1046,1049,1099],[21,22,8],"h1",{"id":23},"vue-2-与-vue-3-响应式差异",[25,26,27,28,33],"p",{},"Vue 2 与 Vue 3 响应式实现的核心差异如下。基础概念见 ",[29,30,32],"a",{"href":31},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fbasics","Vue 基础","。",[25,35,36],{},"以下是 Vue 2 与 Vue 3 响应式系统的核心差异分析，重点从实现原理、局限性和性能角度进行对比。",[38,39,41],"h2",{"id":40},"一vue-2-响应式原理与局限","一、Vue 2 响应式原理与局限",[25,43,44,45,49],{},"Vue 2 使用 ",[46,47,48],"code",{},"Object.defineProperty"," 对数据对象的属性进行劫持，在组件初始化时递归遍历所有属性，将其转换为 getter\u002Fsetter。",[51,52,54],"h3",{"id":53},"_1-无法检测对象属性的新增删除","1. 无法检测对象属性的新增\u002F删除",[25,56,57,58,60],{},"由于 ",[46,59,48],{}," 必须在初始化时知道所有属性键名，动态添加的属性不会触发更新。",[62,63,68],"pre",{"className":64,"code":65,"language":66,"meta":67,"style":67},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","data() {\n  return { user: { name: 'Alice' } };\n},\nmounted() {\n  this.user.age = 25;     \u002F\u002F ❌ 非响应式，视图不更新\n  delete this.user.name;  \u002F\u002F ❌ 非响应式\n}\n","js","",[46,69,70,87,128,134,144,177,200],{"__ignoreMap":67},[71,72,75,79,83],"span",{"class":73,"line":74},"line",1,[71,76,78],{"class":77},"sGLFI","data",[71,80,82],{"class":81},"su5hD","() ",[71,84,86],{"class":85},"sP7_E","{\n",[71,88,90,94,97,101,104,106,109,111,115,119,122,125],{"class":73,"line":89},2,[71,91,93],{"class":92},"sVHd0","  return",[71,95,96],{"class":85}," {",[71,98,100],{"class":99},"skxfh"," user",[71,102,103],{"class":85},":",[71,105,96],{"class":85},[71,107,108],{"class":99}," name",[71,110,103],{"class":85},[71,112,114],{"class":113},"sjJ54"," '",[71,116,118],{"class":117},"s_sjI","Alice",[71,120,121],{"class":113},"'",[71,123,124],{"class":85}," }",[71,126,127],{"class":85}," };\n",[71,129,131],{"class":73,"line":130},3,[71,132,133],{"class":85},"},\n",[71,135,137,140,142],{"class":73,"line":136},4,[71,138,139],{"class":77},"mounted",[71,141,82],{"class":81},[71,143,86],{"class":85},[71,145,147,151,154,157,159,162,166,170,173],{"class":73,"line":146},5,[71,148,150],{"class":149},"s39Yj","  this",[71,152,153],{"class":85},".",[71,155,156],{"class":81},"user",[71,158,153],{"class":85},[71,160,161],{"class":81},"age",[71,163,165],{"class":164},"smGrS"," =",[71,167,169],{"class":168},"srdBf"," 25",[71,171,172],{"class":85},";",[71,174,176],{"class":175},"sutJx","     \u002F\u002F ❌ 非响应式，视图不更新\n",[71,178,180,183,186,188,190,192,195,197],{"class":73,"line":179},6,[71,181,182],{"class":164},"  delete",[71,184,185],{"class":149}," this",[71,187,153],{"class":85},[71,189,156],{"class":81},[71,191,153],{"class":85},[71,193,194],{"class":81},"name",[71,196,172],{"class":85},[71,198,199],{"class":175},"  \u002F\u002F ❌ 非响应式\n",[71,201,203],{"class":73,"line":202},7,[71,204,205],{"class":85},"}\n",[25,207,208,212,213,216,217,220,221,216,224,227],{},[209,210,211],"strong",{},"补救方案","：",[46,214,215],{},"Vue.set"," \u002F ",[46,218,219],{},"Vue.delete"," 或 ",[46,222,223],{},"this.$set",[46,225,226],{},"this.$delete","，手动通知依赖更新。",[62,229,231],{"className":64,"code":230,"language":66,"meta":67,"style":67},"this.$set(this.user, \"age\", 25); \u002F\u002F ✅ 响应式\nthis.$delete(this.user, \"name\"); \u002F\u002F ✅ 响应式\n",[46,232,233,275],{"__ignoreMap":67},[71,234,235,238,240,243,246,248,250,252,255,258,260,263,265,267,270,272],{"class":73,"line":74},[71,236,237],{"class":149},"this",[71,239,153],{"class":85},[71,241,242],{"class":77},"$set",[71,244,245],{"class":81},"(",[71,247,237],{"class":149},[71,249,153],{"class":85},[71,251,156],{"class":81},[71,253,254],{"class":85},",",[71,256,257],{"class":113}," \"",[71,259,161],{"class":117},[71,261,262],{"class":113},"\"",[71,264,254],{"class":85},[71,266,169],{"class":168},[71,268,269],{"class":81},")",[71,271,172],{"class":85},[71,273,274],{"class":175}," \u002F\u002F ✅ 响应式\n",[71,276,277,279,281,284,286,288,290,292,294,296,298,300,302,304],{"class":73,"line":89},[71,278,237],{"class":149},[71,280,153],{"class":85},[71,282,283],{"class":77},"$delete",[71,285,245],{"class":81},[71,287,237],{"class":149},[71,289,153],{"class":85},[71,291,156],{"class":81},[71,293,254],{"class":85},[71,295,257],{"class":113},[71,297,194],{"class":117},[71,299,262],{"class":113},[71,301,269],{"class":81},[71,303,172],{"class":85},[71,305,274],{"class":175},[51,307,309],{"id":308},"_2-无法直接监听数组索引赋值和-length-修改","2. 无法直接监听数组索引赋值和 length 修改",[25,311,312,314,315,318,319,318,322,318,325,318,328,318,331,318,334,337,338,341],{},[46,313,48],{}," 无法高效拦截数组索引变化，Vue 2 只能拦截修改数组长度的七个方法（",[46,316,317],{},"push",", ",[46,320,321],{},"pop",[46,323,324],{},"shift",[46,326,327],{},"unshift",[46,329,330],{},"splice",[46,332,333],{},"sort",[46,335,336],{},"reverse","），而直接通过索引修改值或修改 ",[46,339,340],{},"length"," 无法触发更新。",[62,343,345],{"className":64,"code":344,"language":66,"meta":67,"style":67},"this.list[0] = newValue; \u002F\u002F ❌ 不触发更新\nthis.list.length = 0; \u002F\u002F ❌ 不触发更新\n",[46,346,347,373],{"__ignoreMap":67},[71,348,349,351,353,356,359,362,365,368,370],{"class":73,"line":74},[71,350,237],{"class":149},[71,352,153],{"class":85},[71,354,355],{"class":81},"list[",[71,357,358],{"class":168},"0",[71,360,361],{"class":81},"] ",[71,363,364],{"class":164},"=",[71,366,367],{"class":81}," newValue",[71,369,172],{"class":85},[71,371,372],{"class":175}," \u002F\u002F ❌ 不触发更新\n",[71,374,375,377,379,382,384,387,389,392,394],{"class":73,"line":89},[71,376,237],{"class":149},[71,378,153],{"class":85},[71,380,381],{"class":81},"list",[71,383,153],{"class":85},[71,385,340],{"class":386},"s_hVV",[71,388,165],{"class":164},[71,390,391],{"class":168}," 0",[71,393,172],{"class":85},[71,395,372],{"class":175},[25,397,398,400,401,403,404,406],{},[209,399,211],{},"：使用 ",[46,402,242],{}," 或数组变异方法（如 ",[46,405,330],{},"）。",[62,408,410],{"className":64,"code":409,"language":66,"meta":67,"style":67},"this.$set(this.list, 0, newValue); \u002F\u002F ✅\nthis.list.splice(0, 1, newValue); \u002F\u002F ✅\n",[46,411,412,442],{"__ignoreMap":67},[71,413,414,416,418,420,422,424,426,428,430,432,434,437,439],{"class":73,"line":74},[71,415,237],{"class":149},[71,417,153],{"class":85},[71,419,242],{"class":77},[71,421,245],{"class":81},[71,423,237],{"class":149},[71,425,153],{"class":85},[71,427,381],{"class":81},[71,429,254],{"class":85},[71,431,391],{"class":168},[71,433,254],{"class":85},[71,435,436],{"class":81}," newValue)",[71,438,172],{"class":85},[71,440,441],{"class":175}," \u002F\u002F ✅\n",[71,443,444,446,448,450,452,454,456,458,460,463,465,467,469],{"class":73,"line":89},[71,445,237],{"class":149},[71,447,153],{"class":85},[71,449,381],{"class":81},[71,451,153],{"class":85},[71,453,330],{"class":77},[71,455,245],{"class":81},[71,457,358],{"class":168},[71,459,254],{"class":85},[71,461,462],{"class":168}," 1",[71,464,254],{"class":85},[71,466,436],{"class":81},[71,468,172],{"class":85},[71,470,441],{"class":175},[51,472,474],{"id":473},"_3-递归初始化的性能开销","3. 递归初始化的性能开销",[25,476,477,478,480],{},"Vue 2 在初始化 ",[46,479,78],{}," 时会深度遍历所有嵌套对象，为每个属性添加 getter\u002Fsetter。如果数据结构庞大或嵌套层级深，会消耗较多初始渲染时间，并对后续性能产生一定内存压力（每个属性都产生闭包依赖）。",[38,482,484],{"id":483},"二vue-3-响应式原理与优势","二、Vue 3 响应式原理与优势",[25,486,487,488,491,492,495],{},"Vue 3 使用 ES6 的 ",[46,489,490],{},"Proxy"," + ",[46,493,494],{},"Reflect"," 实现响应式，从根本上解决了 Vue 2 的诸多局限。",[51,497,499],{"id":498},"_1-天然支持属性新增与删除","1. 天然支持属性新增与删除",[25,501,502,504,505,508],{},[46,503,490],{}," 可以拦截对对象的所有操作，包括属性读取、赋值、删除、",[46,506,507],{},"in"," 运算符等。因此动态添加或删除属性会自动触发更新，无需手动 API。",[62,510,512],{"className":64,"code":511,"language":66,"meta":67,"style":67},"import { reactive } from \"vue\";\nconst state = reactive({ user: { name: \"Alice\" } });\nstate.user.age = 25; \u002F\u002F ✅ 响应式，视图更新\ndelete state.user.name; \u002F\u002F ✅ 响应式\n",[46,513,514,538,580,603],{"__ignoreMap":67},[71,515,516,519,521,524,526,529,531,533,535],{"class":73,"line":74},[71,517,518],{"class":92},"import",[71,520,96],{"class":85},[71,522,523],{"class":81}," reactive",[71,525,124],{"class":85},[71,527,528],{"class":92}," from",[71,530,257],{"class":113},[71,532,12],{"class":117},[71,534,262],{"class":113},[71,536,537],{"class":85},";\n",[71,539,540,544,547,549,551,553,556,558,560,562,564,566,568,570,572,574,576,578],{"class":73,"line":89},[71,541,543],{"class":542},"sbsja","const",[71,545,546],{"class":386}," state",[71,548,165],{"class":164},[71,550,523],{"class":77},[71,552,245],{"class":81},[71,554,555],{"class":85},"{",[71,557,100],{"class":99},[71,559,103],{"class":85},[71,561,96],{"class":85},[71,563,108],{"class":99},[71,565,103],{"class":85},[71,567,257],{"class":113},[71,569,118],{"class":117},[71,571,262],{"class":113},[71,573,124],{"class":85},[71,575,124],{"class":85},[71,577,269],{"class":81},[71,579,537],{"class":85},[71,581,582,585,587,589,591,594,596,598,600],{"class":73,"line":130},[71,583,584],{"class":81},"state",[71,586,153],{"class":85},[71,588,156],{"class":81},[71,590,153],{"class":85},[71,592,593],{"class":81},"age ",[71,595,364],{"class":164},[71,597,169],{"class":168},[71,599,172],{"class":85},[71,601,602],{"class":175}," \u002F\u002F ✅ 响应式，视图更新\n",[71,604,605,608,610,612,614,616,618,620],{"class":73,"line":136},[71,606,607],{"class":164},"delete",[71,609,546],{"class":81},[71,611,153],{"class":85},[71,613,156],{"class":81},[71,615,153],{"class":85},[71,617,194],{"class":81},[71,619,172],{"class":85},[71,621,274],{"class":175},[51,623,625],{"id":624},"_2-完美支持数组操作","2. 完美支持数组操作",[25,627,628,630,631,633,634,636],{},[46,629,490],{}," 能拦截索引赋值和 ",[46,632,340],{}," 修改，因此直接通过索引修改数组项或修改 ",[46,635,340],{}," 都可以触发更新，也无需对数组方法进行额外包装。",[62,638,640],{"className":64,"code":639,"language":66,"meta":67,"style":67},"const list = reactive([1, 2, 3]);\nlist[0] = 100; \u002F\u002F ✅ 响应式\nlist.length = 0; \u002F\u002F ✅ 响应式\n",[46,641,642,674,691],{"__ignoreMap":67},[71,643,644,646,649,651,653,656,659,661,664,666,669,672],{"class":73,"line":74},[71,645,543],{"class":542},[71,647,648],{"class":386}," list",[71,650,165],{"class":164},[71,652,523],{"class":77},[71,654,655],{"class":81},"([",[71,657,658],{"class":168},"1",[71,660,254],{"class":85},[71,662,663],{"class":168}," 2",[71,665,254],{"class":85},[71,667,668],{"class":168}," 3",[71,670,671],{"class":81},"])",[71,673,537],{"class":85},[71,675,676,678,680,682,684,687,689],{"class":73,"line":89},[71,677,355],{"class":81},[71,679,358],{"class":168},[71,681,361],{"class":81},[71,683,364],{"class":164},[71,685,686],{"class":168}," 100",[71,688,172],{"class":85},[71,690,274],{"class":175},[71,692,693,695,697,699,701,703,705],{"class":73,"line":130},[71,694,381],{"class":81},[71,696,153],{"class":85},[71,698,340],{"class":386},[71,700,165],{"class":164},[71,702,391],{"class":168},[71,704,172],{"class":85},[71,706,274],{"class":175},[51,708,710],{"id":709},"_3-懒递归代理lazy-reactivity","3. 懒递归代理（Lazy Reactivity）",[25,712,713,714,717],{},"Vue 3 的响应式是",[209,715,716],{},"惰性","的：当访问一个嵌套对象时，才会将该对象转换为响应式代理（Proxy），而不是初始化时就递归所有属性。这带来了明显的性能提升：",[719,720,721,728,734],"ul",{},[722,723,724,727],"li",{},[209,725,726],{},"初始渲染更快","：仅对最外层对象创建 Proxy，深层属性只在被读取时才代理。",[722,729,730,733],{},[209,731,732],{},"内存占用更少","：减少了不必要的 getter\u002Fsetter 闭包。",[722,735,736,739],{},[209,737,738],{},"适合大型数据结构","：例如树形数据、深度嵌套配置等。",[62,741,743],{"className":64,"code":742,"language":66,"meta":67,"style":67},"const state = reactive({\n  level1: {\n    level2: {\n      value: 42,\n    },\n  },\n});\n\u002F\u002F 此时只有 level1 是响应式代理，level2 尚未被代理\nconsole.log(state.level1.level2.value);\n\u002F\u002F 当访问 level2 时，Vue 3 会将其也转换为响应式代理\n",[46,744,745,759,769,778,791,796,801,810,816,847],{"__ignoreMap":67},[71,746,747,749,751,753,755,757],{"class":73,"line":74},[71,748,543],{"class":542},[71,750,546],{"class":386},[71,752,165],{"class":164},[71,754,523],{"class":77},[71,756,245],{"class":81},[71,758,86],{"class":85},[71,760,761,764,766],{"class":73,"line":89},[71,762,763],{"class":99},"  level1",[71,765,103],{"class":85},[71,767,768],{"class":85}," {\n",[71,770,771,774,776],{"class":73,"line":130},[71,772,773],{"class":99},"    level2",[71,775,103],{"class":85},[71,777,768],{"class":85},[71,779,780,783,785,788],{"class":73,"line":136},[71,781,782],{"class":99},"      value",[71,784,103],{"class":85},[71,786,787],{"class":168}," 42",[71,789,790],{"class":85},",\n",[71,792,793],{"class":73,"line":146},[71,794,795],{"class":85},"    },\n",[71,797,798],{"class":73,"line":179},[71,799,800],{"class":85},"  },\n",[71,802,803,806,808],{"class":73,"line":202},[71,804,805],{"class":85},"}",[71,807,269],{"class":81},[71,809,537],{"class":85},[71,811,813],{"class":73,"line":812},8,[71,814,815],{"class":175},"\u002F\u002F 此时只有 level1 是响应式代理，level2 尚未被代理\n",[71,817,819,822,824,827,830,832,835,837,840,842,845],{"class":73,"line":818},9,[71,820,821],{"class":81},"console",[71,823,153],{"class":85},[71,825,826],{"class":77},"log",[71,828,829],{"class":81},"(state",[71,831,153],{"class":85},[71,833,834],{"class":81},"level1",[71,836,153],{"class":85},[71,838,839],{"class":81},"level2",[71,841,153],{"class":85},[71,843,844],{"class":81},"value)",[71,846,537],{"class":85},[71,848,850],{"class":73,"line":849},10,[71,851,852],{"class":175},"\u002F\u002F 当访问 level2 时，Vue 3 会将其也转换为响应式代理\n",[38,854,856],{"id":855},"三总结对比","三、总结对比",[858,859,860,882],"table",{},[861,862,863],"thead",{},[864,865,866,870,875],"tr",{},[867,868,869],"th",{},"特性",[867,871,872,873,269],{},"Vue 2 (",[46,874,48],{},[867,876,877,878,491,880,269],{},"Vue 3 (",[46,879,490],{},[46,881,494],{},[883,884,885,903,917,929,942,955,968],"tbody",{},[864,886,887,893,900],{},[888,889,890],"td",{},[209,891,892],{},"对象属性新增\u002F删除",[888,894,895,896,216,898],{},"不支持，需 ",[46,897,215],{},[46,899,607],{},[888,901,902],{},"天然支持",[864,904,905,910,915],{},[888,906,907],{},[209,908,909],{},"数组索引赋值",[888,911,895,912,914],{},[46,913,242],{}," 或变异方法",[888,916,902],{},[864,918,919,924,927],{},[888,920,921],{},[209,922,923],{},"修改数组 length",[888,925,926],{},"不支持",[888,928,902],{},[864,930,931,936,939],{},[888,932,933],{},[209,934,935],{},"初始化性能",[888,937,938],{},"递归遍历所有属性，深度越大开销越大",[888,940,941],{},"懒递归，按需代理，性能更好",[864,943,944,949,952],{},[888,945,946],{},[209,947,948],{},"代理粒度",[888,950,951],{},"每个属性单独 getter\u002Fsetter，占用内存较高",[888,953,954],{},"每个对象一个 Proxy，内存效率更高",[864,956,957,962,965],{},[888,958,959],{},[209,960,961],{},"兼容性",[888,963,964],{},"支持 IE9+（需 polyfill）",[888,966,967],{},"不支持 IE（Proxy 无法完全 polyfill）",[864,969,970,975,978],{},[888,971,972],{},[209,973,974],{},"TypeScript 支持",[888,976,977],{},"有限，需额外类型声明",[888,979,980],{},"原生支持，类型推导更准确",[38,982,984],{"id":983},"四注意事项","四、注意事项",[719,986,987,1010,1023],{},[722,988,989,212,1000,1002,1003,1006,1007,1009],{},[209,990,991,992,995,996,999],{},"Vue 3 中 ",[46,993,994],{},"ref"," 与 ",[46,997,998],{},"reactive"," 的区别",[46,1001,994],{}," 用于基本类型，通过 ",[46,1004,1005],{},".value"," 访问；",[46,1008,998],{}," 用于对象\u002F数组，基于 Proxy。",[722,1011,1012,1015,1016,1018,1019,1022],{},[209,1013,1014],{},"解构丢失响应性","：在 Vue 3 中直接解构 ",[46,1017,998],{}," 对象的属性会丢失响应式，需使用 ",[46,1020,1021],{},"toRefs"," 包裹。",[722,1024,1025,1028,1029,1031,1032,1035,1036,1039],{},[209,1026,1027],{},"Proxy 无法代理原始值","：因此 Vue 3 仍需要 ",[46,1030,994],{}," 来处理 ",[46,1033,1034],{},"number","、",[46,1037,1038],{},"string"," 等类型。",[25,1041,1042],{},"总体而言，Vue 3 的响应式系统更强大、更直观、性能更优，是现代 Vue 应用的首选。",[38,1044,1045],{"id":1045},"参考文献",[25,1047,1048],{},"以下链接在编写时均可正常访问：",[858,1050,1051,1061],{},[861,1052,1053],{},[864,1054,1055,1058],{},[867,1056,1057],{},"资料",[867,1059,1060],{},"说明",[883,1062,1063,1076,1088],{},[864,1064,1065,1073],{},[888,1066,1067],{},[29,1068,1072],{"href":1069,"rel":1070},"https:\u002F\u002Fcn.vuejs.org\u002Fguide\u002Fextras\u002Freactivity-in-depth.html",[1071],"nofollow","Vue 3：深入响应式",[888,1074,1075],{},"官方深度说明",[864,1077,1078,1085],{},[888,1079,1080],{},[29,1081,1084],{"href":1082,"rel":1083},"https:\u002F\u002Fv2.cn.vuejs.org\u002Fv2\u002Fguide\u002Freactivity.html",[1071],"Vue 2：响应式原理",[888,1086,1087],{},"Vue 2 文档（归档）",[864,1089,1090,1097],{},[888,1091,1092],{},[29,1093,1096],{"href":1094,"rel":1095},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FProxy",[1071],"MDN：Proxy",[888,1098,490],{},[1100,1101,1102],"style",{},"html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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);}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":67,"searchDepth":89,"depth":89,"links":1104},[1105,1110,1115,1116,1117],{"id":40,"depth":89,"text":41,"children":1106},[1107,1108,1109],{"id":53,"depth":130,"text":54},{"id":308,"depth":130,"text":309},{"id":473,"depth":130,"text":474},{"id":483,"depth":89,"text":484,"children":1111},[1112,1113,1114],{"id":498,"depth":130,"text":499},{"id":624,"depth":130,"text":625},{"id":709,"depth":130,"text":710},{"id":855,"depth":89,"text":856},{"id":983,"depth":89,"text":984},{"id":1045,"depth":89,"text":1045},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fframe\u002FVue\u002Freactivity\u002Fv2-v3","knowledge\u002Fknowledge\u002Fbooklet\u002Fframe\u002FVue\u002Freactivity\u002Fv2-v3.md","md",{"items":1123},[1124,1128,1132,1136,1140,1144],{"path":1125,"title":1126,"description":1127,"category":10,"score":818},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Freactivity\u002Ftrack","依赖收集与派发更新机制","说明 Vue 3 中 track \u002F trigger 与 targetMap 的工作方式。前置：v2-v3 差异。",{"path":1129,"title":1130,"description":1131,"category":10,"score":818},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Freactivity\u002Fproxy","响应式进阶","toRefs、shallowRef、readonly、customRef 等 API 的适用场景与注意点。前置：依赖收集。",{"path":1133,"title":1134,"description":1135,"category":10,"score":136},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fperformance\u002Fassets","资源优化","图片懒加载、按需引入与 Web Vitals 监控。见 HTML 图片、CSS 字体优化。",{"path":1137,"title":1138,"description":1139,"category":10,"score":136},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fstatus","状态管理：Pinia 与 Vuex","Pinia 是 Vue 官方推荐的状态管理库（Vue 3 新项目默认选型）。Vuex 4 仍可与 Vue 3 配合，用于维护旧项目。见 Vue 基础。",{"path":1141,"title":1142,"description":1143,"category":10,"score":136},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fecology","Vue 生态关键库深度集成","VueUse、Vite 与 Nuxt 是 Vue 3 生态中常用的效率与工程化方案。概览见 Vue 基础。",{"path":1145,"title":1146,"description":1147,"category":10,"score":136},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Ftest","测试策略","Vue 应用常用 Vitest + @vue\u002Ftest-utils 做单元\u002F组件测试，Playwright 或 Cypress 做 E2E。见 Vue 基础。",{"series":1149,"title":13,"items":1150,"index":89,"prev":1156,"next":1157},"booklet\u002Fframe\u002Fvue\u002Freactivity",[1151,1153,1155],{"path":1129,"title":1130,"date":1152,"pinned":16},"2023-03-21",{"path":1125,"title":1126,"date":1154,"pinned":16},"2025-01-13",{"path":7,"title":8,"date":15,"pinned":16},{"path":1125,"title":1126,"date":1154,"pinned":16},null]