Nuxt JS 刷新子页面时如何正常渲染父路由定义的head资源标签
问题根因
当前刷新时资源失效是两个结构问题叠加导致的:
- 直接在页面组件
dashboard.vue中写了<body>标签,违反Nuxt的DOM结构规范。客户端路由跳转时浏览器会自动修正非法的DOM嵌套,让head配置正常生效;但全量刷新触发服务端渲染时,非法结构会打断head聚合流程,导致父页面定义的link、script标签没有被收录到最终输出的HTML中。 - 所有静态资源用相对路径引用,不同路由深度下解析的绝对路径不一致,会进一步加剧资源加载失效的问题。
推荐实现方案
核心思路是把父路由的公共逻辑抽成专属路由布局,既满足资源作用域限制,又能从机制上保障所有场景下的head配置生效,完全规避之前提到的两类方案的局限:
步骤1:创建admin专属布局
在项目layouts/目录下新建admin.vue,把原dashboard.vue里的模板逻辑全部迁移过来,移除非法的<body>标签,将body的class配置、需要加载的公共样式与脚本全部放到布局的head配置中,同时把资源路径改为根路径形式避免解析错误:
<template> <div class="wrapper"> <admin-navbar></admin-navbar> <main-sidebar></main-sidebar> <div class="content-wrapper"> <!-- 布局内的页面出口用Nuxt内置的<Nuxt />组件 --> <Nuxt /> </div> </div> </template> <script> export default { head() { return { // Nuxt会自动将bodyAttrs配置应用到页面根body标签上 bodyAttrs: { class: 'hold-transition sidebar-mini layout-fixed' }, link: [ { rel: "stylesheet", href: "https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" }, { rel: 'stylesheet', href: '/adminPanel/plugins/fontawesome-free/css/all.min.css' }, ], script: [ { src: '/adminPanel/dist/js/adminlte.js', body: true }, { src: '/adminPanel/dist/js/demo.js', body: true }, { src: '/adminPanel/dist/js/pages/dashboard.js', body: true }, ] } } } </script>
注意:布局内的子组件出口必须用Nuxt内置的
<Nuxt />组件,不要用<NuxtChild>,否则会出现内容渲染错误。
步骤2:调整pages目录下的路由结构
移除原来嵌套作为父路由的dashboard.vue文件,把dashboard/目录下的子页面都放到pages/vendor/dashboard/路径下。每个属于该admin模块的页面,只需要在组件配置里声明使用刚才创建的admin布局,就会自动套用公共结构和加载对应的资源:
<script> export default { // 声明使用admin专属布局,只有配置了这一行的页面才会加载对应的资源 layout: 'admin', // 页面自身的业务逻辑... } </script>
方案特性
- 资源作用域完全符合需求:所有link、script配置只在声明使用admin布局的路由下生效,不会全局污染其他模块的页面
- 全场景生效:不管是客户端路由跳转,还是直接刷新任意子路由,Nuxt在服务端渲染阶段就会完整加载布局的head配置,输出完整的HTML资源,不会出现刷新失效的问题
- 零冗余维护:公共的资源配置只需要在布局中维护一次,所有子页面自动继承,不需要重复写配置
临时替代方案(不调整现有路由结构时使用)
如果不方便改动现有嵌套路由结构,可以把公共的head配置抽成独立的公共模块,避免重复写配置的冗余:
- 新建公共配置文件
utils/adminHeadConfig.js,导出所有需要统一加载的link、script配置 - 在
dashboard.vue和所有子页面的head配置中,直接引入这个公共配置即可。后续修改资源路径只需要改一次公共文件,不会出现分散维护的问题。
内容的提问来源于stack exchange,提问作者adeab
相关产品推荐
相关产品推荐

