【问题标题】:Vue router: How to dynamically generate page titles for dynamic routes?Vue路由器:如何为动态路由动态生成页面标题?
【发布时间】:2021-05-21 23:42:57
【问题描述】:

我有一个使用 Vue CLI 创建的简单的基于 Vue 的网站,我正在尝试弄清楚如何为带有动态路由的视图动态生成页面标题。该站点正在从无头 CMS 中提取 JSON 数据,并且我为“项目”内容类型的详细视图设置了动态路由。我的动态路由设置如下:

// single project vue (dynamic)
{
    path: "/projects/:project_name_slug",
    name: "single-project",
    component: () =>
        import(
            /* webpackChunkName: "single-project" */ "./views/SingleProject.vue"
        ),
    meta: {
        title: "project detail",
    }
}

我添加了以下内容,适用于添加静态页面标题:

// show page titles
const DEFAULT_TITLE = "my blog";
router.afterEach((to, from) => {
    // document.title = to.meta.title || DEFAULT_TITLE;
    document.title = "my blog - " + to.meta.title || DEFAULT_TITLE;
});

就目前而言,在访问项目详细信息视图时,标题将显示为“我的博客 - 项目详细信息”;但是,我希望它从 project_name 的 JSON/字段数据中提取实际项目名称(就像路由路径使用 project_name_slug 一样),但到目前为止我没有尝试过任何工作。例如,使用meta: { title: (route) => route.params.project_name } 只会导致原始函数文本显示在“我的博客-”之后。因此,对于那些动态视图,我希望 to.meta.title 解析为项目名称,创建“我的博客 - {项目名称}”。感谢您在这里提供的任何帮助,如果我需要提供更多详细信息,请告诉我。

*注意:这个问题与this SO thread 中提出的问题不同,因为我的案例涉及使用通过 Axios 请求的 JSON 数据的动态路由

【问题讨论】:

  • 这能回答你的问题吗? How to manage page titles dynamically in Vuejs?
  • @KeithNicholas - 该链接使用静态元,这个问题是关于动态元(链接问题中的标题是动态的,但元不是)
  • 您的 JSON 数据在组件生命周期事件之前是否可用,或者您是否在创建组件后从 axios 请求中获取它?
  • @Ohgodwhy 我从 axios 请求中获取数据
  • @KeithNicholas 这是我查看的第一批帖子之一,但在我的情况下似乎没有动态路由

标签: vue.js vue-router vue-cli


【解决方案1】:

这是旧的,但如果它对任何人都有帮助,我刚刚遇到了这个问题,我发现一个组合使用 router.afterEach 用于静态标题与 mixin 用于动态标题。

在 OP 解释的情况下,我会从路由器和 afterEach 中的任何动态页面中删除 title 属性,只需检查 meta.title

router.afterEach(to => {
  if (to.meta.title) {
    document.title = `${to.meta.title} - my blog`;
  }
});

然后为其他页面创建一个简单的 mixin,例如:

export default {
  methods: {
    setTitle(str) {
        document.title = `${str} - my blog`
    }
  }
}

然后在这些动态页面中,您只需调用 this.setTitle() 并使用从服务器加载的任何动态数据。我知道这似乎太容易了,但它确实有效。你在 SO 上找到的所有 beforeEach 方法都遇到了问题。

注意:这不适用于 SEO 或网络爬虫(我推荐使用 prerenderSpa),但它确实为您提供了不错的标题、后退按钮历史记录和书签。

【讨论】:

    【解决方案2】:

    在路由器的beforeEach导航守卫中设置meta

    router.beforeEach((to, from, next) => {
      to.meta.title = to.params.project_name_slug;
      next();
    });
    

    -或-

    您可以使用beforeRouteEnterbeforeRouteUpdate in-component guards

    export default {
      ...
      beforeRouteEnter(to, from, next) {
        to.meta.title = to.params.project_name_slug;
        next();
      },
      beforeRouteUpdate(to, from, next) {
        to.meta.title = to.params.project_name_slug;
        next();
      }
    }
    

    您可以像使用静态元一样使用afterEach,因为它已经设置好了:

    const DEFAULT_TITLE = "my blog";
    router.afterEach((to, from) => {
        // document.title = to.meta.title || DEFAULT_TITLE;
        document.title = "my blog - " + to.meta.title || DEFAULT_TITLE;
    });
    

    (注意: 在路由定义中使用beforeEnter 是不够的,因为从一个动态参数到另一个动态参数时它不会触发。即使<router-view :key="$route.fullPath"></router-view> 也不会触发@987654333 @ 更改参数时。)

    【讨论】:

    【解决方案3】:

    我假设您在初始化组件之前询问如何执行此操作,因为您有 SEO 问题,否则就像从 axios 请求中的 JSON 响应中提取它并在组件中使用 document.title = myJson.page_title 一样简单.

    如果您的最终目标是消除对 SEO 的担忧(这是完全正确的),那么您需要更改方法以在组件渲染之前使 JSON 数据可用。

    我建议在你的路由导航守卫中发出 axios 请求,并提前为路由属性补水,这样你就可以真正访问页面标题。观察:

    更新您的路线以接受新的元属性:

    meta: {
      title: "project detail",
      content: []
    }
    

    在包含导航守卫的文件中导入 axios 并执行 axios 请求以获取和水合 content。请从 afterEach 迁移到 beforeEach,以便在收到数据之前阻止组件的呈现:

    import axios from 'axios'
    
    router.beforeEach(async(to, from, next) => {
      const { response } = await axios.get(`/my/cms/endpoint/${to.params.project_name_slug}`)
    
      document.title = `my blog - ${response.data.title}`
    
      to.meta.content = response.data.content
    
      next()
    })
    

    我对上述响应的形状做了一些假设,您需要对其进行修改以适应您的服务器响应。

    现在在您的组件中,您将能够访问 this.$route.meta.content 并且您可以在 mounted 生命周期中使用它来补充本地属性,或者使用 getter 来返回它,我假设您正在这样做已经有类似的东西了:

    export default {
      get pageContent () {
        return this.$route.meta.content
      }
    }
    

    【讨论】:

    • 谢谢@ohgodwhy,我意识到这正是问题所在——即需要在组件渲染之前使 JSON 数据可用(否则,通过 SingleProject 组件中的 JSON 响应设置标题本身会导致标题显示延迟,我觉得这很让人分心——我什至没有想到 SEO 问题,但这是一个好点!)我会尝试你的解决方案——谢谢。
    • 请注意,这并不能保证网络爬虫会看到这个标题,因为它是由 JavaScript 设置的。 (我的回答也没有。)通常网站使用预渲染方案(例如 SSR)来处理 SEO。这是使用 Nuxt 的主要原因之一。尽管如此,很好的答案也适用于需要提取的时候。
    猜你喜欢
    • 2019-12-05
    • 2020-01-10
    • 1970-01-01
    • 2020-07-30
    • 2022-08-15
    • 2020-08-12
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多