[{"data":1,"prerenderedAt":2572},["ShallowReactive",2],{"page-\u002Fvue\u002Fnuxt\u002F动态组件":3},{"id":4,"title":5,"body":6,"description":2565,"extension":2566,"meta":2567,"navigation":90,"path":2568,"seo":2569,"stem":2570,"__hash__":2571},"content\u002FVue\u002FNuxt\u002F动态组件.md","动态组件",{"type":7,"value":8,"toc":2559},"minimark",[9,30,187,199,205,358,361,364,374,378,390,393,442,451,454,457,505,514,517,570,585,594,597,650,662,671,674,733,742,745,877,886,889,937,946,953,1071,1074,1081,1096,1099,1884,1891,1894,1994,2004,2219,2238,2241,2291,2298,2336,2344,2370,2377,2391,2394,2423,2457,2555],[10,11,12,13,17,18,21,22,25,26,29],"p",{},"如果你想使用 Vue 的 ",[14,15,16],"code",{},"\u003Ccomponent :is=\"someComputedComponent\">"," 语法，你需要使用 Vue 提供的 ",[14,19,20],{},"resolveComponent"," 辅助函数，或者直接从 ",[14,23,24],{},"#components"," 导入组件并将其传递给 ",[14,27,28],{},"is"," 属性。",[31,32,37],"pre",{"className":33,"code":34,"language":35,"meta":36,"style":36},"language-vue shiki shiki-themes github-light github-dark","\u003Cscript setup lang=\"ts\">\nimport { SomeComponent } from '#components'\n\nconst MyButton = resolveComponent('MyButton')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Ccomponent :is=\"clickable ? MyButton : 'div'\" \u002F>\n  \u003Ccomponent :is=\"SomeComponent\" \u002F>\n\u003C\u002Ftemplate>\n\n","vue","",[14,38,39,69,85,92,117,127,132,142,162,178],{"__ignoreMap":36},[40,41,44,48,52,56,59,62,66],"span",{"class":42,"line":43},"line",1,[40,45,47],{"class":46},"sVt8B","\u003C",[40,49,51],{"class":50},"s9eBZ","script",[40,53,55],{"class":54},"sScJk"," setup",[40,57,58],{"class":54}," lang",[40,60,61],{"class":46},"=",[40,63,65],{"class":64},"sZZnC","\"ts\"",[40,67,68],{"class":46},">\n",[40,70,72,76,79,82],{"class":42,"line":71},2,[40,73,75],{"class":74},"szBVR","import",[40,77,78],{"class":46}," { SomeComponent } ",[40,80,81],{"class":74},"from",[40,83,84],{"class":64}," '#components'\n",[40,86,88],{"class":42,"line":87},3,[40,89,91],{"emptyLinePlaceholder":90},true,"\n",[40,93,95,98,102,105,108,111,114],{"class":42,"line":94},4,[40,96,97],{"class":74},"const",[40,99,101],{"class":100},"sj4cs"," MyButton",[40,103,104],{"class":74}," =",[40,106,107],{"class":54}," resolveComponent",[40,109,110],{"class":46},"(",[40,112,113],{"class":64},"'MyButton'",[40,115,116],{"class":46},")\n",[40,118,120,123,125],{"class":42,"line":119},5,[40,121,122],{"class":46},"\u003C\u002F",[40,124,51],{"class":50},[40,126,68],{"class":46},[40,128,130],{"class":42,"line":129},6,[40,131,91],{"emptyLinePlaceholder":90},[40,133,135,137,140],{"class":42,"line":134},7,[40,136,47],{"class":46},[40,138,139],{"class":50},"template",[40,141,68],{"class":46},[40,143,145,148,151,154,156,159],{"class":42,"line":144},8,[40,146,147],{"class":46},"  \u003C",[40,149,150],{"class":50},"component",[40,152,153],{"class":54}," :is",[40,155,61],{"class":46},[40,157,158],{"class":64},"\"clickable ? MyButton : 'div'\"",[40,160,161],{"class":46}," \u002F>\n",[40,163,165,167,169,171,173,176],{"class":42,"line":164},9,[40,166,147],{"class":46},[40,168,150],{"class":50},[40,170,153],{"class":54},[40,172,61],{"class":46},[40,174,175],{"class":64},"\"SomeComponent\"",[40,177,161],{"class":46},[40,179,181,183,185],{"class":42,"line":180},10,[40,182,122],{"class":46},[40,184,139],{"class":50},[40,186,68],{"class":46},[10,188,189,190,198],{},"要动态导入组件（也称为延迟加载组件），只需在组件名称前",[191,192,193,194,197],"strong",{},"添加 ",[14,195,196],{},"Lazy"," 前缀","。如果组件并非总是需要，这非常有用。",[10,200,201,202,204],{},"通过使用 ",[14,203,196],{}," 前缀，你可以延迟加载组件代码，直到需要时才加载，这有助于优化 JavaScript 包大小。",[31,206,208],{"className":33,"code":207,"language":35,"meta":36,"style":36},"\u003Cscript setup lang=\"ts\">\nconst show = ref(false)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Ch1>山脉\u003C\u002Fh1>\n    \u003CLazyMountainsList v-if=\"show\" \u002F>\n    \u003Cbutton v-if=\"!show\" @click=\"show = true\">显示列表\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n",[14,209,210,226,245,253,257,265,274,289,311,340,349],{"__ignoreMap":36},[40,211,212,214,216,218,220,222,224],{"class":42,"line":43},[40,213,47],{"class":46},[40,215,51],{"class":50},[40,217,55],{"class":54},[40,219,58],{"class":54},[40,221,61],{"class":46},[40,223,65],{"class":64},[40,225,68],{"class":46},[40,227,228,230,233,235,238,240,243],{"class":42,"line":71},[40,229,97],{"class":74},[40,231,232],{"class":100}," show",[40,234,104],{"class":74},[40,236,237],{"class":54}," ref",[40,239,110],{"class":46},[40,241,242],{"class":100},"false",[40,244,116],{"class":46},[40,246,247,249,251],{"class":42,"line":87},[40,248,122],{"class":46},[40,250,51],{"class":50},[40,252,68],{"class":46},[40,254,255],{"class":42,"line":94},[40,256,91],{"emptyLinePlaceholder":90},[40,258,259,261,263],{"class":42,"line":119},[40,260,47],{"class":46},[40,262,139],{"class":50},[40,264,68],{"class":46},[40,266,267,269,272],{"class":42,"line":129},[40,268,147],{"class":46},[40,270,271],{"class":50},"div",[40,273,68],{"class":46},[40,275,276,279,282,285,287],{"class":42,"line":134},[40,277,278],{"class":46},"    \u003C",[40,280,281],{"class":50},"h1",[40,283,284],{"class":46},">山脉\u003C\u002F",[40,286,281],{"class":50},[40,288,68],{"class":46},[40,290,291,293,296,299,301,304,307,309],{"class":42,"line":144},[40,292,278],{"class":46},[40,294,295],{"class":50},"LazyMountainsList",[40,297,298],{"class":74}," v-if",[40,300,61],{"class":46},[40,302,303],{"class":64},"\"",[40,305,306],{"class":46},"show",[40,308,303],{"class":64},[40,310,161],{"class":46},[40,312,313,315,318,320,322,325,328,330,333,336,338],{"class":42,"line":164},[40,314,278],{"class":46},[40,316,317],{"class":50},"button",[40,319,298],{"class":54},[40,321,61],{"class":46},[40,323,324],{"class":64},"\"!show\"",[40,326,327],{"class":54}," @click",[40,329,61],{"class":46},[40,331,332],{"class":64},"\"show = true\"",[40,334,335],{"class":46},">显示列表\u003C\u002F",[40,337,317],{"class":50},[40,339,68],{"class":46},[40,341,342,345,347],{"class":42,"line":180},[40,343,344],{"class":46},"  \u003C\u002F",[40,346,271],{"class":50},[40,348,68],{"class":46},[40,350,352,354,356],{"class":42,"line":351},11,[40,353,122],{"class":46},[40,355,139],{"class":50},[40,357,68],{"class":46},[10,359,360],{},"延迟组件非常适合控制应用的块大小，但它们并不总是能提升运行时性能，因为除非有条件渲染，否则它们仍然会急切加载。在现实世界的应用中，有些页面可能包含大量内容和组件，大多数时候并非所有组件都需要在页面加载时立即交互。让它们全部急切加载可能会对性能产生负面影响。",[10,362,363],{},"为了优化你的应用，你可能希望延迟某些组件的 hydration，直到它们可见或浏览器完成更重要的任务。Nuxt 通过延迟（或惰性）hydration 支持这一点，允许你控制组件何时变得可交互。Nuxt 提供了一系列内置的 hydration 策略。每个延迟组件只能使用一种策略。",[10,365,366,367,370,371,373],{},"目前 Nuxt 的内置延迟 hydration 仅适用于单文件组件（SFC），并且要求你在模板中定义 prop（而不是通过 ",[14,368,369],{},"v-bind"," 展开 prop 对象）。它也不适用于直接从 ",[14,372,24],{}," 导入的组件。",[375,376,377],"h2",{"id":377},"水合策略",[379,380,382],"h4",{"id":381},"hydrate-on-visible",[383,384,388],"a",{"href":385,"rel":386},"https:\u002F\u002Fnuxt.com.cn\u002Fdocs\u002F4.x\u002Fguide\u002Fdirectory-structure\u002Fapp\u002Fcomponents#hydrate-on-visible",[387],"nofollow",[14,389,381],{},[10,391,392],{},"当组件进入视口时进行 hydration。  pages\u002Findex.vue",[31,394,396],{"className":33,"code":395,"language":35,"meta":36,"style":36},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003CLazyMyComponent hydrate-on-visible \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[14,397,398,406,414,426,434],{"__ignoreMap":36},[40,399,400,402,404],{"class":42,"line":43},[40,401,47],{"class":46},[40,403,139],{"class":50},[40,405,68],{"class":46},[40,407,408,410,412],{"class":42,"line":71},[40,409,147],{"class":46},[40,411,271],{"class":50},[40,413,68],{"class":46},[40,415,416,418,421,424],{"class":42,"line":87},[40,417,278],{"class":46},[40,419,420],{"class":50},"LazyMyComponent",[40,422,423],{"class":54}," hydrate-on-visible",[40,425,161],{"class":46},[40,427,428,430,432],{"class":42,"line":94},[40,429,344],{"class":46},[40,431,271],{"class":50},[40,433,68],{"class":46},[40,435,436,438,440],{"class":42,"line":119},[40,437,122],{"class":46},[40,439,139],{"class":50},[40,441,68],{"class":46},[379,443,445],{"id":444},"hydrate-on-idle",[383,446,449],{"href":447,"rel":448},"https:\u002F\u002Fnuxt.com.cn\u002Fdocs\u002F4.x\u002Fguide\u002Fdirectory-structure\u002Fapp\u002Fcomponents#hydrate-on-idle",[387],[14,450,444],{},[10,452,453],{},"当浏览器空闲时进行 hydration。如果需要组件尽快加载但不阻塞关键渲染路径，这很适合。",[10,455,456],{},"你还可以传递一个数字作为最大超时时间。pages\u002Findex.vue",[31,458,460],{"className":33,"code":459,"language":35,"meta":36,"style":36},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003CLazyMyComponent hydrate-on-idle \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[14,461,462,470,478,489,497],{"__ignoreMap":36},[40,463,464,466,468],{"class":42,"line":43},[40,465,47],{"class":46},[40,467,139],{"class":50},[40,469,68],{"class":46},[40,471,472,474,476],{"class":42,"line":71},[40,473,147],{"class":46},[40,475,271],{"class":50},[40,477,68],{"class":46},[40,479,480,482,484,487],{"class":42,"line":87},[40,481,278],{"class":46},[40,483,420],{"class":50},[40,485,486],{"class":54}," hydrate-on-idle",[40,488,161],{"class":46},[40,490,491,493,495],{"class":42,"line":94},[40,492,344],{"class":46},[40,494,271],{"class":50},[40,496,68],{"class":46},[40,498,499,501,503],{"class":42,"line":119},[40,500,122],{"class":46},[40,502,139],{"class":50},[40,504,68],{"class":46},[379,506,508],{"id":507},"hydrate-on-interaction",[383,509,512],{"href":510,"rel":511},"https:\u002F\u002Fnuxt.com.cn\u002Fdocs\u002F4.x\u002Fguide\u002Fdirectory-structure\u002Fapp\u002Fcomponents#hydrate-on-interaction",[387],[14,513,507],{},[10,515,516],{},"在指定交互（例如点击、鼠标悬停）后进行 hydration。pages\u002Findex.vue",[31,518,520],{"className":33,"code":519,"language":35,"meta":36,"style":36},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003CLazyMyComponent hydrate-on-interaction=\"mouseover\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[14,521,522,530,538,554,562],{"__ignoreMap":36},[40,523,524,526,528],{"class":42,"line":43},[40,525,47],{"class":46},[40,527,139],{"class":50},[40,529,68],{"class":46},[40,531,532,534,536],{"class":42,"line":71},[40,533,147],{"class":46},[40,535,271],{"class":50},[40,537,68],{"class":46},[40,539,540,542,544,547,549,552],{"class":42,"line":87},[40,541,278],{"class":46},[40,543,420],{"class":50},[40,545,546],{"class":54}," hydrate-on-interaction",[40,548,61],{"class":46},[40,550,551],{"class":64},"\"mouseover\"",[40,553,161],{"class":46},[40,555,556,558,560],{"class":42,"line":94},[40,557,344],{"class":46},[40,559,271],{"class":50},[40,561,68],{"class":46},[40,563,564,566,568],{"class":42,"line":119},[40,565,122],{"class":46},[40,567,139],{"class":50},[40,569,68],{"class":46},[10,571,572,573,576,577,580,581,584],{},"如果不传递事件或事件列表，它默认在 ",[14,574,575],{},"pointerenter","、",[14,578,579],{},"click"," 和 ",[14,582,583],{},"focus"," 时进行 hydration。",[379,586,588],{"id":587},"hydrate-on-media-query",[383,589,592],{"href":590,"rel":591},"https:\u002F\u002Fnuxt.com.cn\u002Fdocs\u002F4.x\u002Fguide\u002Fdirectory-structure\u002Fapp\u002Fcomponents#hydrate-on-media-query",[387],[14,593,587],{},[10,595,596],{},"当窗口匹配媒体查询时进行 hydration。pages\u002Findex.vue",[31,598,600],{"className":33,"code":599,"language":35,"meta":36,"style":36},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003CLazyMyComponent hydrate-on-media-query=\"(max-width: 768px)\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[14,601,602,610,618,634,642],{"__ignoreMap":36},[40,603,604,606,608],{"class":42,"line":43},[40,605,47],{"class":46},[40,607,139],{"class":50},[40,609,68],{"class":46},[40,611,612,614,616],{"class":42,"line":71},[40,613,147],{"class":46},[40,615,271],{"class":50},[40,617,68],{"class":46},[40,619,620,622,624,627,629,632],{"class":42,"line":87},[40,621,278],{"class":46},[40,623,420],{"class":50},[40,625,626],{"class":54}," hydrate-on-media-query",[40,628,61],{"class":46},[40,630,631],{"class":64},"\"(max-width: 768px)\"",[40,633,161],{"class":46},[40,635,636,638,640],{"class":42,"line":94},[40,637,344],{"class":46},[40,639,271],{"class":50},[40,641,68],{"class":46},[40,643,644,646,648],{"class":42,"line":119},[40,645,122],{"class":46},[40,647,139],{"class":50},[40,649,68],{"class":46},[10,651,652,653,661],{},"在底层，这使用了 Vue 内置的 ",[383,654,657,660],{"href":655,"rel":656},"https:\u002F\u002Fvuejs.org\u002Fguide\u002Fcomponents\u002Fasync.html#hydrate-on-media-query",[387],[14,658,659],{},"hydrateOnMediaQuery"," 策略","。",[379,663,665],{"id":664},"hydrate-after",[383,666,669],{"href":667,"rel":668},"https:\u002F\u002Fnuxt.com.cn\u002Fdocs\u002F4.x\u002Fguide\u002Fdirectory-structure\u002Fapp\u002Fcomponents#hydrate-after",[387],[14,670,664],{},[10,672,673],{},"在指定延迟（以毫秒为单位）后进行 hydration。pages\u002Findex.vue",[31,675,677],{"className":33,"code":676,"language":35,"meta":36,"style":36},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003CLazyMyComponent :hydrate-after=\"2000\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[14,678,679,687,695,717,725],{"__ignoreMap":36},[40,680,681,683,685],{"class":42,"line":43},[40,682,47],{"class":46},[40,684,139],{"class":50},[40,686,68],{"class":46},[40,688,689,691,693],{"class":42,"line":71},[40,690,147],{"class":46},[40,692,271],{"class":50},[40,694,68],{"class":46},[40,696,697,699,701,704,706,708,710,713,715],{"class":42,"line":87},[40,698,278],{"class":46},[40,700,420],{"class":50},[40,702,703],{"class":46}," :",[40,705,664],{"class":54},[40,707,61],{"class":46},[40,709,303],{"class":64},[40,711,712],{"class":100},"2000",[40,714,303],{"class":64},[40,716,161],{"class":46},[40,718,719,721,723],{"class":42,"line":94},[40,720,344],{"class":46},[40,722,271],{"class":50},[40,724,68],{"class":46},[40,726,727,729,731],{"class":42,"line":119},[40,728,122],{"class":46},[40,730,139],{"class":50},[40,732,68],{"class":46},[379,734,736],{"id":735},"hydrate-when",[383,737,740],{"href":738,"rel":739},"https:\u002F\u002Fnuxt.com.cn\u002Fdocs\u002F4.x\u002Fguide\u002Fdirectory-structure\u002Fapp\u002Fcomponents#hydrate-when",[387],[14,741,735],{},[10,743,744],{},"基于布尔条件进行 hydration。pages\u002Findex.vue",[31,746,748],{"className":33,"code":747,"language":35,"meta":36,"style":36},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003CLazyMyComponent :hydrate-when=\"isReady\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\u003Cscript setup lang=\"ts\">\nconst isReady = ref(false)\nfunction myFunction() {\n  \u002F\u002F 触发自定义 hydration 策略...\n  isReady.value = true\n}\n\u003C\u002Fscript>\n",[14,749,750,758,766,787,795,803,819,836,847,853,863,868],{"__ignoreMap":36},[40,751,752,754,756],{"class":42,"line":43},[40,753,47],{"class":46},[40,755,139],{"class":50},[40,757,68],{"class":46},[40,759,760,762,764],{"class":42,"line":71},[40,761,147],{"class":46},[40,763,271],{"class":50},[40,765,68],{"class":46},[40,767,768,770,772,774,776,778,780,783,785],{"class":42,"line":87},[40,769,278],{"class":46},[40,771,420],{"class":50},[40,773,703],{"class":46},[40,775,735],{"class":54},[40,777,61],{"class":46},[40,779,303],{"class":64},[40,781,782],{"class":46},"isReady",[40,784,303],{"class":64},[40,786,161],{"class":46},[40,788,789,791,793],{"class":42,"line":94},[40,790,344],{"class":46},[40,792,271],{"class":50},[40,794,68],{"class":46},[40,796,797,799,801],{"class":42,"line":119},[40,798,122],{"class":46},[40,800,139],{"class":50},[40,802,68],{"class":46},[40,804,805,807,809,811,813,815,817],{"class":42,"line":129},[40,806,47],{"class":46},[40,808,51],{"class":50},[40,810,55],{"class":54},[40,812,58],{"class":54},[40,814,61],{"class":46},[40,816,65],{"class":64},[40,818,68],{"class":46},[40,820,821,823,826,828,830,832,834],{"class":42,"line":134},[40,822,97],{"class":74},[40,824,825],{"class":100}," isReady",[40,827,104],{"class":74},[40,829,237],{"class":54},[40,831,110],{"class":46},[40,833,242],{"class":100},[40,835,116],{"class":46},[40,837,838,841,844],{"class":42,"line":144},[40,839,840],{"class":74},"function",[40,842,843],{"class":54}," myFunction",[40,845,846],{"class":46},"() {\n",[40,848,849],{"class":42,"line":164},[40,850,852],{"class":851},"sJ8bj","  \u002F\u002F 触发自定义 hydration 策略...\n",[40,854,855,858,860],{"class":42,"line":180},[40,856,857],{"class":46},"  isReady.value ",[40,859,61],{"class":74},[40,861,862],{"class":100}," true\n",[40,864,865],{"class":42,"line":351},[40,866,867],{"class":46},"}\n",[40,869,871,873,875],{"class":42,"line":870},12,[40,872,122],{"class":46},[40,874,51],{"class":50},[40,876,68],{"class":46},[379,878,880],{"id":879},"hydrate-never",[383,881,884],{"href":882,"rel":883},"https:\u002F\u002Fnuxt.com.cn\u002Fdocs\u002F4.x\u002Fguide\u002Fdirectory-structure\u002Fapp\u002Fcomponents#hydrate-never",[387],[14,885,879],{},[10,887,888],{},"永不 hydration 组件。pages\u002Findex.vue",[31,890,892],{"className":33,"code":891,"language":35,"meta":36,"style":36},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003CLazyMyComponent hydrate-never \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[14,893,894,902,910,921,929],{"__ignoreMap":36},[40,895,896,898,900],{"class":42,"line":43},[40,897,47],{"class":46},[40,899,139],{"class":50},[40,901,68],{"class":46},[40,903,904,906,908],{"class":42,"line":71},[40,905,147],{"class":46},[40,907,271],{"class":50},[40,909,68],{"class":46},[40,911,912,914,916,919],{"class":42,"line":87},[40,913,278],{"class":46},[40,915,420],{"class":50},[40,917,918],{"class":54}," hydrate-never",[40,920,161],{"class":46},[40,922,923,925,927],{"class":42,"line":94},[40,924,344],{"class":46},[40,926,271],{"class":50},[40,928,68],{"class":46},[40,930,931,933,935],{"class":42,"line":119},[40,932,122],{"class":46},[40,934,139],{"class":50},[40,936,68],{"class":46},[938,939,941],"h3",{"id":940},"监听-hydration-事件",[383,942,945],{"href":943,"rel":944},"https:\u002F\u002Fnuxt.com.cn\u002Fdocs\u002F4.x\u002Fguide\u002Fdirectory-structure\u002Fapp\u002Fcomponents#%E7%9B%91%E5%90%AC-hydration-%E4%BA%8B%E4%BB%B6",[387],"监听 Hydration 事件",[10,947,948,949,952],{},"所有延迟 hydration 组件在 hydration 时都会发出一个 ",[14,950,951],{},"@hydrated"," 事件。pages\u002Findex.vue",[31,954,956],{"className":33,"code":955,"language":35,"meta":36,"style":36},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003CLazyMyComponent hydrate-on-visible @hydrated=\"onHydrate\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup lang=\"ts\">\nfunction onHydrate() {\n  console.log(\"组件已完成 hydration！\")\n}\n\u003C\u002Fscript>\n",[14,957,958,966,974,999,1007,1015,1019,1035,1044,1059,1063],{"__ignoreMap":36},[40,959,960,962,964],{"class":42,"line":43},[40,961,47],{"class":46},[40,963,139],{"class":50},[40,965,68],{"class":46},[40,967,968,970,972],{"class":42,"line":71},[40,969,147],{"class":46},[40,971,271],{"class":50},[40,973,68],{"class":46},[40,975,976,978,980,982,985,988,990,992,995,997],{"class":42,"line":87},[40,977,278],{"class":46},[40,979,420],{"class":50},[40,981,423],{"class":54},[40,983,984],{"class":46}," @",[40,986,987],{"class":54},"hydrated",[40,989,61],{"class":46},[40,991,303],{"class":64},[40,993,994],{"class":46},"onHydrate",[40,996,303],{"class":64},[40,998,161],{"class":46},[40,1000,1001,1003,1005],{"class":42,"line":94},[40,1002,344],{"class":46},[40,1004,271],{"class":50},[40,1006,68],{"class":46},[40,1008,1009,1011,1013],{"class":42,"line":119},[40,1010,122],{"class":46},[40,1012,139],{"class":50},[40,1014,68],{"class":46},[40,1016,1017],{"class":42,"line":129},[40,1018,91],{"emptyLinePlaceholder":90},[40,1020,1021,1023,1025,1027,1029,1031,1033],{"class":42,"line":134},[40,1022,47],{"class":46},[40,1024,51],{"class":50},[40,1026,55],{"class":54},[40,1028,58],{"class":54},[40,1030,61],{"class":46},[40,1032,65],{"class":64},[40,1034,68],{"class":46},[40,1036,1037,1039,1042],{"class":42,"line":144},[40,1038,840],{"class":74},[40,1040,1041],{"class":54}," onHydrate",[40,1043,846],{"class":46},[40,1045,1046,1049,1052,1054,1057],{"class":42,"line":164},[40,1047,1048],{"class":46},"  console.",[40,1050,1051],{"class":54},"log",[40,1053,110],{"class":46},[40,1055,1056],{"class":64},"\"组件已完成 hydration！\"",[40,1058,116],{"class":46},[40,1060,1061],{"class":42,"line":180},[40,1062,867],{"class":46},[40,1064,1065,1067,1069],{"class":42,"line":351},[40,1066,122],{"class":46},[40,1068,51],{"class":50},[40,1070,68],{"class":46},[375,1072,1073],{"id":1073},"动态路由文件",[10,1075,1076,1077,1080],{},"当我们访问例如\u002Fanimation\u002F",[14,1078,1079],{},"[name].vue"," 这样的页面的时候，url会类似于\u002Fanimation\u002Ffade类似于这样，我们可以通过route.params.name来匹配文件的名称从而达到动态路由的效果。",[10,1082,1083,1084,1087,1088,1091,1092,1095],{},"中括号 ",[14,1085,1086],{},"[]"," 表示这是一个",[191,1089,1090],{},"动态参数","，它会捕获 URL 中对应位置的值，并存入 ",[14,1093,1094],{},"route.params"," 对象中。",[10,1097,1098],{},"这是一个简单的实现：",[31,1100,1102],{"className":33,"code":1101,"language":35,"meta":36,"style":36},"\u003Ctemplate>\n  \u003Cdiv class=\"p-6 max-w-4xl mx-auto\">\n    \u003Cdiv class=\"border-2 border-dashed border-gray-300 rounded-lg p-12 min-h-[400px] flex items-center justify-center bg-gray-50\">\n      \u003Ccomponent\n        :is=\"component\"\n        :key=\"componentKey\"\n        class=\"w-full\"\n      \u002F>\n    \u003C\u002Fdiv>\n    \u003C!-- 自动扫描 components\u002Fanimations\u002F 目录生成按钮 -->\n    \u003Cdiv class=\"mt-6 flex gap-3 flex-wrap\">\n      \u003CNuxtLink\n        v-for=\"item in availableAnimations\"\n        :key=\"item\"\n        :to=\"`\u002Fanimation\u002F${item}`\"\n        class=\"px-4 py-2 rounded-lg border transition-colors\"\n        :class=\"\n          item === animationName\n            ? 'bg-blue-600 text-white border-blue-600'\n            : 'border-gray-300 hover:bg-gray-100'\n        \"\n      >\n        {{ item }}\n      \u003C\u002FNuxtLink>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup lang=\"ts\">\nconst route = useRoute()\nconst router = useRouter()\nconst animationName = computed(() => route.params.name as string)\nconst component = defineAsyncComponent({\n  loader: () => import(`~\u002Fcomponents\u002Fanimations\u002F${animationName.value}.vue`),\n  onError: () => {\n    console.warn(`动画组件 ${animationName.value} 不存在，重定向到 fade`)\n    navigateTo('\u002Fanimation\u002Ffade', { replace: true })\n  }\n})\nconst componentKey = ref(0)\nconst animationModules = import.meta.glob('~\u002Fcomponents\u002Fanimations\u002F*.vue')\nconst availableAnimations = computed(() => {\n  return Object.keys(animationModules).map((path) => {\n    const fileName = path.split('\u002F').pop() || ''\n    return fileName.replace('.vue', '')\n  })\n})\nonMounted(() => {\n  if (!availableAnimations.value.includes(animationName.value)) {\n    navigateTo(`\u002Fanimation\u002F${availableAnimations.value[0] || 'fade'}`, { replace: true })\n  }\n})\nconst replay = () => {\n  componentKey.value++\n}\n\u003C\u002Fscript>\n",[14,1103,1104,1112,1129,1145,1153,1163,1173,1183,1188,1197,1202,1217,1224,1246,1264,1282,1293,1305,1317,1326,1335,1341,1347,1353,1364,1373,1383,1392,1397,1414,1430,1445,1475,1491,1525,1538,1563,1583,1589,1595,1614,1643,1660,1692,1729,1754,1760,1765,1777,1798,1834,1839,1844,1861,1870,1875],{"__ignoreMap":36},[40,1105,1106,1108,1110],{"class":42,"line":43},[40,1107,47],{"class":46},[40,1109,139],{"class":50},[40,1111,68],{"class":46},[40,1113,1114,1117,1119,1122,1124,1127],{"class":42,"line":71},[40,1115,1116],{"class":46},"  \u003C",[40,1118,271],{"class":50},[40,1120,1121],{"class":54}," class",[40,1123,61],{"class":46},[40,1125,1126],{"class":64},"\"p-6 max-w-4xl mx-auto\"",[40,1128,68],{"class":46},[40,1130,1131,1134,1136,1138,1140,1143],{"class":42,"line":87},[40,1132,1133],{"class":46},"    \u003C",[40,1135,271],{"class":50},[40,1137,1121],{"class":54},[40,1139,61],{"class":46},[40,1141,1142],{"class":64},"\"border-2 border-dashed border-gray-300 rounded-lg p-12 min-h-[400px] flex items-center justify-center bg-gray-50\"",[40,1144,68],{"class":46},[40,1146,1147,1150],{"class":42,"line":94},[40,1148,1149],{"class":46},"      \u003C",[40,1151,1152],{"class":50},"component\n",[40,1154,1155,1158,1160],{"class":42,"line":119},[40,1156,1157],{"class":54},"        :is",[40,1159,61],{"class":46},[40,1161,1162],{"class":64},"\"component\"\n",[40,1164,1165,1168,1170],{"class":42,"line":129},[40,1166,1167],{"class":54},"        :key",[40,1169,61],{"class":46},[40,1171,1172],{"class":64},"\"componentKey\"\n",[40,1174,1175,1178,1180],{"class":42,"line":134},[40,1176,1177],{"class":54},"        class",[40,1179,61],{"class":46},[40,1181,1182],{"class":64},"\"w-full\"\n",[40,1184,1185],{"class":42,"line":144},[40,1186,1187],{"class":46},"      \u002F>\n",[40,1189,1190,1193,1195],{"class":42,"line":164},[40,1191,1192],{"class":46},"    \u003C\u002F",[40,1194,271],{"class":50},[40,1196,68],{"class":46},[40,1198,1199],{"class":42,"line":180},[40,1200,1201],{"class":851},"    \u003C!-- 自动扫描 components\u002Fanimations\u002F 目录生成按钮 -->\n",[40,1203,1204,1206,1208,1210,1212,1215],{"class":42,"line":351},[40,1205,1133],{"class":46},[40,1207,271],{"class":50},[40,1209,1121],{"class":54},[40,1211,61],{"class":46},[40,1213,1214],{"class":64},"\"mt-6 flex gap-3 flex-wrap\"",[40,1216,68],{"class":46},[40,1218,1219,1221],{"class":42,"line":870},[40,1220,1149],{"class":46},[40,1222,1223],{"class":50},"NuxtLink\n",[40,1225,1227,1230,1232,1234,1237,1240,1243],{"class":42,"line":1226},13,[40,1228,1229],{"class":74},"        v-for",[40,1231,61],{"class":46},[40,1233,303],{"class":64},[40,1235,1236],{"class":46},"item ",[40,1238,1239],{"class":74},"in",[40,1241,1242],{"class":46}," availableAnimations",[40,1244,1245],{"class":64},"\"\n",[40,1247,1249,1252,1255,1257,1259,1262],{"class":42,"line":1248},14,[40,1250,1251],{"class":46},"        :",[40,1253,1254],{"class":54},"key",[40,1256,61],{"class":46},[40,1258,303],{"class":64},[40,1260,1261],{"class":46},"item",[40,1263,1245],{"class":64},[40,1265,1267,1269,1272,1274,1277,1279],{"class":42,"line":1266},15,[40,1268,1251],{"class":46},[40,1270,1271],{"class":54},"to",[40,1273,61],{"class":46},[40,1275,1276],{"class":64},"\"`\u002Fanimation\u002F${",[40,1278,1261],{"class":46},[40,1280,1281],{"class":64},"}`\"\n",[40,1283,1285,1288,1290],{"class":42,"line":1284},16,[40,1286,1287],{"class":54},"        class",[40,1289,61],{"class":46},[40,1291,1292],{"class":64},"\"px-4 py-2 rounded-lg border transition-colors\"\n",[40,1294,1296,1298,1301,1303],{"class":42,"line":1295},17,[40,1297,1251],{"class":46},[40,1299,1300],{"class":54},"class",[40,1302,61],{"class":46},[40,1304,1245],{"class":64},[40,1306,1308,1311,1314],{"class":42,"line":1307},18,[40,1309,1310],{"class":46},"          item ",[40,1312,1313],{"class":74},"===",[40,1315,1316],{"class":46}," animationName\n",[40,1318,1320,1323],{"class":42,"line":1319},19,[40,1321,1322],{"class":74},"            ?",[40,1324,1325],{"class":64}," 'bg-blue-600 text-white border-blue-600'\n",[40,1327,1329,1332],{"class":42,"line":1328},20,[40,1330,1331],{"class":74},"            :",[40,1333,1334],{"class":64}," 'border-gray-300 hover:bg-gray-100'\n",[40,1336,1338],{"class":42,"line":1337},21,[40,1339,1340],{"class":64},"        \"\n",[40,1342,1344],{"class":42,"line":1343},22,[40,1345,1346],{"class":46},"      >\n",[40,1348,1350],{"class":42,"line":1349},23,[40,1351,1352],{"class":46},"        {{ item }}\n",[40,1354,1356,1359,1362],{"class":42,"line":1355},24,[40,1357,1358],{"class":46},"      \u003C\u002F",[40,1360,1361],{"class":50},"NuxtLink",[40,1363,68],{"class":46},[40,1365,1367,1369,1371],{"class":42,"line":1366},25,[40,1368,1192],{"class":46},[40,1370,271],{"class":50},[40,1372,68],{"class":46},[40,1374,1376,1379,1381],{"class":42,"line":1375},26,[40,1377,1378],{"class":46},"  \u003C\u002F",[40,1380,271],{"class":50},[40,1382,68],{"class":46},[40,1384,1386,1388,1390],{"class":42,"line":1385},27,[40,1387,122],{"class":46},[40,1389,139],{"class":50},[40,1391,68],{"class":46},[40,1393,1395],{"class":42,"line":1394},28,[40,1396,91],{"emptyLinePlaceholder":90},[40,1398,1400,1402,1404,1406,1408,1410,1412],{"class":42,"line":1399},29,[40,1401,47],{"class":46},[40,1403,51],{"class":50},[40,1405,55],{"class":54},[40,1407,58],{"class":54},[40,1409,61],{"class":46},[40,1411,65],{"class":64},[40,1413,68],{"class":46},[40,1415,1417,1419,1422,1424,1427],{"class":42,"line":1416},30,[40,1418,97],{"class":74},[40,1420,1421],{"class":100}," route",[40,1423,104],{"class":74},[40,1425,1426],{"class":54}," useRoute",[40,1428,1429],{"class":46},"()\n",[40,1431,1433,1435,1438,1440,1443],{"class":42,"line":1432},31,[40,1434,97],{"class":74},[40,1436,1437],{"class":100}," router",[40,1439,104],{"class":74},[40,1441,1442],{"class":54}," useRouter",[40,1444,1429],{"class":46},[40,1446,1448,1450,1453,1455,1458,1461,1464,1467,1470,1473],{"class":42,"line":1447},32,[40,1449,97],{"class":74},[40,1451,1452],{"class":100}," animationName",[40,1454,104],{"class":74},[40,1456,1457],{"class":54}," computed",[40,1459,1460],{"class":46},"(() ",[40,1462,1463],{"class":74},"=>",[40,1465,1466],{"class":46}," route.params.name ",[40,1468,1469],{"class":74},"as",[40,1471,1472],{"class":100}," string",[40,1474,116],{"class":46},[40,1476,1478,1480,1483,1485,1488],{"class":42,"line":1477},33,[40,1479,97],{"class":74},[40,1481,1482],{"class":100}," component",[40,1484,104],{"class":74},[40,1486,1487],{"class":54}," defineAsyncComponent",[40,1489,1490],{"class":46},"({\n",[40,1492,1494,1497,1500,1502,1505,1507,1510,1513,1516,1519,1522],{"class":42,"line":1493},34,[40,1495,1496],{"class":54},"  loader",[40,1498,1499],{"class":46},": () ",[40,1501,1463],{"class":74},[40,1503,1504],{"class":74}," import",[40,1506,110],{"class":46},[40,1508,1509],{"class":64},"`~\u002Fcomponents\u002Fanimations\u002F${",[40,1511,1512],{"class":46},"animationName",[40,1514,1515],{"class":64},".",[40,1517,1518],{"class":46},"value",[40,1520,1521],{"class":64},"}.vue`",[40,1523,1524],{"class":46},"),\n",[40,1526,1528,1531,1533,1535],{"class":42,"line":1527},35,[40,1529,1530],{"class":54},"  onError",[40,1532,1499],{"class":46},[40,1534,1463],{"class":74},[40,1536,1537],{"class":46}," {\n",[40,1539,1541,1544,1547,1549,1552,1554,1556,1558,1561],{"class":42,"line":1540},36,[40,1542,1543],{"class":46},"    console.",[40,1545,1546],{"class":54},"warn",[40,1548,110],{"class":46},[40,1550,1551],{"class":64},"`动画组件 ${",[40,1553,1512],{"class":46},[40,1555,1515],{"class":64},[40,1557,1518],{"class":46},[40,1559,1560],{"class":64},"} 不存在，重定向到 fade`",[40,1562,116],{"class":46},[40,1564,1566,1569,1571,1574,1577,1580],{"class":42,"line":1565},37,[40,1567,1568],{"class":54},"    navigateTo",[40,1570,110],{"class":46},[40,1572,1573],{"class":64},"'\u002Fanimation\u002Ffade'",[40,1575,1576],{"class":46},", { replace: ",[40,1578,1579],{"class":100},"true",[40,1581,1582],{"class":46}," })\n",[40,1584,1586],{"class":42,"line":1585},38,[40,1587,1588],{"class":46},"  }\n",[40,1590,1592],{"class":42,"line":1591},39,[40,1593,1594],{"class":46},"})\n",[40,1596,1598,1600,1603,1605,1607,1609,1612],{"class":42,"line":1597},40,[40,1599,97],{"class":74},[40,1601,1602],{"class":100}," componentKey",[40,1604,104],{"class":74},[40,1606,237],{"class":54},[40,1608,110],{"class":46},[40,1610,1611],{"class":100},"0",[40,1613,116],{"class":46},[40,1615,1617,1619,1622,1624,1626,1628,1631,1633,1636,1638,1641],{"class":42,"line":1616},41,[40,1618,97],{"class":74},[40,1620,1621],{"class":100}," animationModules",[40,1623,104],{"class":74},[40,1625,1504],{"class":74},[40,1627,1515],{"class":46},[40,1629,1630],{"class":100},"meta",[40,1632,1515],{"class":46},[40,1634,1635],{"class":54},"glob",[40,1637,110],{"class":46},[40,1639,1640],{"class":64},"'~\u002Fcomponents\u002Fanimations\u002F*.vue'",[40,1642,116],{"class":46},[40,1644,1646,1648,1650,1652,1654,1656,1658],{"class":42,"line":1645},42,[40,1647,97],{"class":74},[40,1649,1242],{"class":100},[40,1651,104],{"class":74},[40,1653,1457],{"class":54},[40,1655,1460],{"class":46},[40,1657,1463],{"class":74},[40,1659,1537],{"class":46},[40,1661,1663,1666,1669,1672,1675,1678,1681,1685,1688,1690],{"class":42,"line":1662},43,[40,1664,1665],{"class":74},"  return",[40,1667,1668],{"class":46}," Object.",[40,1670,1671],{"class":54},"keys",[40,1673,1674],{"class":46},"(animationModules).",[40,1676,1677],{"class":54},"map",[40,1679,1680],{"class":46},"((",[40,1682,1684],{"class":1683},"s4XuR","path",[40,1686,1687],{"class":46},") ",[40,1689,1463],{"class":74},[40,1691,1537],{"class":46},[40,1693,1695,1698,1701,1703,1706,1709,1711,1714,1717,1720,1723,1726],{"class":42,"line":1694},44,[40,1696,1697],{"class":74},"    const",[40,1699,1700],{"class":100}," fileName",[40,1702,104],{"class":74},[40,1704,1705],{"class":46}," path.",[40,1707,1708],{"class":54},"split",[40,1710,110],{"class":46},[40,1712,1713],{"class":64},"'\u002F'",[40,1715,1716],{"class":46},").",[40,1718,1719],{"class":54},"pop",[40,1721,1722],{"class":46},"() ",[40,1724,1725],{"class":74},"||",[40,1727,1728],{"class":64}," ''\n",[40,1730,1732,1735,1738,1741,1743,1746,1749,1752],{"class":42,"line":1731},45,[40,1733,1734],{"class":74},"    return",[40,1736,1737],{"class":46}," fileName.",[40,1739,1740],{"class":54},"replace",[40,1742,110],{"class":46},[40,1744,1745],{"class":64},"'.vue'",[40,1747,1748],{"class":46},", ",[40,1750,1751],{"class":64},"''",[40,1753,116],{"class":46},[40,1755,1757],{"class":42,"line":1756},46,[40,1758,1759],{"class":46},"  })\n",[40,1761,1763],{"class":42,"line":1762},47,[40,1764,1594],{"class":46},[40,1766,1768,1771,1773,1775],{"class":42,"line":1767},48,[40,1769,1770],{"class":54},"onMounted",[40,1772,1460],{"class":46},[40,1774,1463],{"class":74},[40,1776,1537],{"class":46},[40,1778,1780,1783,1786,1789,1792,1795],{"class":42,"line":1779},49,[40,1781,1782],{"class":74},"  if",[40,1784,1785],{"class":46}," (",[40,1787,1788],{"class":74},"!",[40,1790,1791],{"class":46},"availableAnimations.value.",[40,1793,1794],{"class":54},"includes",[40,1796,1797],{"class":46},"(animationName.value)) {\n",[40,1799,1801,1803,1805,1808,1811,1813,1815,1818,1820,1823,1825,1828,1830,1832],{"class":42,"line":1800},50,[40,1802,1568],{"class":54},[40,1804,110],{"class":46},[40,1806,1807],{"class":64},"`\u002Fanimation\u002F${",[40,1809,1810],{"class":46},"availableAnimations",[40,1812,1515],{"class":64},[40,1814,1518],{"class":46},[40,1816,1817],{"class":64},"[",[40,1819,1611],{"class":100},[40,1821,1822],{"class":64},"] ",[40,1824,1725],{"class":74},[40,1826,1827],{"class":64}," 'fade'}`",[40,1829,1576],{"class":46},[40,1831,1579],{"class":100},[40,1833,1582],{"class":46},[40,1835,1837],{"class":42,"line":1836},51,[40,1838,1588],{"class":46},[40,1840,1842],{"class":42,"line":1841},52,[40,1843,1594],{"class":46},[40,1845,1847,1849,1852,1854,1857,1859],{"class":42,"line":1846},53,[40,1848,97],{"class":74},[40,1850,1851],{"class":54}," replay",[40,1853,104],{"class":74},[40,1855,1856],{"class":46}," () ",[40,1858,1463],{"class":74},[40,1860,1537],{"class":46},[40,1862,1864,1867],{"class":42,"line":1863},54,[40,1865,1866],{"class":46},"  componentKey.value",[40,1868,1869],{"class":74},"++\n",[40,1871,1873],{"class":42,"line":1872},55,[40,1874,867],{"class":46},[40,1876,1878,1880,1882],{"class":42,"line":1877},56,[40,1879,122],{"class":46},[40,1881,51],{"class":50},[40,1883,68],{"class":46},[10,1885,1886,1887,1890],{},"我们就是通过 ",[14,1888,1889],{},"const animationName = computed(() => route.params.name as string)"," 来获取到的名称，通过nuxt提供的组合式函数返回当前路由的信息对象。用computed来创建响应式变量，当变化的时候自动更新。",[10,1892,1893],{},"最关键的地方在动态导入部分：",[31,1895,1899],{"className":1896,"code":1897,"language":1898,"meta":36,"style":36},"language-ts shiki shiki-themes github-light github-dark","const component = defineAsyncComponent({\n  loader: () => import(`~\u002Fcomponents\u002Fanimations\u002F${animationName.value}.vue`),\n  onError: () => {\n    console.warn(`动画组件 ${animationName.value} 不存在，重定向到 fade`)\n    navigateTo('\u002Fanimation\u002Ffade', { replace: true })\n  }\n})\n","ts",[14,1900,1901,1913,1938,1949,1970,1985,1990],{"__ignoreMap":36},[40,1902,1903,1905,1907,1909,1911],{"class":42,"line":43},[40,1904,97],{"class":74},[40,1906,1482],{"class":100},[40,1908,104],{"class":74},[40,1910,1487],{"class":54},[40,1912,1490],{"class":46},[40,1914,1915,1918,1920,1922,1924,1926,1928,1930,1932,1934,1936],{"class":42,"line":71},[40,1916,1917],{"class":54},"  loader",[40,1919,1499],{"class":46},[40,1921,1463],{"class":74},[40,1923,1504],{"class":74},[40,1925,110],{"class":46},[40,1927,1509],{"class":64},[40,1929,1512],{"class":46},[40,1931,1515],{"class":64},[40,1933,1518],{"class":46},[40,1935,1521],{"class":64},[40,1937,1524],{"class":46},[40,1939,1940,1943,1945,1947],{"class":42,"line":87},[40,1941,1942],{"class":54},"  onError",[40,1944,1499],{"class":46},[40,1946,1463],{"class":74},[40,1948,1537],{"class":46},[40,1950,1951,1954,1956,1958,1960,1962,1964,1966,1968],{"class":42,"line":94},[40,1952,1953],{"class":46},"    console.",[40,1955,1546],{"class":54},[40,1957,110],{"class":46},[40,1959,1551],{"class":64},[40,1961,1512],{"class":46},[40,1963,1515],{"class":64},[40,1965,1518],{"class":46},[40,1967,1560],{"class":64},[40,1969,116],{"class":46},[40,1971,1972,1975,1977,1979,1981,1983],{"class":42,"line":119},[40,1973,1974],{"class":54},"    navigateTo",[40,1976,110],{"class":46},[40,1978,1573],{"class":64},[40,1980,1576],{"class":46},[40,1982,1579],{"class":100},[40,1984,1582],{"class":46},[40,1986,1987],{"class":42,"line":129},[40,1988,1989],{"class":46},"  }\n",[40,1991,1992],{"class":42,"line":134},[40,1993,1594],{"class":46},[10,1995,1996,1997,2000,2001,661],{},"这里我们使用了一个vue的一个方法，定义一个异步组件，它在运行时是懒加载的。参数可以是一个",[191,1998,1999],{},"异步加载函数","，或是",[191,2002,2003],{},"对加载行为进行更具体定制的一个选项对象",[31,2005,2007],{"className":1896,"code":2006,"language":1898,"meta":36,"style":36},"function defineAsyncComponent(\n  source: AsyncComponentLoader | AsyncComponentOptions\n): Component\n\ntype AsyncComponentLoader = () => Promise\u003CComponent>\n\ninterface AsyncComponentOptions {\n  loader: AsyncComponentLoader\n  loadingComponent?: Component\n  errorComponent?: Component\n  delay?: number\n  timeout?: number\n  suspensible?: boolean\n  onError?: (\n    error: Error,\n    retry: () => void,\n    fail: () => void,\n    attempts: number\n  ) => any\n}\n",[14,2008,2009,2018,2035,2045,2049,2072,2076,2086,2095,2105,2114,2124,2133,2143,2152,2165,2181,2196,2205,2215],{"__ignoreMap":36},[40,2010,2011,2013,2015],{"class":42,"line":43},[40,2012,840],{"class":74},[40,2014,1487],{"class":54},[40,2016,2017],{"class":46},"(\n",[40,2019,2020,2023,2026,2029,2032],{"class":42,"line":71},[40,2021,2022],{"class":1683},"  source",[40,2024,2025],{"class":74},":",[40,2027,2028],{"class":54}," AsyncComponentLoader",[40,2030,2031],{"class":74}," |",[40,2033,2034],{"class":54}," AsyncComponentOptions\n",[40,2036,2037,2040,2042],{"class":42,"line":87},[40,2038,2039],{"class":46},")",[40,2041,2025],{"class":74},[40,2043,2044],{"class":54}," Component\n",[40,2046,2047],{"class":42,"line":94},[40,2048,91],{"emptyLinePlaceholder":90},[40,2050,2051,2054,2056,2058,2060,2062,2065,2067,2070],{"class":42,"line":119},[40,2052,2053],{"class":74},"type",[40,2055,2028],{"class":54},[40,2057,104],{"class":74},[40,2059,1856],{"class":46},[40,2061,1463],{"class":74},[40,2063,2064],{"class":54}," Promise",[40,2066,47],{"class":46},[40,2068,2069],{"class":54},"Component",[40,2071,68],{"class":46},[40,2073,2074],{"class":42,"line":129},[40,2075,91],{"emptyLinePlaceholder":90},[40,2077,2078,2081,2084],{"class":42,"line":134},[40,2079,2080],{"class":74},"interface",[40,2082,2083],{"class":54}," AsyncComponentOptions",[40,2085,1537],{"class":46},[40,2087,2088,2090,2092],{"class":42,"line":144},[40,2089,1917],{"class":1683},[40,2091,2025],{"class":74},[40,2093,2094],{"class":54}," AsyncComponentLoader\n",[40,2096,2097,2100,2103],{"class":42,"line":164},[40,2098,2099],{"class":1683},"  loadingComponent",[40,2101,2102],{"class":74},"?:",[40,2104,2044],{"class":54},[40,2106,2107,2110,2112],{"class":42,"line":180},[40,2108,2109],{"class":1683},"  errorComponent",[40,2111,2102],{"class":74},[40,2113,2044],{"class":54},[40,2115,2116,2119,2121],{"class":42,"line":351},[40,2117,2118],{"class":1683},"  delay",[40,2120,2102],{"class":74},[40,2122,2123],{"class":100}," number\n",[40,2125,2126,2129,2131],{"class":42,"line":870},[40,2127,2128],{"class":1683},"  timeout",[40,2130,2102],{"class":74},[40,2132,2123],{"class":100},[40,2134,2135,2138,2140],{"class":42,"line":1226},[40,2136,2137],{"class":1683},"  suspensible",[40,2139,2102],{"class":74},[40,2141,2142],{"class":100}," boolean\n",[40,2144,2145,2147,2149],{"class":42,"line":1248},[40,2146,1942],{"class":54},[40,2148,2102],{"class":74},[40,2150,2151],{"class":46}," (\n",[40,2153,2154,2157,2159,2162],{"class":42,"line":1266},[40,2155,2156],{"class":1683},"    error",[40,2158,2025],{"class":74},[40,2160,2161],{"class":54}," Error",[40,2163,2164],{"class":46},",\n",[40,2166,2167,2170,2172,2174,2176,2179],{"class":42,"line":1284},[40,2168,2169],{"class":54},"    retry",[40,2171,2025],{"class":74},[40,2173,1856],{"class":46},[40,2175,1463],{"class":74},[40,2177,2178],{"class":100}," void",[40,2180,2164],{"class":46},[40,2182,2183,2186,2188,2190,2192,2194],{"class":42,"line":1295},[40,2184,2185],{"class":54},"    fail",[40,2187,2025],{"class":74},[40,2189,1856],{"class":46},[40,2191,1463],{"class":74},[40,2193,2178],{"class":100},[40,2195,2164],{"class":46},[40,2197,2198,2201,2203],{"class":42,"line":1307},[40,2199,2200],{"class":1683},"    attempts",[40,2202,2025],{"class":74},[40,2204,2123],{"class":100},[40,2206,2207,2210,2212],{"class":42,"line":1319},[40,2208,2209],{"class":46},"  ) ",[40,2211,1463],{"class":74},[40,2213,2214],{"class":100}," any\n",[40,2216,2217],{"class":42,"line":1328},[40,2218,867],{"class":46},[10,2220,2221,2222,2225,2226,2229,2230,2233,2234,2237],{},"当我们选中了一个组件的时候，我们就会动态导入对应的vue组件进去，并且还包含了错误处理。通过这种动态拼接模板字符串的方式，我们就可以成功处理下来。",[191,2223,2224],{},"Vite 的处理","：\nVite 在构建时会扫描代码中的 ",[14,2227,2228],{},"import()"," 语句，发现这里是动态拼接的，",[191,2231,2232],{},"不会在编译时确定具体文件","，而是生成一个",[191,2235,2236],{},"动态 chunk","，在运行时根据实际路径去加载对应的文件",[10,2239,2240],{},"这里有一个强制重播的key：",[31,2242,2244],{"className":1896,"code":2243,"language":1898,"meta":36,"style":36},"const componentKey = ref(0)\n\nconst replay = () => {\n  componentKey.value++\n}\n",[14,2245,2246,2262,2266,2280,2287],{"__ignoreMap":36},[40,2247,2248,2250,2252,2254,2256,2258,2260],{"class":42,"line":43},[40,2249,97],{"class":74},[40,2251,1602],{"class":100},[40,2253,104],{"class":74},[40,2255,237],{"class":54},[40,2257,110],{"class":46},[40,2259,1611],{"class":100},[40,2261,116],{"class":46},[40,2263,2264],{"class":42,"line":71},[40,2265,91],{"emptyLinePlaceholder":90},[40,2267,2268,2270,2272,2274,2276,2278],{"class":42,"line":87},[40,2269,97],{"class":74},[40,2271,1851],{"class":54},[40,2273,104],{"class":74},[40,2275,1856],{"class":46},[40,2277,1463],{"class":74},[40,2279,1537],{"class":46},[40,2281,2282,2285],{"class":42,"line":94},[40,2283,2284],{"class":46},"  componentKey.value",[40,2286,1869],{"class":74},[40,2288,2289],{"class":42,"line":119},[40,2290,867],{"class":46},[10,2292,2293,2294,2297],{},"在模板中使用了 ",[14,2295,2296],{},":key=\"componentKey\"","：",[31,2299,2301],{"className":33,"code":2300,"language":35,"meta":36,"style":36},"\u003Ccomponent :is=\"component\" :key=\"componentKey\" \u002F>\n",[14,2302,2303],{"__ignoreMap":36},[40,2304,2305,2307,2309,2311,2313,2315,2317,2319,2321,2323,2325,2327,2329,2332,2334],{"class":42,"line":43},[40,2306,47],{"class":46},[40,2308,150],{"class":50},[40,2310,703],{"class":46},[40,2312,28],{"class":54},[40,2314,61],{"class":46},[40,2316,303],{"class":64},[40,2318,150],{"class":46},[40,2320,303],{"class":64},[40,2322,703],{"class":46},[40,2324,1254],{"class":54},[40,2326,61],{"class":46},[40,2328,303],{"class":64},[40,2330,2331],{"class":46},"componentKey",[40,2333,303],{"class":64},[40,2335,161],{"class":46},[10,2337,2338,2297],{},[191,2339,2340,2341,2343],{},"Vue 的 ",[14,2342,1254],{}," 机制",[2345,2346,2347,2358],"ul",{},[2348,2349,2350,2351,2353,2354,2357],"li",{},"当 ",[14,2352,1254],{}," 不变时，Vue 会",[191,2355,2356],{},"复用","已有的组件实例。",[2348,2359,2350,2360,2362,2363,2366,2367,661],{},[14,2361,1254],{}," 变化时，Vue 会",[191,2364,2365],{},"销毁旧实例","并",[191,2368,2369],{},"创建新实例",[10,2371,2372,2373,2376],{},"调用 ",[14,2374,2375],{},"replay()"," 时：",[2345,2378,2379,2384],{},[2348,2380,2381,2383],{},[14,2382,2331],{}," 从 0 → 1 → 2 → ...",[2348,2385,2386,2387,2390],{},"Vue 认为这是一个全新的组件，",[191,2388,2389],{},"重新挂载","，动画重新播放。",[10,2392,2393],{},"我们这里还进行了自动扫描可用的动画：",[31,2395,2397],{"className":1896,"code":2396,"language":1898,"meta":36,"style":36},"const animationModules = import.meta.glob('~\u002Fcomponents\u002Fanimations\u002F*.vue')\n",[14,2398,2399],{"__ignoreMap":36},[40,2400,2401,2403,2405,2407,2409,2411,2413,2415,2417,2419,2421],{"class":42,"line":43},[40,2402,97],{"class":74},[40,2404,1621],{"class":100},[40,2406,104],{"class":74},[40,2408,1504],{"class":74},[40,2410,1515],{"class":46},[40,2412,1630],{"class":100},[40,2414,1515],{"class":46},[40,2416,1635],{"class":54},[40,2418,110],{"class":46},[40,2420,1640],{"class":64},[40,2422,116],{"class":46},[10,2424,2425,2428,2429,2432,2433,2436,2437,2440,2441,2444,2445,2448,2449,2452,2453,2456],{},[14,2426,2427],{},"import.meta.glob","这是 ",[191,2430,2431],{},"Vite 独有的编译时功能","，不是 Node.js 或浏览器 API。 ",[191,2434,2435],{},"编译时","（",[14,2438,2439],{},"pnpm dev"," 或 ",[14,2442,2443],{},"pnpm build"," 时），Vite 扫描 ",[14,2446,2447],{},"~\u002Fcomponents\u002Fanimations\u002F*.vue"," 这个路径模式。1. 找到所有匹配的文件，生成一个",[191,2450,2451],{},"映射对象","， 这个对象在运行时可以直接使用。\n",[191,2454,2455],{},"编译后生成的对象","（伪代码）：",[31,2458,2462],{"className":2459,"code":2460,"language":2461,"meta":36,"style":36},"language-js shiki shiki-themes github-light github-dark","const animationModules = {\n  '\u002Fcomponents\u002Fanimations\u002Ffade.vue': () => import('\u002Fcomponents\u002Fanimations\u002Ffade.vue'),\n  '\u002Fcomponents\u002Fanimations\u002Fslide.vue': () => import('\u002Fcomponents\u002Fanimations\u002Fslide.vue'),\n  '\u002Fcomponents\u002Fanimations\u002Fbounce.vue': () => import('\u002Fcomponents\u002Fanimations\u002Fbounce.vue'),\n  '\u002Fcomponents\u002Fanimations\u002Frotate.vue': () => import('\u002Fcomponents\u002Fanimations\u002Frotate.vue'),\n  \u002F\u002F ... 所有匹配的文件\n}\n","js",[14,2463,2464,2474,2492,2510,2528,2546,2551],{"__ignoreMap":36},[40,2465,2466,2468,2470,2472],{"class":42,"line":43},[40,2467,97],{"class":74},[40,2469,1621],{"class":100},[40,2471,104],{"class":74},[40,2473,1537],{"class":46},[40,2475,2476,2479,2481,2483,2485,2487,2490],{"class":42,"line":71},[40,2477,2478],{"class":64},"  '\u002Fcomponents\u002Fanimations\u002Ffade.vue'",[40,2480,1499],{"class":46},[40,2482,1463],{"class":74},[40,2484,1504],{"class":74},[40,2486,110],{"class":46},[40,2488,2489],{"class":64},"'\u002Fcomponents\u002Fanimations\u002Ffade.vue'",[40,2491,1524],{"class":46},[40,2493,2494,2497,2499,2501,2503,2505,2508],{"class":42,"line":87},[40,2495,2496],{"class":64},"  '\u002Fcomponents\u002Fanimations\u002Fslide.vue'",[40,2498,1499],{"class":46},[40,2500,1463],{"class":74},[40,2502,1504],{"class":74},[40,2504,110],{"class":46},[40,2506,2507],{"class":64},"'\u002Fcomponents\u002Fanimations\u002Fslide.vue'",[40,2509,1524],{"class":46},[40,2511,2512,2515,2517,2519,2521,2523,2526],{"class":42,"line":94},[40,2513,2514],{"class":64},"  '\u002Fcomponents\u002Fanimations\u002Fbounce.vue'",[40,2516,1499],{"class":46},[40,2518,1463],{"class":74},[40,2520,1504],{"class":74},[40,2522,110],{"class":46},[40,2524,2525],{"class":64},"'\u002Fcomponents\u002Fanimations\u002Fbounce.vue'",[40,2527,1524],{"class":46},[40,2529,2530,2533,2535,2537,2539,2541,2544],{"class":42,"line":119},[40,2531,2532],{"class":64},"  '\u002Fcomponents\u002Fanimations\u002Frotate.vue'",[40,2534,1499],{"class":46},[40,2536,1463],{"class":74},[40,2538,1504],{"class":74},[40,2540,110],{"class":46},[40,2542,2543],{"class":64},"'\u002Fcomponents\u002Fanimations\u002Frotate.vue'",[40,2545,1524],{"class":46},[40,2547,2548],{"class":42,"line":129},[40,2549,2550],{"class":851},"  \u002F\u002F ... 所有匹配的文件\n",[40,2552,2553],{"class":42,"line":134},[40,2554,867],{"class":46},[2556,2557,2558],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":36,"searchDepth":71,"depth":71,"links":2560},[2561,2564],{"id":377,"depth":71,"text":377,"children":2562},[2563],{"id":940,"depth":87,"text":945},{"id":1073,"depth":71,"text":1073},"如果你想使用 Vue 的 \u003Ccomponent :is=\"someComputedComponent\"> 语法，你需要使用 Vue 提供的 resolveComponent 辅助函数，或者直接从 #components 导入组件并将其传递给 is 属性。","md",{},"\u002Fvue\u002Fnuxt\u002F动态组件",{"description":2565},"Vue\u002FNuxt\u002F动态组件","PPfkcxPiNTujPW1A747SvkROsb2ywYSNoMk0pzr_-PM",1791042467730]