[{"data":1,"prerenderedAt":1662},["ShallowReactive",2],{"docsNavigation":3,"blogNavigation":53,"/blog/asian-cuisine":95,"/blog/asian-cuisine-surround":1658},[4,38],{"title":5,"path":6,"stem":7,"children":8,"icon":37},"常用网站","/docs/getting-started","1.docs/1.getting-started/1.index",[9,12,17,22,27,32],{"title":10,"path":6,"stem":7,"icon":11},"区块链相关(前端)","i-lucide-box",{"title":13,"path":14,"stem":15,"icon":16},"图片压缩","/docs/getting-started/photo-compression","1.docs/1.getting-started/2.photo-compression","i-lucide-image",{"title":18,"path":19,"stem":20,"icon":21},"组件库","/docs/getting-started/component-library","1.docs/1.getting-started/3.component-library","i-lucide-puzzle",{"title":23,"path":24,"stem":25,"icon":26},"图表库","/docs/getting-started/charts","1.docs/1.getting-started/4.charts","i-lucide-bar-chart-3",{"title":28,"path":29,"stem":30,"icon":31},"CSS","/docs/getting-started/css","1.docs/1.getting-started/5.css","i-lucide-palette",{"title":33,"path":34,"stem":35,"icon":36},"调试测试工具","/docs/getting-started/test","1.docs/1.getting-started/6.test","i-lucide-bug",false,{"title":39,"path":40,"stem":41,"children":42,"page":37},"常用工具","/docs/essentials","1.docs/2.essentials",[43,48],{"title":44,"path":45,"stem":46,"icon":47},"uni-helper","/docs/essentials/uni-helper","1.docs/2.essentials/1.uni-helper","i-lucide-settings",{"title":49,"path":50,"stem":51,"icon":52},"工作流可视化库","/docs/essentials/workflow-libraries","1.docs/2.essentials/2.workflow-libraries","i-lucide-workflow",[54],{"title":55,"path":56,"stem":57,"children":58,"page":37},"Blog","/blog","3.blog",[59,63,67,71,75,79,83,87,91],{"title":60,"path":61,"stem":62},"Vue 3 中 \u003CTransition> 报错：组件根节点无法被动画化的解决方案","/blog/asian-cuisine","3.blog/1.asian-cuisine",{"title":64,"path":65,"stem":66},"使用 openapi-ts-request 自动生成 API 请求代码","/blog/apifox-api-generation","3.blog/2.apifox-api-generation",{"title":68,"path":69,"stem":70},"解决 uni.upload 多文件上传限制：使用 fetch + FormData 实现 H5 环境下的多文件上传","/blog/file-upload-issue-solution","3.blog/3.file-upload-issue-solution",{"title":72,"path":73,"stem":74},"Wangeditor中被div包裹的img标签被过滤问题解决方案","/blog/wangeditor-img-filter-issue","3.blog/4.wangeditor-img-filter-issue",{"title":76,"path":77,"stem":78},"Nuxt项目部署后报错 “Cannot load payload /_payload.json” 的修复","/blog/nuxt-payload-extraction","3.blog/5.nuxt-payload-extraction",{"title":80,"path":81,"stem":82},"Nuxt项目导入nuxt-echarts实现图表渲染","/blog/nuxt-echarts-implementation","3.blog/6.nuxt-echarts-implementation",{"title":84,"path":85,"stem":86},"Reown+Wagmi 在 UniApp+Vite 项目中的问题与解决方案","/blog/reown-wagmi-uniapp-issues","3.blog/7.reown-wagmi-uniapp-issues",{"title":88,"path":89,"stem":90},"数字滚动动画组件 - Vue 动画最佳实践","/blog/number-scroll-animation","3.blog/8.number-scroll-animation",{"title":92,"path":93,"stem":94},"新电脑安装 nvm 卡住？无需修改配置文件，一行命令完美解决！","/blog/nvm-install-solution","3.blog/9.nvm-install-solution",{"id":96,"title":60,"authors":97,"badge":102,"body":104,"date":1650,"description":1651,"extension":1652,"image":1653,"meta":1655,"navigation":210,"path":61,"seo":1656,"stem":62,"__hash__":1657},"posts/3.blog/1.asian-cuisine.md",[98],{"name":99,"avatar":100},"qibmz",{"src":101},"/image/avatar.avif",{"label":103},"work",{"type":105,"value":106,"toc":1633},"minimark",[107,121,126,132,167,175,179,184,187,320,324,330,463,467,474,666,670,677,681,689,823,827,838,1059,1063,1070,1281,1285,1292,1494,1498,1507,1534,1537,1541,1600,1609,1612,1623,1629],[108,109,110,111,115,116,120],"p",{},"在 Vue 3 开发中使用 ",[112,113,114],"code",{},"\u003CTransition>"," 组件实现动画效果时，很多开发者都会遇到一个常见警告：",[117,118,119],"strong",{},"“Transition 组件的直接子元素必须是单一的根 DOM 元素”","。本文将深入解析这个问题的原因、常见错误场景，并提供完整的解决方案。",[122,123,125],"h2",{"id":124},"一核心规则transition-组件的子元素要求","一、核心规则：Transition 组件的子元素要求",[108,127,128,129,131],{},"Vue 3 的 ",[112,130,114],{}," 组件对其直接子元素有明确限制，必须满足：",[133,134,135,154,157],"ul",{},[136,137,138,139,142,143,146,147,146,150,153],"li",{},"必须是 ",[117,140,141],{},"单一的根 DOM 元素","（即 ",[112,144,145],{},"\u003Cdiv>","、",[112,148,149],{},"\u003Cspan>",[112,151,152],{},"\u003Csection>"," 等真实 HTML 标签）；",[136,155,156],{},"不能是纯文本、注释、多个根节点；",[136,158,159,160,146,163,166],{},"不能是 ",[112,161,162],{},"\u003CTeleport>",[112,164,165],{},"\u003CKeepAlive>"," 等特殊内置组件。",[108,168,169,170,146,172,174],{},"💡 关键提醒：尽管 Vue 3 支持多根组件（Fragments），但 ",[112,171,114],{},[112,173,165],{}," 等动画 / 缓存相关组件并不兼容这种结构。",[122,176,178],{"id":177},"二常见错误场景及示例","二、常见错误场景及示例",[180,181,183],"h3",{"id":182},"场景-1组件模板只有纯文本无根元素","场景 1：组件模板只有纯文本（无根元素）",[108,185,186],{},"组件模板中直接写文本，没有任何 DOM 元素包裹，会触发警告：",[188,189,194],"pre",{"className":190,"code":191,"language":192,"meta":193,"style":193},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!-- ❌ 错误：无任何包裹元素，纯文本作为子元素 -->\n\n\u003Ctemplate>\n\n Hello, Vue 3 Transition!\n\n\u003C/template>\n\n\u003C!-- 对应的 Transition 使用方式（同样报错） -->\n\n\u003CTransition name=\"fade\">\n\n \u003CTextComponent /> \\\u003C!-- 该组件无DOM根元素 -->\n\n\u003C/Transition>\n","vue","",[112,195,196,205,212,226,231,238,243,253,258,264,269,295,300,306,311],{"__ignoreMap":193},[197,198,201],"span",{"class":199,"line":200},"line",1,[197,202,204],{"class":203},"sHwdD","\u003C!-- ❌ 错误：无任何包裹元素，纯文本作为子元素 -->\n",[197,206,208],{"class":199,"line":207},2,[197,209,211],{"emptyLinePlaceholder":210},true,"\n",[197,213,215,219,223],{"class":199,"line":214},3,[197,216,218],{"class":217},"sMK4o","\u003C",[197,220,222],{"class":221},"swJcz","template",[197,224,225],{"class":217},">\n",[197,227,229],{"class":199,"line":228},4,[197,230,211],{"emptyLinePlaceholder":210},[197,232,234],{"class":199,"line":233},5,[197,235,237],{"class":236},"sTEyZ"," Hello, Vue 3 Transition!\n",[197,239,241],{"class":199,"line":240},6,[197,242,211],{"emptyLinePlaceholder":210},[197,244,246,249,251],{"class":199,"line":245},7,[197,247,248],{"class":217},"\u003C/",[197,250,222],{"class":221},[197,252,225],{"class":217},[197,254,256],{"class":199,"line":255},8,[197,257,211],{"emptyLinePlaceholder":210},[197,259,261],{"class":199,"line":260},9,[197,262,263],{"class":203},"\u003C!-- 对应的 Transition 使用方式（同样报错） -->\n",[197,265,267],{"class":199,"line":266},10,[197,268,211],{"emptyLinePlaceholder":210},[197,270,272,274,277,281,284,287,291,293],{"class":199,"line":271},11,[197,273,218],{"class":217},[197,275,276],{"class":221},"Transition",[197,278,280],{"class":279},"spNyl"," name",[197,282,283],{"class":217},"=",[197,285,286],{"class":217},"\"",[197,288,290],{"class":289},"sfazB","fade",[197,292,286],{"class":217},[197,294,225],{"class":217},[197,296,298],{"class":199,"line":297},12,[197,299,211],{"emptyLinePlaceholder":210},[197,301,303],{"class":199,"line":302},13,[197,304,305],{"class":236}," \u003CTextComponent /> \\\u003C!-- 该组件无DOM根元素 -->\n",[197,307,309],{"class":199,"line":308},14,[197,310,211],{"emptyLinePlaceholder":210},[197,312,314,316,318],{"class":199,"line":313},15,[197,315,248],{"class":217},[197,317,276],{"class":221},[197,319,225],{"class":217},[180,321,323],{"id":322},"场景-2组件存在多个根节点fragments","场景 2：组件存在多个根节点（Fragments）",[108,325,326,327,329],{},"Vue 3 允许组件有多个根节点，但 ",[112,328,114],{}," 不支持这种结构：",[188,331,333],{"className":190,"code":332,"language":192,"meta":193,"style":193},"\u003C!-- ❌ 错误：多根节点（h1 和 p 并列，无外层包裹） -->\n\n\u003Ctemplate>\n\n \u003Ch1>Transition 动画演示\\\u003C/h1>\n\n \u003Cp>这是一个多根节点的组件\\\u003C/p>\n\n\u003C/template>\n\n\u003C!-- 对应的 Transition 使用方式（报错） -->\n\n\u003CTransition name=\"fade\">\n\n \u003CMultiRootComponent /> \u003C!-- 该组件有多个根节点 -->\n\n\u003C/Transition>\n",[112,334,335,340,344,352,356,376,380,397,401,409,413,418,422,440,444,449,454],{"__ignoreMap":193},[197,336,337],{"class":199,"line":200},[197,338,339],{"class":203},"\u003C!-- ❌ 错误：多根节点（h1 和 p 并列，无外层包裹） -->\n",[197,341,342],{"class":199,"line":207},[197,343,211],{"emptyLinePlaceholder":210},[197,345,346,348,350],{"class":199,"line":214},[197,347,218],{"class":217},[197,349,222],{"class":221},[197,351,225],{"class":217},[197,353,354],{"class":199,"line":228},[197,355,211],{"emptyLinePlaceholder":210},[197,357,358,361,364,367,370,372,374],{"class":199,"line":233},[197,359,360],{"class":217}," \u003C",[197,362,363],{"class":221},"h1",[197,365,366],{"class":217},">",[197,368,369],{"class":236},"Transition 动画演示\\",[197,371,248],{"class":217},[197,373,363],{"class":221},[197,375,225],{"class":217},[197,377,378],{"class":199,"line":240},[197,379,211],{"emptyLinePlaceholder":210},[197,381,382,384,386,388,391,393,395],{"class":199,"line":245},[197,383,360],{"class":217},[197,385,108],{"class":221},[197,387,366],{"class":217},[197,389,390],{"class":236},"这是一个多根节点的组件\\",[197,392,248],{"class":217},[197,394,108],{"class":221},[197,396,225],{"class":217},[197,398,399],{"class":199,"line":255},[197,400,211],{"emptyLinePlaceholder":210},[197,402,403,405,407],{"class":199,"line":260},[197,404,248],{"class":217},[197,406,222],{"class":221},[197,408,225],{"class":217},[197,410,411],{"class":199,"line":266},[197,412,211],{"emptyLinePlaceholder":210},[197,414,415],{"class":199,"line":271},[197,416,417],{"class":203},"\u003C!-- 对应的 Transition 使用方式（报错） -->\n",[197,419,420],{"class":199,"line":297},[197,421,211],{"emptyLinePlaceholder":210},[197,423,424,426,428,430,432,434,436,438],{"class":199,"line":302},[197,425,218],{"class":217},[197,427,276],{"class":221},[197,429,280],{"class":279},[197,431,283],{"class":217},[197,433,286],{"class":217},[197,435,290],{"class":289},[197,437,286],{"class":217},[197,439,225],{"class":217},[197,441,442],{"class":199,"line":308},[197,443,211],{"emptyLinePlaceholder":210},[197,445,446],{"class":199,"line":313},[197,447,448],{"class":236}," \u003CMultiRootComponent /> \u003C!-- 该组件有多个根节点 -->\n",[197,450,452],{"class":199,"line":451},16,[197,453,211],{"emptyLinePlaceholder":210},[197,455,457,459,461],{"class":199,"line":456},17,[197,458,248],{"class":217},[197,460,276],{"class":221},[197,462,225],{"class":217},[180,464,466],{"id":465},"场景-3动态组件未保证单一根节点","场景 3：动态组件未保证单一根节点",[108,468,469,470,473],{},"使用 ",[112,471,472],{},"\u003Ccomponent :is=\"...\">"," 切换组件时，如果某个候选组件不符合要求，会触发警告：",[188,475,477],{"className":190,"code":476,"language":192,"meta":193,"style":193},"\u003C!-- 父组件中使用动态组件 -->\n\n\u003CTransition name=\"fade\">\n\n \u003Ccomponent :is=\"currentView\" :key=\"currentView\" />\n\n\u003C/Transition>\n\n\u003C!-- 问题：若 currentView 对应的组件（如 About.vue）是多根节点，则报错 -->\n\n\u003C!-- About.vue（❌ 错误示例） -->\n\n\u003Ctemplate>\n\n \u003Ch2>关于我们\\\u003C/h2>\n\n \u003Cul>\n\n   \u003Cli>公司简介\\\u003C/li>\n\n   \u003Cli>联系我们\\\u003C/li>\n\n \u003C/ul>\n\n\u003C/template>\n",[112,478,479,484,488,506,510,515,519,527,531,536,540,545,549,557,561,578,582,590,595,614,619,637,642,652,657],{"__ignoreMap":193},[197,480,481],{"class":199,"line":200},[197,482,483],{"class":203},"\u003C!-- 父组件中使用动态组件 -->\n",[197,485,486],{"class":199,"line":207},[197,487,211],{"emptyLinePlaceholder":210},[197,489,490,492,494,496,498,500,502,504],{"class":199,"line":214},[197,491,218],{"class":217},[197,493,276],{"class":221},[197,495,280],{"class":279},[197,497,283],{"class":217},[197,499,286],{"class":217},[197,501,290],{"class":289},[197,503,286],{"class":217},[197,505,225],{"class":217},[197,507,508],{"class":199,"line":228},[197,509,211],{"emptyLinePlaceholder":210},[197,511,512],{"class":199,"line":233},[197,513,514],{"class":236}," \u003Ccomponent :is=\"currentView\" :key=\"currentView\" />\n",[197,516,517],{"class":199,"line":240},[197,518,211],{"emptyLinePlaceholder":210},[197,520,521,523,525],{"class":199,"line":245},[197,522,248],{"class":217},[197,524,276],{"class":221},[197,526,225],{"class":217},[197,528,529],{"class":199,"line":255},[197,530,211],{"emptyLinePlaceholder":210},[197,532,533],{"class":199,"line":260},[197,534,535],{"class":203},"\u003C!-- 问题：若 currentView 对应的组件（如 About.vue）是多根节点，则报错 -->\n",[197,537,538],{"class":199,"line":266},[197,539,211],{"emptyLinePlaceholder":210},[197,541,542],{"class":199,"line":271},[197,543,544],{"class":203},"\u003C!-- About.vue（❌ 错误示例） -->\n",[197,546,547],{"class":199,"line":297},[197,548,211],{"emptyLinePlaceholder":210},[197,550,551,553,555],{"class":199,"line":302},[197,552,218],{"class":217},[197,554,222],{"class":221},[197,556,225],{"class":217},[197,558,559],{"class":199,"line":308},[197,560,211],{"emptyLinePlaceholder":210},[197,562,563,565,567,569,572,574,576],{"class":199,"line":313},[197,564,360],{"class":217},[197,566,122],{"class":221},[197,568,366],{"class":217},[197,570,571],{"class":236},"关于我们\\",[197,573,248],{"class":217},[197,575,122],{"class":221},[197,577,225],{"class":217},[197,579,580],{"class":199,"line":451},[197,581,211],{"emptyLinePlaceholder":210},[197,583,584,586,588],{"class":199,"line":456},[197,585,360],{"class":217},[197,587,133],{"class":221},[197,589,225],{"class":217},[197,591,593],{"class":199,"line":592},18,[197,594,211],{"emptyLinePlaceholder":210},[197,596,598,601,603,605,608,610,612],{"class":199,"line":597},19,[197,599,600],{"class":217},"   \u003C",[197,602,136],{"class":221},[197,604,366],{"class":217},[197,606,607],{"class":236},"公司简介\\",[197,609,248],{"class":217},[197,611,136],{"class":221},[197,613,225],{"class":217},[197,615,617],{"class":199,"line":616},20,[197,618,211],{"emptyLinePlaceholder":210},[197,620,622,624,626,628,631,633,635],{"class":199,"line":621},21,[197,623,600],{"class":217},[197,625,136],{"class":221},[197,627,366],{"class":217},[197,629,630],{"class":236},"联系我们\\",[197,632,248],{"class":217},[197,634,136],{"class":221},[197,636,225],{"class":217},[197,638,640],{"class":199,"line":639},22,[197,641,211],{"emptyLinePlaceholder":210},[197,643,645,648,650],{"class":199,"line":644},23,[197,646,647],{"class":217}," \u003C/",[197,649,133],{"class":221},[197,651,225],{"class":217},[197,653,655],{"class":199,"line":654},24,[197,656,211],{"emptyLinePlaceholder":210},[197,658,660,662,664],{"class":199,"line":659},25,[197,661,248],{"class":217},[197,663,222],{"class":221},[197,665,225],{"class":217},[122,667,669],{"id":668},"三解决方案确保单一根-dom-元素","三、解决方案：确保单一根 DOM 元素",[108,671,672,673,676],{},"解决思路非常简单：",[117,674,675],{},"给组件模板添加一个外层包裹元素","，将多根节点、纯文本等统一包裹为单一的根 DOM 元素。",[180,678,680],{"id":679},"方案-1修复纯文本问题","方案 1：修复纯文本问题",[108,682,683,684,146,686,688],{},"用 ",[112,685,149],{},[112,687,145],{}," 等行内 / 块级元素包裹纯文本：",[188,690,692],{"className":190,"code":691,"language":192,"meta":193,"style":193},"\u003C!-- ✅ 正确：用 span 包裹纯文本（适合行内内容） -->\n\n\u003Ctemplate>\n\n \u003Cspan>Hello, Vue 3 Transition!\\\u003C/span>\n\n\u003C/template>\n\n\u003C!-- 或用 div 包裹（适合块级内容） -->\n\n\u003Ctemplate>\n\n \u003Cdiv class=\"text-container\">\n\n   Hello, Vue 3 Transition!\n\n \u003C/div>\n\n\u003C/template>\n",[112,693,694,699,703,711,715,732,736,744,748,753,757,765,769,790,794,799,803,811,815],{"__ignoreMap":193},[197,695,696],{"class":199,"line":200},[197,697,698],{"class":203},"\u003C!-- ✅ 正确：用 span 包裹纯文本（适合行内内容） -->\n",[197,700,701],{"class":199,"line":207},[197,702,211],{"emptyLinePlaceholder":210},[197,704,705,707,709],{"class":199,"line":214},[197,706,218],{"class":217},[197,708,222],{"class":221},[197,710,225],{"class":217},[197,712,713],{"class":199,"line":228},[197,714,211],{"emptyLinePlaceholder":210},[197,716,717,719,721,723,726,728,730],{"class":199,"line":233},[197,718,360],{"class":217},[197,720,197],{"class":221},[197,722,366],{"class":217},[197,724,725],{"class":236},"Hello, Vue 3 Transition!\\",[197,727,248],{"class":217},[197,729,197],{"class":221},[197,731,225],{"class":217},[197,733,734],{"class":199,"line":240},[197,735,211],{"emptyLinePlaceholder":210},[197,737,738,740,742],{"class":199,"line":245},[197,739,248],{"class":217},[197,741,222],{"class":221},[197,743,225],{"class":217},[197,745,746],{"class":199,"line":255},[197,747,211],{"emptyLinePlaceholder":210},[197,749,750],{"class":199,"line":260},[197,751,752],{"class":203},"\u003C!-- 或用 div 包裹（适合块级内容） -->\n",[197,754,755],{"class":199,"line":266},[197,756,211],{"emptyLinePlaceholder":210},[197,758,759,761,763],{"class":199,"line":271},[197,760,218],{"class":217},[197,762,222],{"class":221},[197,764,225],{"class":217},[197,766,767],{"class":199,"line":297},[197,768,211],{"emptyLinePlaceholder":210},[197,770,771,773,776,779,781,783,786,788],{"class":199,"line":302},[197,772,360],{"class":217},[197,774,775],{"class":221},"div",[197,777,778],{"class":279}," class",[197,780,283],{"class":217},[197,782,286],{"class":217},[197,784,785],{"class":289},"text-container",[197,787,286],{"class":217},[197,789,225],{"class":217},[197,791,792],{"class":199,"line":308},[197,793,211],{"emptyLinePlaceholder":210},[197,795,796],{"class":199,"line":313},[197,797,798],{"class":236},"   Hello, Vue 3 Transition!\n",[197,800,801],{"class":199,"line":451},[197,802,211],{"emptyLinePlaceholder":210},[197,804,805,807,809],{"class":199,"line":456},[197,806,647],{"class":217},[197,808,775],{"class":221},[197,810,225],{"class":217},[197,812,813],{"class":199,"line":592},[197,814,211],{"emptyLinePlaceholder":210},[197,816,817,819,821],{"class":199,"line":597},[197,818,248],{"class":217},[197,820,222],{"class":221},[197,822,225],{"class":217},[180,824,826],{"id":825},"方案-2修复多根节点问题","方案 2：修复多根节点问题",[108,828,683,829,831,832,146,834,837],{},[112,830,145],{}," 或语义化标签（",[112,833,152],{},[112,835,836],{},"\u003Carticle>"," 等）包裹所有根节点：",[188,839,841],{"className":190,"code":840,"language":192,"meta":193,"style":193},"\u003C!-- ✅ 正确：用 div 包裹多根节点 -->\n\n\u003Ctemplate>\n\n \u003Cdiv class=\"component-container\">\n\n   \u003Ch1>Transition 动画演示\\\u003C/h1>\n\n   \u003Cp>这是一个修复后的单根节点组件\\\u003C/p>\n\n \u003C/div>\n\n\u003C/template>\n\n\u003C!-- 或使用语义化标签（推荐，提升可读性） -->\n\n\u003Ctemplate>\n\n \u003Csection class=\"component-section\">\n\n   \u003Ch1>Transition 动画演示\\\u003C/h1>\n\n   \u003Cp>这是一个修复后的单根节点组件\\\u003C/p>\n\n \u003C/section>\n\n\u003C/template>\n",[112,842,843,848,852,860,864,883,887,903,907,924,928,936,940,948,952,957,961,969,973,993,997,1013,1017,1033,1037,1045,1050],{"__ignoreMap":193},[197,844,845],{"class":199,"line":200},[197,846,847],{"class":203},"\u003C!-- ✅ 正确：用 div 包裹多根节点 -->\n",[197,849,850],{"class":199,"line":207},[197,851,211],{"emptyLinePlaceholder":210},[197,853,854,856,858],{"class":199,"line":214},[197,855,218],{"class":217},[197,857,222],{"class":221},[197,859,225],{"class":217},[197,861,862],{"class":199,"line":228},[197,863,211],{"emptyLinePlaceholder":210},[197,865,866,868,870,872,874,876,879,881],{"class":199,"line":233},[197,867,360],{"class":217},[197,869,775],{"class":221},[197,871,778],{"class":279},[197,873,283],{"class":217},[197,875,286],{"class":217},[197,877,878],{"class":289},"component-container",[197,880,286],{"class":217},[197,882,225],{"class":217},[197,884,885],{"class":199,"line":240},[197,886,211],{"emptyLinePlaceholder":210},[197,888,889,891,893,895,897,899,901],{"class":199,"line":245},[197,890,600],{"class":217},[197,892,363],{"class":221},[197,894,366],{"class":217},[197,896,369],{"class":236},[197,898,248],{"class":217},[197,900,363],{"class":221},[197,902,225],{"class":217},[197,904,905],{"class":199,"line":255},[197,906,211],{"emptyLinePlaceholder":210},[197,908,909,911,913,915,918,920,922],{"class":199,"line":260},[197,910,600],{"class":217},[197,912,108],{"class":221},[197,914,366],{"class":217},[197,916,917],{"class":236},"这是一个修复后的单根节点组件\\",[197,919,248],{"class":217},[197,921,108],{"class":221},[197,923,225],{"class":217},[197,925,926],{"class":199,"line":266},[197,927,211],{"emptyLinePlaceholder":210},[197,929,930,932,934],{"class":199,"line":271},[197,931,647],{"class":217},[197,933,775],{"class":221},[197,935,225],{"class":217},[197,937,938],{"class":199,"line":297},[197,939,211],{"emptyLinePlaceholder":210},[197,941,942,944,946],{"class":199,"line":302},[197,943,248],{"class":217},[197,945,222],{"class":221},[197,947,225],{"class":217},[197,949,950],{"class":199,"line":308},[197,951,211],{"emptyLinePlaceholder":210},[197,953,954],{"class":199,"line":313},[197,955,956],{"class":203},"\u003C!-- 或使用语义化标签（推荐，提升可读性） -->\n",[197,958,959],{"class":199,"line":451},[197,960,211],{"emptyLinePlaceholder":210},[197,962,963,965,967],{"class":199,"line":456},[197,964,218],{"class":217},[197,966,222],{"class":221},[197,968,225],{"class":217},[197,970,971],{"class":199,"line":592},[197,972,211],{"emptyLinePlaceholder":210},[197,974,975,977,980,982,984,986,989,991],{"class":199,"line":597},[197,976,360],{"class":217},[197,978,979],{"class":221},"section",[197,981,778],{"class":279},[197,983,283],{"class":217},[197,985,286],{"class":217},[197,987,988],{"class":289},"component-section",[197,990,286],{"class":217},[197,992,225],{"class":217},[197,994,995],{"class":199,"line":616},[197,996,211],{"emptyLinePlaceholder":210},[197,998,999,1001,1003,1005,1007,1009,1011],{"class":199,"line":621},[197,1000,600],{"class":217},[197,1002,363],{"class":221},[197,1004,366],{"class":217},[197,1006,369],{"class":236},[197,1008,248],{"class":217},[197,1010,363],{"class":221},[197,1012,225],{"class":217},[197,1014,1015],{"class":199,"line":639},[197,1016,211],{"emptyLinePlaceholder":210},[197,1018,1019,1021,1023,1025,1027,1029,1031],{"class":199,"line":644},[197,1020,600],{"class":217},[197,1022,108],{"class":221},[197,1024,366],{"class":217},[197,1026,917],{"class":236},[197,1028,248],{"class":217},[197,1030,108],{"class":221},[197,1032,225],{"class":217},[197,1034,1035],{"class":199,"line":654},[197,1036,211],{"emptyLinePlaceholder":210},[197,1038,1039,1041,1043],{"class":199,"line":659},[197,1040,647],{"class":217},[197,1042,979],{"class":221},[197,1044,225],{"class":217},[197,1046,1048],{"class":199,"line":1047},26,[197,1049,211],{"emptyLinePlaceholder":210},[197,1051,1053,1055,1057],{"class":199,"line":1052},27,[197,1054,248],{"class":217},[197,1056,222],{"class":221},[197,1058,225],{"class":217},[180,1060,1062],{"id":1061},"方案-3处理动态组件场景","方案 3：处理动态组件场景",[108,1064,1065,1066,1069],{},"确保所有可能被切换的组件（",[112,1067,1068],{},"currentView"," 对应的候选组件）都满足 “单一根 DOM 元素” 要求：",[188,1071,1073],{"className":190,"code":1072,"language":192,"meta":193,"style":193},"\u003C!-- 父组件：动态组件用法不变 -->\n\n\u003CTransition name=\"fade\">    \n\n \u003Ccomponent :is=\"currentView\" :key=\"currentView\" />\n\n\u003C/Transition>\n\n\u003C!-- 所有候选组件需修复为单根节点，例如 About.vue（✅ 正确示例） -->\n\n\u003Ctemplate>\n\n \u003Cdiv class=\"about-container\">\n\n   \u003Ch2>关于我们\\\u003C/h2>\n\n   \u003Cul>\n\n     \u003Cli>公司简介\u003C/li>\n\n     \u003Cli>联系我们\u003C/li>\n\n   \u003C/ul>\n\n \u003C/div>\n\n\u003C/template>\n",[112,1074,1075,1080,1084,1105,1109,1113,1117,1125,1129,1134,1138,1146,1150,1169,1173,1189,1193,1201,1205,1223,1227,1244,1248,1257,1261,1269,1273],{"__ignoreMap":193},[197,1076,1077],{"class":199,"line":200},[197,1078,1079],{"class":203},"\u003C!-- 父组件：动态组件用法不变 -->\n",[197,1081,1082],{"class":199,"line":207},[197,1083,211],{"emptyLinePlaceholder":210},[197,1085,1086,1088,1090,1092,1094,1096,1098,1100,1102],{"class":199,"line":214},[197,1087,218],{"class":217},[197,1089,276],{"class":221},[197,1091,280],{"class":279},[197,1093,283],{"class":217},[197,1095,286],{"class":217},[197,1097,290],{"class":289},[197,1099,286],{"class":217},[197,1101,366],{"class":217},[197,1103,1104],{"class":236},"    \n",[197,1106,1107],{"class":199,"line":228},[197,1108,211],{"emptyLinePlaceholder":210},[197,1110,1111],{"class":199,"line":233},[197,1112,514],{"class":236},[197,1114,1115],{"class":199,"line":240},[197,1116,211],{"emptyLinePlaceholder":210},[197,1118,1119,1121,1123],{"class":199,"line":245},[197,1120,248],{"class":217},[197,1122,276],{"class":221},[197,1124,225],{"class":217},[197,1126,1127],{"class":199,"line":255},[197,1128,211],{"emptyLinePlaceholder":210},[197,1130,1131],{"class":199,"line":260},[197,1132,1133],{"class":203},"\u003C!-- 所有候选组件需修复为单根节点，例如 About.vue（✅ 正确示例） -->\n",[197,1135,1136],{"class":199,"line":266},[197,1137,211],{"emptyLinePlaceholder":210},[197,1139,1140,1142,1144],{"class":199,"line":271},[197,1141,218],{"class":217},[197,1143,222],{"class":221},[197,1145,225],{"class":217},[197,1147,1148],{"class":199,"line":297},[197,1149,211],{"emptyLinePlaceholder":210},[197,1151,1152,1154,1156,1158,1160,1162,1165,1167],{"class":199,"line":302},[197,1153,360],{"class":217},[197,1155,775],{"class":221},[197,1157,778],{"class":279},[197,1159,283],{"class":217},[197,1161,286],{"class":217},[197,1163,1164],{"class":289},"about-container",[197,1166,286],{"class":217},[197,1168,225],{"class":217},[197,1170,1171],{"class":199,"line":308},[197,1172,211],{"emptyLinePlaceholder":210},[197,1174,1175,1177,1179,1181,1183,1185,1187],{"class":199,"line":313},[197,1176,600],{"class":217},[197,1178,122],{"class":221},[197,1180,366],{"class":217},[197,1182,571],{"class":236},[197,1184,248],{"class":217},[197,1186,122],{"class":221},[197,1188,225],{"class":217},[197,1190,1191],{"class":199,"line":451},[197,1192,211],{"emptyLinePlaceholder":210},[197,1194,1195,1197,1199],{"class":199,"line":456},[197,1196,600],{"class":217},[197,1198,133],{"class":221},[197,1200,225],{"class":217},[197,1202,1203],{"class":199,"line":592},[197,1204,211],{"emptyLinePlaceholder":210},[197,1206,1207,1210,1212,1214,1217,1219,1221],{"class":199,"line":597},[197,1208,1209],{"class":217},"     \u003C",[197,1211,136],{"class":221},[197,1213,366],{"class":217},[197,1215,1216],{"class":236},"公司简介",[197,1218,248],{"class":217},[197,1220,136],{"class":221},[197,1222,225],{"class":217},[197,1224,1225],{"class":199,"line":616},[197,1226,211],{"emptyLinePlaceholder":210},[197,1228,1229,1231,1233,1235,1238,1240,1242],{"class":199,"line":621},[197,1230,1209],{"class":217},[197,1232,136],{"class":221},[197,1234,366],{"class":217},[197,1236,1237],{"class":236},"联系我们",[197,1239,248],{"class":217},[197,1241,136],{"class":221},[197,1243,225],{"class":217},[197,1245,1246],{"class":199,"line":639},[197,1247,211],{"emptyLinePlaceholder":210},[197,1249,1250,1253,1255],{"class":199,"line":644},[197,1251,1252],{"class":217},"   \u003C/",[197,1254,133],{"class":221},[197,1256,225],{"class":217},[197,1258,1259],{"class":199,"line":654},[197,1260,211],{"emptyLinePlaceholder":210},[197,1262,1263,1265,1267],{"class":199,"line":659},[197,1264,647],{"class":217},[197,1266,775],{"class":221},[197,1268,225],{"class":217},[197,1270,1271],{"class":199,"line":1047},[197,1272,211],{"emptyLinePlaceholder":210},[197,1274,1275,1277,1279],{"class":199,"line":1052},[197,1276,248],{"class":217},[197,1278,222],{"class":221},[197,1280,225],{"class":217},[180,1282,1284],{"id":1283},"方案-4异步组件-函数式组件处理","方案 4：异步组件 / 函数式组件处理",[108,1286,1287,1288,1291],{},"即使是通过 ",[112,1289,1290],{},"defineAsyncComponent"," 加载的异步组件，或函数式组件，也需遵循同样规则：",[188,1293,1295],{"className":190,"code":1294,"language":192,"meta":193,"style":193},"\u003C!-- 异步组件示例（✅ 正确） -->\n\u003Cscript setup lang=\"ts\">\nimport { defineAsyncComponent } from 'vue';\n\nconst AsyncComponent = defineAsyncComponent(() =>\n\n import('./AsyncComponent.vue')\n\n);\n\u003C/script>\n\n\n\u003Ctemplate>\n  // AsyncComponent.vue 必须有单一根 DOM 元素\n \u003Cdiv class=\"async-container\">\n\n   这是一个异步组件，有单一根元素\n\n \u003C/div>\n\n\u003C/template>\n\n",[112,1296,1297,1302,1326,1355,1359,1381,1385,1402,1406,1413,1421,1425,1429,1437,1442,1461,1465,1470,1474,1482,1486],{"__ignoreMap":193},[197,1298,1299],{"class":199,"line":200},[197,1300,1301],{"class":203},"\u003C!-- 异步组件示例（✅ 正确） -->\n",[197,1303,1304,1306,1309,1312,1315,1317,1319,1322,1324],{"class":199,"line":207},[197,1305,218],{"class":217},[197,1307,1308],{"class":221},"script",[197,1310,1311],{"class":279}," setup",[197,1313,1314],{"class":279}," lang",[197,1316,283],{"class":217},[197,1318,286],{"class":217},[197,1320,1321],{"class":289},"ts",[197,1323,286],{"class":217},[197,1325,225],{"class":217},[197,1327,1328,1332,1335,1338,1341,1344,1347,1349,1352],{"class":199,"line":214},[197,1329,1331],{"class":1330},"s7zQu","import",[197,1333,1334],{"class":217}," {",[197,1336,1337],{"class":236}," defineAsyncComponent",[197,1339,1340],{"class":217}," }",[197,1342,1343],{"class":1330}," from",[197,1345,1346],{"class":217}," '",[197,1348,192],{"class":289},[197,1350,1351],{"class":217},"'",[197,1353,1354],{"class":217},";\n",[197,1356,1357],{"class":199,"line":228},[197,1358,211],{"emptyLinePlaceholder":210},[197,1360,1361,1364,1367,1369,1372,1375,1378],{"class":199,"line":233},[197,1362,1363],{"class":279},"const",[197,1365,1366],{"class":236}," AsyncComponent ",[197,1368,283],{"class":217},[197,1370,1337],{"class":1371},"s2Zo4",[197,1373,1374],{"class":236},"(",[197,1376,1377],{"class":217},"()",[197,1379,1380],{"class":279}," =>\n",[197,1382,1383],{"class":199,"line":240},[197,1384,211],{"emptyLinePlaceholder":210},[197,1386,1387,1390,1392,1394,1397,1399],{"class":199,"line":245},[197,1388,1389],{"class":217}," import",[197,1391,1374],{"class":236},[197,1393,1351],{"class":217},[197,1395,1396],{"class":289},"./AsyncComponent.vue",[197,1398,1351],{"class":217},[197,1400,1401],{"class":236},")\n",[197,1403,1404],{"class":199,"line":255},[197,1405,211],{"emptyLinePlaceholder":210},[197,1407,1408,1411],{"class":199,"line":260},[197,1409,1410],{"class":236},")",[197,1412,1354],{"class":217},[197,1414,1415,1417,1419],{"class":199,"line":266},[197,1416,248],{"class":217},[197,1418,1308],{"class":221},[197,1420,225],{"class":217},[197,1422,1423],{"class":199,"line":271},[197,1424,211],{"emptyLinePlaceholder":210},[197,1426,1427],{"class":199,"line":297},[197,1428,211],{"emptyLinePlaceholder":210},[197,1430,1431,1433,1435],{"class":199,"line":302},[197,1432,218],{"class":217},[197,1434,222],{"class":221},[197,1436,225],{"class":217},[197,1438,1439],{"class":199,"line":308},[197,1440,1441],{"class":236},"  // AsyncComponent.vue 必须有单一根 DOM 元素\n",[197,1443,1444,1446,1448,1450,1452,1454,1457,1459],{"class":199,"line":313},[197,1445,360],{"class":217},[197,1447,775],{"class":221},[197,1449,778],{"class":279},[197,1451,283],{"class":217},[197,1453,286],{"class":217},[197,1455,1456],{"class":289},"async-container",[197,1458,286],{"class":217},[197,1460,225],{"class":217},[197,1462,1463],{"class":199,"line":451},[197,1464,211],{"emptyLinePlaceholder":210},[197,1466,1467],{"class":199,"line":456},[197,1468,1469],{"class":236},"   这是一个异步组件，有单一根元素\n",[197,1471,1472],{"class":199,"line":592},[197,1473,211],{"emptyLinePlaceholder":210},[197,1475,1476,1478,1480],{"class":199,"line":597},[197,1477,647],{"class":217},[197,1479,775],{"class":221},[197,1481,225],{"class":217},[197,1483,1484],{"class":199,"line":616},[197,1485,211],{"emptyLinePlaceholder":210},[197,1487,1488,1490,1492],{"class":199,"line":621},[197,1489,248],{"class":217},[197,1491,222],{"class":221},[197,1493,225],{"class":217},[122,1495,1497],{"id":1496},"四为什么-vue-要做这样的限制","四、为什么 Vue 要做这样的限制？",[108,1499,1500,1502,1503,1506],{},[112,1501,114],{}," 组件的核心原理是 ",[117,1504,1505],{},"通过操作 DOM 元素的 CSS 类名和监听过渡事件实现动画","，具体依赖：",[1508,1509,1510,1523],"ol",{},[136,1511,1512,1513,146,1516,146,1519,1522],{},"向根 DOM 元素添加 / 移除过渡类名（如 ",[112,1514,1515],{},"v-enter-from",[112,1517,1518],{},"v-enter-active",[112,1520,1521],{},"v-leave-to"," 等）；",[136,1524,1525,1526,1529,1530,1533],{},"监听根 DOM 元素的 ",[112,1527,1528],{},"transitionend"," 或 ",[112,1531,1532],{},"animationend"," 事件，判断动画是否完成。",[108,1535,1536],{},"如果根节点不是真实 DOM 元素（如纯文本、Fragment），Vue 无法挂载这些类名，也无法监听过渡事件，最终导致动画失效，因此必须强制要求 “单一根 DOM 元素”。",[122,1538,1540],{"id":1539},"五总结问题与解决方案对照表","五、总结：问题与解决方案对照表",[1542,1543,1544,1557],"table",{},[1545,1546,1547],"thead",{},[1548,1549,1550,1554],"tr",{},[1551,1552,1553],"th",{},"常见问题",[1551,1555,1556],{},"解决方案",[1558,1559,1560,1574,1584,1592],"tbody",{},[1548,1561,1562,1566],{},[1563,1564,1565],"td",{},"组件模板只有纯文本",[1563,1567,683,1568,1570,1571,1573],{},[112,1569,149],{},"/",[112,1572,145],{}," 包裹文本",[1548,1575,1576,1579],{},[1563,1577,1578],{},"组件存在多个根节点",[1563,1580,683,1581,1583],{},[112,1582,145],{},"/ 语义化标签包裹所有节点",[1548,1585,1586,1589],{},[1563,1587,1588],{},"动态组件切换时报错",[1563,1590,1591],{},"确保所有候选组件均为单一根 DOM 元素",[1548,1593,1594,1597],{},[1563,1595,1596],{},"异步 / 函数式组件报错",[1563,1598,1599],{},"组件内部添加单一外层 DOM 包裹",[108,1601,1602,1603,1605,1608],{},"只要记住核心原则：",[112,1604,114],{},[117,1606,1607],{},"内部的直接子组件，必须有且仅有一个真实的 DOM 根元素","，就能彻底消除警告，让过渡动画正常工作。",[122,1610,1611],{"id":1611},"延伸阅读",[133,1613,1614],{},[136,1615,1616],{},[1617,1618,1622],"a",{"href":1619,"rel":1620},"https://cn.vuejs.org/guide/built-ins/transition.html",[1621],"nofollow","Vue 3 官方文档 - Transition 组件",[1624,1625,1626],"blockquote",{},[108,1627,1628],{},"（注：文档内容由 Copilot 生成）",[1630,1631,1632],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}",{"title":193,"searchDepth":207,"depth":207,"links":1634},[1635,1636,1641,1647,1648,1649],{"id":124,"depth":207,"text":125},{"id":177,"depth":207,"text":178,"children":1637},[1638,1639,1640],{"id":182,"depth":214,"text":183},{"id":322,"depth":214,"text":323},{"id":465,"depth":214,"text":466},{"id":668,"depth":207,"text":669,"children":1642},[1643,1644,1645,1646],{"id":679,"depth":214,"text":680},{"id":825,"depth":214,"text":826},{"id":1061,"depth":214,"text":1062},{"id":1283,"depth":214,"text":1284},{"id":1496,"depth":207,"text":1497},{"id":1539,"depth":207,"text":1540},{"id":1611,"depth":207,"text":1611},"2025-11-10T00:00:00.000Z","[Vue warn]: Component inside \u003CTransition> renders non-element root node that cannot be  （导致页面切换后无法渲染）","md",{"src":1654},"https://picsum.photos/id/199/640/360",{},{"title":60,"description":1651},"3WN8owhzdWo4pPZO0F9ZpVHM_kOheYWf4fBqWtD6g5I",[1659,1660],null,{"title":64,"path":65,"stem":66,"description":1661,"children":-1},"介绍如何根据 Apifox 文档自动生成类型安全的 API 请求文件，提高开发效率",1774239530071]