[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fbasics":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fbasics":2026,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fbasics":2047},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":13,"pinned":14,"draft":14,"body":15,"seo":2022,"stem":2023,"id":2024,"extension":2025},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fbasics","Vue 基础","Vue 是用于构建用户界面的渐进式 JavaScript 框架。当前主线版本为 Vue 3（2020 年发布），采用 组合式 API 与基于 Proxy 的响应式系统。前置知识：JavaScript 基础、HTML、CSS。","技能小册",[12],"vue","2021-07-29",false,{"type":16,"value":17,"toc":2007},"minimark",[18,22,62,67,166,179,183,189,439,482,485,563,568,572,588,616,620,623,987,1047,1050,1196,1210,1214,1288,1453,1456,1505,1629,1633,1704,1711,1714,1796,1799,1843,1846,1948,1951,1954,2004],[19,20,8],"h1",{"id":21},"vue-基础",[23,24,25,32,33,37,38,42,43,47,48,52,53,52,57,61],"p",{},[26,27,31],"a",{"href":28,"rel":29},"https:\u002F\u002Fvuejs.org\u002F",[30],"nofollow","Vue"," 是用于构建用户界面的渐进式 JavaScript 框架。当前主线版本为 ",[34,35,36],"strong",{},"Vue 3","（2020 年发布），采用 ",[26,39,41],{"href":40},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fdesign","组合式 API"," 与基于 ",[44,45,46],"code",{},"Proxy"," 的响应式系统。前置知识：",[26,49,51],{"href":50},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fjs\u002Fbasics","JavaScript 基础","、",[26,54,56],{"href":55},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fhtml\u002Finfo","HTML",[26,58,60],{"href":59},"\u002Fknowledge\u002Fbooklet\u002Fweb\u002Fcss\u002Fflex","CSS","。",[63,64,66],"h2",{"id":65},"vue-2-与-vue-3","Vue 2 与 Vue 3",[68,69,70,84],"table",{},[71,72,73],"thead",{},[74,75,76,79,82],"tr",{},[77,78],"th",{},[77,80,81],{},"Vue 2",[77,83,36],{},[85,86,87,107,121,139,153],"tbody",{},[74,88,89,93,98],{},[90,91,92],"td",{},"响应式",[90,94,95],{},[44,96,97],{},"Object.defineProperty",[90,99,100,102,103,106],{},[44,101,46],{},"（见 ",[26,104,92],{"href":105},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Freactivity\u002Fv2-v3","）",[74,108,109,112,115],{},[90,110,111],{},"推荐 API",[90,113,114],{},"选项式 API（仍支持）",[90,116,117,118],{},"组合式 API + ",[44,119,120],{},"\u003Cscript setup>",[74,122,123,126,129],{},[90,124,125],{},"构建",[90,127,128],{},"Vue CLI \u002F Webpack 常见",[90,130,131,134,135,138],{},[34,132,133],{},"Vite"," + ",[44,136,137],{},"@vitejs\u002Fplugin-vue"," 常见",[74,140,141,144,147],{},[90,142,143],{},"状态",[90,145,146],{},"Vuex 3\u002F4",[90,148,149,152],{},[34,150,151],{},"Pinia","（官方推荐）",[74,154,155,158,161],{},[90,156,157],{},"路由",[90,159,160],{},"Vue Router 3",[90,162,163],{},[34,164,165],{},"Vue Router 4",[23,167,168,169,172,173,178],{},"新项目应使用 ",[34,170,171],{},"Vue 3 + Vite + Pinia + Vue Router 4","。维护 Vue 2 项目须注意官方已结束对 Vue 2 的功能更新（仅安全相关维护期已结束，以 ",[26,174,177],{"href":175,"rel":176},"https:\u002F\u002Fv2.vuejs.org\u002Feol\u002F",[30],"Vue 2 EOL 公告"," 为准）。",[63,180,182],{"id":181},"单文件组件sfc","单文件组件（SFC）",[23,184,185,188],{},[44,186,187],{},".vue"," 文件将模板、逻辑、样式聚合：",[190,191,195],"pre",{"className":192,"code":193,"language":12,"meta":194,"style":194},"language-vue shiki shiki-themes material-theme-lighter github-light github-dark","\u003Cscript setup lang=\"ts\">\nimport { ref } from \"vue\";\n\nconst count = ref(0);\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n    \u003Cbutton type=\"button\" @click=\"count++\">{{ count }}\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003Cstyle scoped>\nbutton {\n    font-size: 1rem;\n}\n\u003C\u002Fstyle>\n","",[44,196,197,233,263,270,300,310,315,325,369,378,383,396,405,424,430],{"__ignoreMap":194},[198,199,202,206,210,214,217,220,224,228,230],"span",{"class":200,"line":201},"line",1,[198,203,205],{"class":204},"sP7_E","\u003C",[198,207,209],{"class":208},"sQzsp","script",[198,211,213],{"class":212},"s9AJx"," setup",[198,215,216],{"class":212}," lang",[198,218,219],{"class":204},"=",[198,221,223],{"class":222},"sjJ54","\"",[198,225,227],{"class":226},"s_sjI","ts",[198,229,223],{"class":222},[198,231,232],{"class":204},">\n",[198,234,236,240,243,247,250,253,256,258,260],{"class":200,"line":235},2,[198,237,239],{"class":238},"sVHd0","import",[198,241,242],{"class":204}," {",[198,244,246],{"class":245},"su5hD"," ref",[198,248,249],{"class":204}," }",[198,251,252],{"class":238}," from",[198,254,255],{"class":222}," \"",[198,257,12],{"class":226},[198,259,223],{"class":222},[198,261,262],{"class":204},";\n",[198,264,266],{"class":200,"line":265},3,[198,267,269],{"emptyLinePlaceholder":268},true,"\n",[198,271,273,277,281,285,288,291,295,298],{"class":200,"line":272},4,[198,274,276],{"class":275},"sbsja","const",[198,278,280],{"class":279},"s_hVV"," count",[198,282,284],{"class":283},"smGrS"," =",[198,286,246],{"class":287},"sGLFI",[198,289,290],{"class":245},"(",[198,292,294],{"class":293},"srdBf","0",[198,296,297],{"class":245},")",[198,299,262],{"class":204},[198,301,303,306,308],{"class":200,"line":302},5,[198,304,305],{"class":204},"\u003C\u002F",[198,307,209],{"class":208},[198,309,232],{"class":204},[198,311,313],{"class":200,"line":312},6,[198,314,269],{"emptyLinePlaceholder":268},[198,316,318,320,323],{"class":200,"line":317},7,[198,319,205],{"class":204},[198,321,322],{"class":208},"template",[198,324,232],{"class":204},[198,326,328,331,334,337,339,341,343,345,348,350,352,355,357,360,363,365,367],{"class":200,"line":327},8,[198,329,330],{"class":204},"    \u003C",[198,332,333],{"class":208},"button",[198,335,336],{"class":212}," type",[198,338,219],{"class":204},[198,340,223],{"class":222},[198,342,333],{"class":226},[198,344,223],{"class":222},[198,346,347],{"class":212}," @click",[198,349,219],{"class":204},[198,351,223],{"class":222},[198,353,354],{"class":226},"count++",[198,356,223],{"class":222},[198,358,359],{"class":204},">",[198,361,362],{"class":245},"{{ count }}",[198,364,305],{"class":204},[198,366,333],{"class":208},[198,368,232],{"class":204},[198,370,372,374,376],{"class":200,"line":371},9,[198,373,305],{"class":204},[198,375,322],{"class":208},[198,377,232],{"class":204},[198,379,381],{"class":200,"line":380},10,[198,382,269],{"emptyLinePlaceholder":268},[198,384,386,388,391,394],{"class":200,"line":385},11,[198,387,205],{"class":204},[198,389,390],{"class":208},"style",[198,392,393],{"class":212}," scoped",[198,395,232],{"class":204},[198,397,399,402],{"class":200,"line":398},12,[198,400,333],{"class":401},"s83vy",[198,403,404],{"class":204}," {\n",[198,406,408,412,415,418,422],{"class":200,"line":407},13,[198,409,411],{"class":410},"soE4H","    font-size",[198,413,414],{"class":204},":",[198,416,417],{"class":293}," 1",[198,419,421],{"class":420},"sw1J6","rem",[198,423,262],{"class":204},[198,425,427],{"class":200,"line":426},14,[198,428,429],{"class":204},"}\n",[198,431,433,435,437],{"class":200,"line":432},15,[198,434,305],{"class":204},[198,436,390],{"class":208},[198,438,232],{"class":204},[68,440,441,451],{},[71,442,443],{},[74,444,445,448],{},[77,446,447],{},"块",[77,449,450],{},"作用",[85,452,453,462,472],{},[74,454,455,459],{},[90,456,457],{},[44,458,120],{},[90,460,461],{},"组合式逻辑；顶层绑定自动暴露给模板",[74,463,464,469],{},[90,465,466],{},[44,467,468],{},"\u003Ctemplate>",[90,470,471],{},"声明式 DOM 结构",[74,473,474,479],{},[90,475,476],{},[44,477,478],{},"\u003Cstyle scoped>",[90,480,481],{},"仅作用于当前组件的样式（编译时加属性选择器）",[63,483,484],{"id":484},"应用入口",[190,486,490],{"className":487,"code":488,"language":489,"meta":194,"style":194},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","import { createApp } from \"vue\";\nimport App from \".\u002FApp.vue\";\n\ncreateApp(App).mount(\"#app\");\n","js",[44,491,492,513,532,536],{"__ignoreMap":194},[198,493,494,496,498,501,503,505,507,509,511],{"class":200,"line":201},[198,495,239],{"class":238},[198,497,242],{"class":204},[198,499,500],{"class":245}," createApp",[198,502,249],{"class":204},[198,504,252],{"class":238},[198,506,255],{"class":222},[198,508,12],{"class":226},[198,510,223],{"class":222},[198,512,262],{"class":204},[198,514,515,517,520,523,525,528,530],{"class":200,"line":235},[198,516,239],{"class":238},[198,518,519],{"class":245}," App ",[198,521,522],{"class":238},"from",[198,524,255],{"class":222},[198,526,527],{"class":226},".\u002FApp.vue",[198,529,223],{"class":222},[198,531,262],{"class":204},[198,533,534],{"class":200,"line":265},[198,535,269],{"emptyLinePlaceholder":268},[198,537,538,541,544,547,550,552,554,557,559,561],{"class":200,"line":272},[198,539,540],{"class":287},"createApp",[198,542,543],{"class":245},"(App)",[198,545,546],{"class":204},".",[198,548,549],{"class":287},"mount",[198,551,290],{"class":245},[198,553,223],{"class":222},[198,555,556],{"class":226},"#app",[198,558,223],{"class":222},[198,560,297],{"class":245},[198,562,262],{"class":204},[23,564,565,567],{},[44,566,540],{}," 返回应用实例，可链式注册插件（Router、Pinia）、全局组件与指令。",[63,569,571],{"id":570},"两种组件-api-风格","两种组件 API 风格",[23,573,574,577,578,52,581,52,584,587],{},[34,575,576],{},"选项式 API","（Options API）：",[44,579,580],{},"data",[44,582,583],{},"methods",[44,585,586],{},"computed"," 等选项，适合简单组件或迁移旧代码。",[23,589,590,592,593,596,597,599,600,52,603,52,605,608,609,612,613,61],{},[34,591,41],{},"（Composition API）：在 ",[44,594,595],{},"setup"," 或 ",[44,598,120],{}," 中使用 ",[44,601,602],{},"ref",[44,604,586],{},[44,606,607],{},"watch"," 等，按",[34,610,611],{},"功能","组织逻辑，便于复用（Composables）。详见 ",[26,614,615],{"href":40},"组合式 API 与设计模式",[63,617,619],{"id":618},"响应式基础-api","响应式基础 API",[23,621,622],{},"组合式 API 最常用的四个函数：",[190,624,626],{"className":192,"code":625,"language":12,"meta":194,"style":194},"\u003Cscript setup lang=\"ts\">\nimport { ref, reactive, computed, watch, watchEffect } from \"vue\";\n\n\u002F\u002F ref：包装基本类型或任意值，读写需要 .value（模板中自动解包）\nconst count = ref(0);\n\n\u002F\u002F reactive：包装对象\u002F数组，返回 Proxy，直接读写属性\nconst state = reactive({ list: [1, 2, 3], keyword: \"\" });\n\n\u002F\u002F computed：派生只读值，依赖变化时自动重新计算并缓存\nconst doubled = computed(() => count.value * 2);\n\n\u002F\u002F watch：显式监听某个响应式源，可拿到旧值\u002F新值，适合处理副作用\nwatch(count, (newVal, oldVal) => {\n    console.log(`count: ${oldVal} -> ${newVal}`);\n});\n\n\u002F\u002F watchEffect：立即执行一次，并自动追踪函数内用到的所有响应式依赖\nwatchEffect(() => {\n    console.log(\"keyword changed:\", state.keyword);\n});\n\u003C\u002Fscript>\n",[44,627,628,648,689,693,699,717,721,726,783,787,792,827,831,836,863,904,913,918,924,938,969,978],{"__ignoreMap":194},[198,629,630,632,634,636,638,640,642,644,646],{"class":200,"line":201},[198,631,205],{"class":204},[198,633,209],{"class":208},[198,635,213],{"class":212},[198,637,216],{"class":212},[198,639,219],{"class":204},[198,641,223],{"class":222},[198,643,227],{"class":226},[198,645,223],{"class":222},[198,647,232],{"class":204},[198,649,650,652,654,656,659,662,664,667,669,672,674,677,679,681,683,685,687],{"class":200,"line":235},[198,651,239],{"class":238},[198,653,242],{"class":204},[198,655,246],{"class":245},[198,657,658],{"class":204},",",[198,660,661],{"class":245}," reactive",[198,663,658],{"class":204},[198,665,666],{"class":245}," computed",[198,668,658],{"class":204},[198,670,671],{"class":245}," watch",[198,673,658],{"class":204},[198,675,676],{"class":245}," watchEffect",[198,678,249],{"class":204},[198,680,252],{"class":238},[198,682,255],{"class":222},[198,684,12],{"class":226},[198,686,223],{"class":222},[198,688,262],{"class":204},[198,690,691],{"class":200,"line":265},[198,692,269],{"emptyLinePlaceholder":268},[198,694,695],{"class":200,"line":272},[198,696,698],{"class":697},"sutJx","\u002F\u002F ref：包装基本类型或任意值，读写需要 .value（模板中自动解包）\n",[198,700,701,703,705,707,709,711,713,715],{"class":200,"line":302},[198,702,276],{"class":275},[198,704,280],{"class":279},[198,706,284],{"class":283},[198,708,246],{"class":287},[198,710,290],{"class":245},[198,712,294],{"class":293},[198,714,297],{"class":245},[198,716,262],{"class":204},[198,718,719],{"class":200,"line":312},[198,720,269],{"emptyLinePlaceholder":268},[198,722,723],{"class":200,"line":317},[198,724,725],{"class":697},"\u002F\u002F reactive：包装对象\u002F数组，返回 Proxy，直接读写属性\n",[198,727,728,730,733,735,737,739,742,746,748,751,754,756,759,761,764,767,769,772,774,777,779,781],{"class":200,"line":327},[198,729,276],{"class":275},[198,731,732],{"class":279}," state",[198,734,284],{"class":283},[198,736,661],{"class":287},[198,738,290],{"class":245},[198,740,741],{"class":204},"{",[198,743,745],{"class":744},"skxfh"," list",[198,747,414],{"class":204},[198,749,750],{"class":245}," [",[198,752,753],{"class":293},"1",[198,755,658],{"class":204},[198,757,758],{"class":293}," 2",[198,760,658],{"class":204},[198,762,763],{"class":293}," 3",[198,765,766],{"class":245},"]",[198,768,658],{"class":204},[198,770,771],{"class":744}," keyword",[198,773,414],{"class":204},[198,775,776],{"class":222}," \"\"",[198,778,249],{"class":204},[198,780,297],{"class":245},[198,782,262],{"class":204},[198,784,785],{"class":200,"line":371},[198,786,269],{"emptyLinePlaceholder":268},[198,788,789],{"class":200,"line":380},[198,790,791],{"class":697},"\u002F\u002F computed：派生只读值，依赖变化时自动重新计算并缓存\n",[198,793,794,796,799,801,803,805,808,811,813,815,818,821,823,825],{"class":200,"line":385},[198,795,276],{"class":275},[198,797,798],{"class":279}," doubled",[198,800,284],{"class":283},[198,802,666],{"class":287},[198,804,290],{"class":245},[198,806,807],{"class":204},"()",[198,809,810],{"class":275}," =>",[198,812,280],{"class":245},[198,814,546],{"class":204},[198,816,817],{"class":245},"value ",[198,819,820],{"class":283},"*",[198,822,758],{"class":293},[198,824,297],{"class":245},[198,826,262],{"class":204},[198,828,829],{"class":200,"line":398},[198,830,269],{"emptyLinePlaceholder":268},[198,832,833],{"class":200,"line":407},[198,834,835],{"class":697},"\u002F\u002F watch：显式监听某个响应式源，可拿到旧值\u002F新值，适合处理副作用\n",[198,837,838,840,843,845,848,852,854,857,859,861],{"class":200,"line":426},[198,839,607],{"class":287},[198,841,842],{"class":245},"(count",[198,844,658],{"class":204},[198,846,847],{"class":204}," (",[198,849,851],{"class":850},"s99_P","newVal",[198,853,658],{"class":204},[198,855,856],{"class":850}," oldVal",[198,858,297],{"class":204},[198,860,810],{"class":275},[198,862,404],{"class":204},[198,864,865,868,870,873,875,878,881,884,887,890,893,895,897,900,902],{"class":200,"line":432},[198,866,867],{"class":245},"    console",[198,869,546],{"class":204},[198,871,872],{"class":287},"log",[198,874,290],{"class":744},[198,876,877],{"class":222},"`",[198,879,880],{"class":226},"count: ",[198,882,883],{"class":222},"${",[198,885,886],{"class":245},"oldVal",[198,888,889],{"class":222},"}",[198,891,892],{"class":226}," -> ",[198,894,883],{"class":222},[198,896,851],{"class":245},[198,898,899],{"class":222},"}`",[198,901,297],{"class":744},[198,903,262],{"class":204},[198,905,907,909,911],{"class":200,"line":906},16,[198,908,889],{"class":204},[198,910,297],{"class":245},[198,912,262],{"class":204},[198,914,916],{"class":200,"line":915},17,[198,917,269],{"emptyLinePlaceholder":268},[198,919,921],{"class":200,"line":920},18,[198,922,923],{"class":697},"\u002F\u002F watchEffect：立即执行一次，并自动追踪函数内用到的所有响应式依赖\n",[198,925,927,930,932,934,936],{"class":200,"line":926},19,[198,928,929],{"class":287},"watchEffect",[198,931,290],{"class":245},[198,933,807],{"class":204},[198,935,810],{"class":275},[198,937,404],{"class":204},[198,939,941,943,945,947,949,951,954,956,958,960,962,965,967],{"class":200,"line":940},20,[198,942,867],{"class":245},[198,944,546],{"class":204},[198,946,872],{"class":287},[198,948,290],{"class":744},[198,950,223],{"class":222},[198,952,953],{"class":226},"keyword changed:",[198,955,223],{"class":222},[198,957,658],{"class":204},[198,959,732],{"class":245},[198,961,546],{"class":204},[198,963,964],{"class":245},"keyword",[198,966,297],{"class":744},[198,968,262],{"class":204},[198,970,972,974,976],{"class":200,"line":971},21,[198,973,889],{"class":204},[198,975,297],{"class":245},[198,977,262],{"class":204},[198,979,981,983,985],{"class":200,"line":980},22,[198,982,305],{"class":204},[198,984,209],{"class":208},[198,986,232],{"class":204},[68,988,989,999],{},[71,990,991],{},[74,992,993,996],{},[77,994,995],{},"API",[77,997,998],{},"适用场景",[85,1000,1001,1010,1020,1029,1038],{},[74,1002,1003,1007],{},[90,1004,1005],{},[44,1006,602],{},[90,1008,1009],{},"基本类型、需要整体替换的值、组件间传递单个值",[74,1011,1012,1017],{},[90,1013,1014],{},[44,1015,1016],{},"reactive",[90,1018,1019],{},"内部字段较多、需要直接属性访问的对象状态",[74,1021,1022,1026],{},[90,1023,1024],{},[44,1025,586],{},[90,1027,1028],{},"由其他状态派生、需要缓存的只读值",[74,1030,1031,1035],{},[90,1032,1033],{},[44,1034,607],{},[90,1036,1037],{},"需要明确知道“监听谁”、拿到新旧值、按需触发副作用",[74,1039,1040,1044],{},[90,1041,1042],{},[44,1043,929],{},[90,1045,1046],{},"依赖较多且不想手动列出、只关心“最新一次执行”",[63,1048,1049],{"id":1049},"常用指令速查",[68,1051,1052,1064],{},[71,1053,1054],{},[74,1055,1056,1059,1061],{},[77,1057,1058],{},"指令",[77,1060,450],{},[77,1062,1063],{},"示例",[85,1065,1066,1088,1107,1128,1145,1163,1178],{},[74,1067,1068,1080,1083],{},[90,1069,1070,1073,1074,1073,1077],{},[44,1071,1072],{},"v-if"," \u002F ",[44,1075,1076],{},"v-else-if",[44,1078,1079],{},"v-else",[90,1081,1082],{},"条件渲染（销毁\u002F重建 DOM）",[90,1084,1085],{},[44,1086,1087],{},"\u003Cp v-if=\"ok\">Yes\u003C\u002Fp>",[74,1089,1090,1095,1102],{},[90,1091,1092],{},[44,1093,1094],{},"v-show",[90,1096,1097,1098,1101],{},"条件显示（只切换 ",[44,1099,1100],{},"display","，DOM 不销毁）",[90,1103,1104],{},[44,1105,1106],{},"\u003Cp v-show=\"ok\">Yes\u003C\u002Fp>",[74,1108,1109,1114,1123],{},[90,1110,1111],{},[44,1112,1113],{},"v-for",[90,1115,1116,1117],{},"列表渲染，",[34,1118,1119,1120],{},"务必配合 ",[44,1121,1122],{},":key",[90,1124,1125],{},[44,1126,1127],{},"\u003Cli v-for=\"item in list\" :key=\"item.id\">",[74,1129,1130,1137,1140],{},[90,1131,1132,1073,1135],{},[44,1133,1134],{},"v-bind",[44,1136,414],{},[90,1138,1139],{},"绑定属性",[90,1141,1142],{},[44,1143,1144],{},"\u003Cimg :src=\"url\">",[74,1146,1147,1155,1158],{},[90,1148,1149,1073,1152],{},[44,1150,1151],{},"v-on",[44,1153,1154],{},"@",[90,1156,1157],{},"绑定事件",[90,1159,1160],{},[44,1161,1162],{},"\u003Cbutton @click=\"onClick\">",[74,1164,1165,1170,1173],{},[90,1166,1167],{},[44,1168,1169],{},"v-model",[90,1171,1172],{},"表单双向绑定",[90,1174,1175],{},[44,1176,1177],{},"\u003Cinput v-model=\"text\">",[74,1179,1180,1188,1191],{},[90,1181,1182,1073,1185],{},[44,1183,1184],{},"v-slot",[44,1186,1187],{},"#",[90,1189,1190],{},"具名\u002F作用域插槽",[90,1192,1193],{},[44,1194,1195],{},"\u003Ctemplate #header>",[23,1197,1198,1200,1201,1203,1204,1206,1207,1209],{},[44,1199,1072],{}," 与 ",[44,1202,1113],{}," 不建议在同一元素上同时使用（优先级和可读性问题），需要时把 ",[44,1205,1072],{}," 提到外层或用 ",[44,1208,586],{}," 先过滤列表。",[63,1211,1213],{"id":1212},"生命周期钩子组合式-api","生命周期钩子（组合式 API）",[68,1215,1216,1226],{},[71,1217,1218],{},[74,1219,1220,1223],{},[77,1221,1222],{},"钩子",[77,1224,1225],{},"触发时机",[85,1227,1228,1238,1248,1258,1268,1278],{},[74,1229,1230,1235],{},[90,1231,1232],{},[44,1233,1234],{},"onBeforeMount",[90,1236,1237],{},"组件挂载前",[74,1239,1240,1245],{},[90,1241,1242],{},[44,1243,1244],{},"onMounted",[90,1246,1247],{},"组件挂载完成，可访问 DOM、发起初始请求",[74,1249,1250,1255],{},[90,1251,1252],{},[44,1253,1254],{},"onBeforeUpdate",[90,1256,1257],{},"响应式状态变化、DOM 更新前",[74,1259,1260,1265],{},[90,1261,1262],{},[44,1263,1264],{},"onUpdated",[90,1266,1267],{},"DOM 更新完成后",[74,1269,1270,1275],{},[90,1271,1272],{},[44,1273,1274],{},"onBeforeUnmount",[90,1276,1277],{},"组件卸载前，适合清理定时器、事件监听",[74,1279,1280,1285],{},[90,1281,1282],{},[44,1283,1284],{},"onUnmounted",[90,1286,1287],{},"组件卸载完成后",[190,1289,1291],{"className":192,"code":1290,"language":12,"meta":194,"style":194},"\u003Cscript setup lang=\"ts\">\nimport { onMounted, onBeforeUnmount } from \"vue\";\n\nlet timer: number;\nonMounted(() => {\n    timer = window.setInterval(() => console.log(\"tick\"), 1000);\n});\nonBeforeUnmount(() => clearInterval(timer));\n\u003C\u002Fscript>\n",[44,1292,1293,1313,1339,1343,1359,1371,1419,1427,1445],{"__ignoreMap":194},[198,1294,1295,1297,1299,1301,1303,1305,1307,1309,1311],{"class":200,"line":201},[198,1296,205],{"class":204},[198,1298,209],{"class":208},[198,1300,213],{"class":212},[198,1302,216],{"class":212},[198,1304,219],{"class":204},[198,1306,223],{"class":222},[198,1308,227],{"class":226},[198,1310,223],{"class":222},[198,1312,232],{"class":204},[198,1314,1315,1317,1319,1322,1324,1327,1329,1331,1333,1335,1337],{"class":200,"line":235},[198,1316,239],{"class":238},[198,1318,242],{"class":204},[198,1320,1321],{"class":245}," onMounted",[198,1323,658],{"class":204},[198,1325,1326],{"class":245}," onBeforeUnmount",[198,1328,249],{"class":204},[198,1330,252],{"class":238},[198,1332,255],{"class":222},[198,1334,12],{"class":226},[198,1336,223],{"class":222},[198,1338,262],{"class":204},[198,1340,1341],{"class":200,"line":265},[198,1342,269],{"emptyLinePlaceholder":268},[198,1344,1345,1348,1351,1353,1357],{"class":200,"line":272},[198,1346,1347],{"class":275},"let",[198,1349,1350],{"class":245}," timer",[198,1352,414],{"class":283},[198,1354,1356],{"class":1355},"sZMiF"," number",[198,1358,262],{"class":204},[198,1360,1361,1363,1365,1367,1369],{"class":200,"line":302},[198,1362,1244],{"class":287},[198,1364,290],{"class":245},[198,1366,807],{"class":204},[198,1368,810],{"class":275},[198,1370,404],{"class":204},[198,1372,1373,1376,1378,1381,1383,1386,1388,1390,1392,1395,1397,1399,1401,1403,1406,1408,1410,1412,1415,1417],{"class":200,"line":312},[198,1374,1375],{"class":245},"    timer",[198,1377,284],{"class":283},[198,1379,1380],{"class":245}," window",[198,1382,546],{"class":204},[198,1384,1385],{"class":287},"setInterval",[198,1387,290],{"class":744},[198,1389,807],{"class":204},[198,1391,810],{"class":275},[198,1393,1394],{"class":245}," console",[198,1396,546],{"class":204},[198,1398,872],{"class":287},[198,1400,290],{"class":744},[198,1402,223],{"class":222},[198,1404,1405],{"class":226},"tick",[198,1407,223],{"class":222},[198,1409,297],{"class":744},[198,1411,658],{"class":204},[198,1413,1414],{"class":293}," 1000",[198,1416,297],{"class":744},[198,1418,262],{"class":204},[198,1420,1421,1423,1425],{"class":200,"line":317},[198,1422,889],{"class":204},[198,1424,297],{"class":245},[198,1426,262],{"class":204},[198,1428,1429,1431,1433,1435,1437,1440,1443],{"class":200,"line":327},[198,1430,1274],{"class":287},[198,1432,290],{"class":245},[198,1434,807],{"class":204},[198,1436,810],{"class":275},[198,1438,1439],{"class":287}," clearInterval",[198,1441,1442],{"class":245},"(timer))",[198,1444,262],{"class":204},[198,1446,1447,1449,1451],{"class":200,"line":371},[198,1448,305],{"class":204},[198,1450,209],{"class":208},[198,1452,232],{"class":204},[63,1454,1455],{"id":1455},"组件通信基础",[1457,1458,1459,1474,1487],"ul",{},[1460,1461,1462,1465,1466,1469,1470,1473],"li",{},[34,1463,1464],{},"父传子","：",[44,1467,1468],{},"props","（详见 ",[26,1471,1468],{"href":1472},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fprops","）。",[1460,1475,1476,1465,1479,1482,1483,1486],{},[34,1477,1478],{},"子传父",[44,1480,1481],{},"emit"," 自定义事件，父组件用 ",[44,1484,1485],{},"@事件名"," 监听。",[1460,1488,1489,1465,1492,1495,1496,1499,1500,1504],{},[34,1490,1491],{},"跨层级",[44,1493,1494],{},"provide","\u002F",[44,1497,1498],{},"inject","，或使用 ",[26,1501,151],{"href":1502,"rel":1503},"https:\u002F\u002Fpinia.vuejs.org\u002F",[30]," 集中状态。",[190,1506,1508],{"className":192,"code":1507,"language":12,"meta":194,"style":194},"\u003C!-- Child.vue -->\n\u003Cscript setup lang=\"ts\">\nconst emit = defineEmits\u003C{ update: [value: string] }>();\n\u003C\u002Fscript>\n\u003Ctemplate>\n    \u003Cbutton @click=\"emit('update', 'hi')\">Send\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n",[44,1509,1510,1515,1535,1577,1585,1593,1621],{"__ignoreMap":194},[198,1511,1512],{"class":200,"line":201},[198,1513,1514],{"class":697},"\u003C!-- Child.vue -->\n",[198,1516,1517,1519,1521,1523,1525,1527,1529,1531,1533],{"class":200,"line":235},[198,1518,205],{"class":204},[198,1520,209],{"class":208},[198,1522,213],{"class":212},[198,1524,216],{"class":212},[198,1526,219],{"class":204},[198,1528,223],{"class":222},[198,1530,227],{"class":226},[198,1532,223],{"class":222},[198,1534,232],{"class":204},[198,1536,1537,1539,1542,1544,1547,1550,1554,1556,1558,1562,1564,1567,1570,1573,1575],{"class":200,"line":265},[198,1538,276],{"class":275},[198,1540,1541],{"class":279}," emit",[198,1543,284],{"class":283},[198,1545,1546],{"class":287}," defineEmits",[198,1548,1549],{"class":204},"\u003C{",[198,1551,1553],{"class":1552},"sucvu"," update",[198,1555,414],{"class":283},[198,1557,750],{"class":245},[198,1559,1561],{"class":1560},"sbgvK","value",[198,1563,414],{"class":204},[198,1565,1566],{"class":1355}," string",[198,1568,1569],{"class":245},"] ",[198,1571,1572],{"class":204},"}>",[198,1574,807],{"class":245},[198,1576,262],{"class":204},[198,1578,1579,1581,1583],{"class":200,"line":272},[198,1580,305],{"class":204},[198,1582,209],{"class":208},[198,1584,232],{"class":204},[198,1586,1587,1589,1591],{"class":200,"line":302},[198,1588,205],{"class":204},[198,1590,322],{"class":208},[198,1592,232],{"class":204},[198,1594,1595,1597,1599,1601,1603,1605,1608,1610,1612,1615,1617,1619],{"class":200,"line":312},[198,1596,330],{"class":204},[198,1598,333],{"class":208},[198,1600,347],{"class":212},[198,1602,219],{"class":204},[198,1604,223],{"class":222},[198,1606,1607],{"class":226},"emit('update', 'hi')",[198,1609,223],{"class":222},[198,1611,359],{"class":204},[198,1613,1614],{"class":245},"Send",[198,1616,305],{"class":204},[198,1618,333],{"class":208},[198,1620,232],{"class":204},[198,1622,1623,1625,1627],{"class":200,"line":317},[198,1624,305],{"class":204},[198,1626,322],{"class":208},[198,1628,232],{"class":204},[63,1630,1632],{"id":1631},"官方生态常用","官方生态（常用）",[68,1634,1635,1645],{},[71,1636,1637],{},[74,1638,1639,1642],{},[77,1640,1641],{},"库",[77,1643,1644],{},"用途",[85,1646,1647,1659,1669,1680,1692],{},[74,1648,1649,1656],{},[90,1650,1651],{},[26,1652,1655],{"href":1653,"rel":1654},"https:\u002F\u002Frouter.vuejs.org\u002F",[30],"Vue Router",[90,1657,1658],{},"客户端路由",[74,1660,1661,1666],{},[90,1662,1663],{},[26,1664,151],{"href":1502,"rel":1665},[30],[90,1667,1668],{},"状态管理",[74,1670,1671,1677],{},[90,1672,1673],{},[26,1674,133],{"href":1675,"rel":1676},"https:\u002F\u002Fvite.dev\u002F",[30],[90,1678,1679],{},"开发与构建",[74,1681,1682,1689],{},[90,1683,1684],{},[26,1685,1688],{"href":1686,"rel":1687},"https:\u002F\u002Fvueuse.org\u002F",[30],"VueUse",[90,1690,1691],{},"组合式工具函数集合",[74,1693,1694,1701],{},[90,1695,1696],{},[26,1697,1700],{"href":1698,"rel":1699},"https:\u002F\u002Fnuxt.com\u002F",[30],"Nuxt",[90,1702,1703],{},"基于 Vue 的全栈\u002FSSR 框架（可选）",[23,1705,1706,1707,61],{},"深度集成见 ",[26,1708,1710],{"href":1709},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fecology","生态",[63,1712,1713],{"id":1713},"常见坑",[1457,1715,1716,1734,1756,1771,1787],{},[1460,1717,1718,1465,1723,1726,1727,1730,1731,61],{},[34,1719,1720,1722],{},[44,1721,1016],{}," 解构后失去响应式",[44,1724,1725],{},"const { list } = state"," 得到的是普通值，需要 ",[44,1728,1729],{},"toRefs(state)"," 或直接访问 ",[44,1732,1733],{},"state.list",[1460,1735,1736,1744,1745,1748,1749,1751,1752,1755],{},[34,1737,1738,1740,1741],{},[44,1739,602],{}," 忘记 ",[44,1742,1743],{},".value","：在 ",[44,1746,1747],{},"\u003Cscript>"," 中（模板里不需要）忘记 ",[44,1750,1743],{}," 会导致拿到的是 ",[44,1753,1754],{},"RefImpl"," 对象而不是实际值。",[1460,1757,1758,1770],{},[34,1759,1760,1762,1763,1765,1766,1769],{},[44,1761,1113],{}," 不写 ",[44,1764,1122],{}," 或用 ",[44,1767,1768],{},"index"," 作 key","：列表增删时会导致 DOM 复用错乱、动画\u002F输入框状态错位，尽量用稳定的业务 ID。",[1460,1772,1773,1465,1778,1780,1781,1783,1784,1786],{},[34,1774,1775,1776],{},"直接修改 ",[44,1777,1468],{},[44,1779,1468],{}," 是只读的，子组件需要“修改”时应 ",[44,1782,1481],{}," 事件让父组件更新，或用 ",[44,1785,586],{}," 生成本地派生值。",[1460,1788,1789,1795],{},[34,1790,1791,1792,1794],{},"在 ",[44,1793,929],{}," 里产生死循环","：如果回调内又修改了它所依赖的响应式数据，会不断触发自身，注意拆分读\u002F写逻辑。",[63,1797,1798],{"id":1798},"最佳实践",[1800,1801,1802,1809,1817,1824,1837],"ol",{},[1460,1803,1804,1805,1808],{},"新项目统一用 ",[44,1806,1807],{},"\u003Cscript setup lang=\"ts\">","，减少样板代码并获得更好的类型推断。",[1460,1810,1811,1812,1814,1815,61],{},"复杂表单\u002F列表状态优先 ",[44,1813,1016],{},"，跨组件共享的原子值优先 ",[44,1816,602],{},[1460,1818,1819,1820,1823],{},"把可复用的响应式逻辑抽成 Composable（",[44,1821,1822],{},"useXxx"," 函数），而不是在组件里堆逻辑。",[1460,1825,1826,1827,1830,1831,1834,1835,61],{},"组件样式默认加 ",[44,1828,1829],{},"scoped","，需要覆盖子组件样式时用 ",[44,1832,1833],{},":deep()"," 而不是去掉 ",[44,1836,1829],{},[1460,1838,1839,1840,1842],{},"生命周期里注册的副作用（定时器、事件监听、订阅）务必在 ",[44,1841,1274],{}," 中清理。",[63,1844,1845],{"id":1845},"本目录学习路径",[68,1847,1848,1858],{},[71,1849,1850],{},[74,1851,1852,1855],{},[77,1853,1854],{},"主题",[77,1856,1857],{},"文档",[85,1859,1860,1879,1891,1906,1921,1933],{},[74,1861,1862,1865],{},[90,1863,1864],{},"响应式原理",[90,1866,1867,1870,1871,1870,1875],{},[26,1868,1869],{"href":105},"v2-v3"," → ",[26,1872,1874],{"href":1873},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Freactivity\u002Ftrack","track",[26,1876,1878],{"href":1877},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Freactivity\u002Fproxy","proxy 进阶",[74,1880,1881,1884],{},[90,1882,1883],{},"组件设计",[90,1885,1886,52,1889],{},[26,1887,1888],{"href":40},"design",[26,1890,1468],{"href":1472},[74,1892,1893,1896],{},[90,1894,1895],{},"路由与状态",[90,1897,1898,52,1902],{},[26,1899,1901],{"href":1900},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Frouter","router",[26,1903,1905],{"href":1904},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fstatus","status",[74,1907,1908,1911],{},[90,1909,1910],{},"渲染与 TS",[90,1912,1913,52,1917],{},[26,1914,1916],{"href":1915},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Frender","render",[26,1918,1920],{"href":1919},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Ftypescript","typescript",[74,1922,1923,1926],{},[90,1924,1925],{},"性能",[90,1927,1928,1932],{},[26,1929,1931],{"href":1930},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fperformance\u002Fbuild","performance\u002Fbuild"," 等",[74,1934,1935,1938],{},[90,1936,1937],{},"工程与测试",[90,1939,1940,52,1944],{},[26,1941,1943],{"href":1942},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fproject","project",[26,1945,1947],{"href":1946},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Ftest","test",[63,1949,1950],{"id":1950},"参考文献",[23,1952,1953],{},"以下链接在编写时均可正常访问：",[68,1955,1956,1966],{},[71,1957,1958],{},[74,1959,1960,1963],{},[77,1961,1962],{},"资料",[77,1964,1965],{},"说明",[85,1967,1968,1980,1992],{},[74,1969,1970,1977],{},[90,1971,1972],{},[26,1973,1976],{"href":1974,"rel":1975},"https:\u002F\u002Fcn.vuejs.org\u002F",[30],"Vue 官方文档",[90,1978,1979],{},"中文文档",[74,1981,1982,1989],{},[90,1983,1984],{},[26,1985,1988],{"href":1986,"rel":1987},"https:\u002F\u002Fv3-migration.vuejs.org\u002F",[30],"Vue 3 迁移指南",[90,1990,1991],{},"从 Vue 2 迁移（英文）",[74,1993,1994,2001],{},[90,1995,1996],{},[26,1997,2000],{"href":1998,"rel":1999},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FLearn_web_development\u002FCore\u002FFrameworks_libraries\u002FVue_getting_started",[30],"MDN：Vue（入门）",[90,2002,2003],{},"MDN 教程",[390,2005,2006],{},"html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sQzsp, html code.shiki .sQzsp{--shiki-light:#E53935;--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .s9AJx, html code.shiki .s9AJx{--shiki-light:#9C3EDA;--shiki-default:#6F42C1;--shiki-dark:#B392F0}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 .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 .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--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 .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s83vy, html code.shiki .s83vy{--shiki-light:#E2931D;--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .soE4H, html code.shiki .soE4H{--shiki-light:#8796B0;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}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 .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 pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":194,"searchDepth":235,"depth":235,"links":2008},[2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021],{"id":65,"depth":235,"text":66},{"id":181,"depth":235,"text":182},{"id":484,"depth":235,"text":484},{"id":570,"depth":235,"text":571},{"id":618,"depth":235,"text":619},{"id":1049,"depth":235,"text":1049},{"id":1212,"depth":235,"text":1213},{"id":1455,"depth":235,"text":1455},{"id":1631,"depth":235,"text":1632},{"id":1713,"depth":235,"text":1713},{"id":1798,"depth":235,"text":1798},{"id":1845,"depth":235,"text":1845},{"id":1950,"depth":235,"text":1950},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fframe\u002FVue\u002Fbasics","knowledge\u002Fknowledge\u002Fbooklet\u002Fframe\u002FVue\u002Fbasics.md","md",{"items":2027},[2028,2032,2035,2038,2041,2044],{"path":2029,"title":2030,"description":2031,"category":10,"score":312},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fperformance\u002Fassets","资源优化","图片懒加载、按需引入与 Web Vitals 监控。见 HTML 图片、CSS 字体优化。",{"path":1904,"title":2033,"description":2034,"category":10,"score":312},"状态管理：Pinia 与 Vuex","Pinia 是 Vue 官方推荐的状态管理库（Vue 3 新项目默认选型）。Vuex 4 仍可与 Vue 3 配合，用于维护旧项目。见 Vue 基础。",{"path":1709,"title":2036,"description":2037,"category":10,"score":312},"Vue 生态关键库深度集成","VueUse、Vite 与 Nuxt 是 Vue 3 生态中常用的效率与工程化方案。概览见 Vue 基础。",{"path":1873,"title":2039,"description":2040,"category":10,"score":312},"依赖收集与派发更新机制","说明 Vue 3 中 track \u002F trigger 与 targetMap 的工作方式。前置：v2-v3 差异。",{"path":1946,"title":2042,"description":2043,"category":10,"score":312},"测试策略","Vue 应用常用 Vitest + @vue\u002Ftest-utils 做单元\u002F组件测试，Playwright 或 Cypress 做 E2E。见 Vue 基础。",{"path":40,"title":2045,"description":2046,"category":10,"score":312},"组合式 API 与逻辑复用设计模式","组合式 API 与 Composables 是 Vue 3 推荐的逻辑组织方式。概览见 Vue 基础。",{"series":2048,"title":12,"items":2049,"index":201,"prev":2091,"next":2092},"booklet\u002Fframe\u002Fvue",[2050,2052,2053,2056,2058,2060,2063,2066,2069,2072,2075,2079,2081,2083,2085,2088],{"path":2029,"title":2030,"date":2051,"pinned":14},"2025-11-06",{"path":7,"title":8,"date":13,"pinned":14},{"path":1930,"title":2054,"date":2055,"pinned":14},"编译与打包优化","2021-08-02",{"path":40,"title":2045,"date":2057,"pinned":14},"2024-06-16",{"path":1709,"title":2036,"date":2059,"pinned":14},"2025-08-26",{"path":1942,"title":2061,"date":2062,"pinned":14},"工程化实践","2021-07-20",{"path":1472,"title":2064,"date":2065,"pinned":14},"组件通信与跨层级设计模式","2023-03-23",{"path":1877,"title":2067,"date":2068,"pinned":14},"响应式进阶","2023-03-21",{"path":1915,"title":2070,"date":2071,"pinned":14},"渲染机制与编译原理","2021-09-23",{"path":1900,"title":2073,"date":2074,"pinned":14},"路由与权限控制","2021-09-12",{"path":2076,"title":2077,"date":2078,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fvue\u002Fperformance\u002Fruntime","运行时优化","2021-06-10",{"path":1904,"title":2033,"date":2080,"pinned":14},"2025-10-11",{"path":1946,"title":2042,"date":2082,"pinned":14},"2024-10-23",{"path":1873,"title":2039,"date":2084,"pinned":14},"2025-01-13",{"path":1919,"title":2086,"date":2087,"pinned":14},"TypeScript 深度集成","2023-11-29",{"path":105,"title":2089,"date":2090,"pinned":14},"Vue 2 与 Vue 3 响应式差异","2022-07-06",{"path":2029,"title":2030,"date":2051,"pinned":14},{"path":1930,"title":2054,"date":2055,"pinned":14}]