Vue / Nuxt异步元标记生成

时间:2018-08-22 07:43:25

标签: javascript vue.js vuejs2 meta nuxt.js

我们有一个使用vue.js和nuxt构建的网页。我们使用nuxt generate生成静态html文件,该文件还应包含SEO和og标签。 这就是为什么我们使用nuxt's head ()来生成元信息的原因。

到目前为止,一切都很好。 但是现在我们有了一个页面,该页面将帖子异步加载到nested route中。如果转到该页面,它将通过ajax调用加载帖子的数据。然后它将使用帖子的元数据填充<head>

当我们使用nuxt generate时,元数据会在一段时间后(在帖子加载后)正确更新,但是,我们使用{生成元信息时,该元信息不存在{1}}。

这就是为什么我们的静态html不包含必要的元信息的原因。 有什么可能的解决方案? 理想的情况是生成过程等待帖子被加载。可以用承诺解决吗?还是还有其他想法?

这里head ()首先设置为false。 我们的辅助函数generateMetaInfo被调用,但显然没有正确的数据。

this.post

我们在调用url时像这样加载帖子:

head () {
  this.log('this.post: ', this.post)
  if (this.post) {
   return generateMetaInfo(this.post)
  }
}

所以我们必须等待ajax调用完成。

非常感谢任何可以帮助我们找到解决方案的想法。

欢呼

============================

编辑:

使用承诺也不起作用:

getPost () {
  // Only if postSlug is present
  if (this.$route.params.postSlug) {
    // If postslug > try to get it from store
    if (this.getCompletePostBySlug(this.$route.params.postSlug)) {
      this.activePost = this.getCompletePostBySlug(this.$route.params.postSlug)
    }
    // if it is not in store get it via axios
    else {
      const ax = axios.create({
        baseURL: `${window.location.origin}/${this._checkRouteByString('programm') ? 'events' : 'posts'}`
      })
      ax.get(`posts.${this.$i18n.locale}.${this.$route.params.postSlug}.json`)
      .then((response) => {
        const newActivePost = response.data && response.data.items ? response.data.items.find(p => p.slug === this.$route.params.postSlug) : false
        if (newActivePost) {
          this.post = newActivePost
          this.$store.dispatch('data/saveCompletePosts', this.activePost)
        } else {
          this.post = '404'
        }
      })
      .catch((error) => {
        // console.log(error.response)
      })
    }
  } else {
    this.setActivePost()
  }
},

这不会等到诺言解决... :( (当然,这只是一个带有超时的示例,在现实世界中,必须将其与ajax调用交换,以获取帖子的数据)

4 个答案:

答案 0 :(得分:0)

Nuxt是一个很棒的框架,但是SEO和在动态路由上分配元标记非常困难。这可能不是为什么它不好的极少数原因之一。

我认为这里的主要问题是您试图从仅在Promise或函数解析后才被调用的方法中加载元数据,这意味着直到页面呈现后它才永远不会获取元数据。我不会为此使用函数或诺言。

从本质上讲,我发现解决此问题的方法是,您需要以以下格式加载所有元数据(连同您的帖子名称作为ID或其他内容)

posts: [
    {
        slug: 'some_id',
        meta: [
            {
                name: 'title',
                content: 'some_title'
            },
            {
                ...
        ]
    },
    {
        ...

将动态页面分成一个数组-例如,我正在使用VueX商店-然后您可以使用

这样的语句
this.$store.state.array.find(p => p.slug === this.$route.params.postSlug).meta
.vue文件中的

,其中id是要与route参数比较的任何值。这将返回元数据数组。

我意识到这种方法效率不高,大多数人可能会对此有所畏惧,但是对于动态路线而言,它似乎确实很有效。

我的head()方法看起来像这样

head() {
    return {
        title: "Title " + this.$route.params.id,
        meta: this.$store.state.results.find((result) => result.id === this.$route.params.id).meta
    }
}

这对我来说非常有效。如果您尝试这样做,我很想听听它的进展。

欢呼

答案 1 :(得分:0)

您必须使用asyncData来获取动态数据(例如从api),然后从中获取数据。那将在服务器端获取。

参考:https://nuxtjs.org/guide/async-data

答案 2 :(得分:0)

代码说明

double

将页面标题设置为“ Article + this.page.title中的值”

答案 3 :(得分:0)

在设置元数据之前检查页面对象是否存在。

head() {
  if (this.page) {
    return {
      title: 'Articles: ' + this.page.title
    }
  }
}