Vue + SSR |如何将mixin传输到配置文件?

时间:2019-03-03 17:30:24

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

我正在为ssr编写配置

添加了mixin,以替换标题和meta在app.js文件中全局宣布。

import headMixin from './util/title'
Vue.mixin(headMixin);

第一次加载页面时,或者转到网站的根目录时,它都可以工作。 如果您转到另一个页面,则该页面不起作用(

我想将其添加到功能entry-client.js中的配置文件router.onReady()

import Vue from 'vue'
import 'es6-promise/auto'
import {createApp} from './app'
import ProgressBar from './components/ProgressBar.vue'

const bar = Vue.prototype.$bar = new Vue(ProgressBar).$mount();
document.body.appendChild(bar.$el);

Vue.mixin({
  beforeRouteUpdate(to, from, next) {
    const {asyncData} = this.$options;
    if (asyncData) {
      asyncData({
        store: this.$store,
        route: to
      }).then(next).catch(next)
    } else {
      next()
    }
  }
});

const {app, router, store} = createApp();

if (window.__INITIAL_STATE__) {
  store.replaceState(window.__INITIAL_STATE__)
}

router.onReady(() => {

  router.beforeResolve((to, from, next) => {
    const matched = router.getMatchedComponents(to);
    const prevMatched = router.getMatchedComponents(from);
    let diffed = false;
    const activated = matched.filter((c, i) => {
      return diffed || (diffed = (prevMatched[i] !== c))
    });
    const asyncDataHooks = activated.map(c => c.asyncData).filter(_ => _);
    if (!asyncDataHooks.length) {
      return next()
    }

    // TODO Обсудить наличие статусбара
    bar.start();
    Promise.all(asyncDataHooks.map(hook => hook({ store, route: to })))
      .then(() => {
        bar.finish();
        next()
      })
      .catch(next)
  });

  app.$mount('#app')
});

但是我不明白如何正确地进行操作(

我自己混在这里

const cleanMetas = () => {
  return new Promise((resolve, reject) => {
    const items = document.head.querySelectorAll('meta');
    for (const i in items) {
      if (typeof items[i] === 'object'
          && ['viewport'].findIndex(val => val === items[i].name) !== 0
          && items[i].name !== '')
        document.head.removeChild(items[i])
    }
    resolve()
  })
};

const createMeta = (vm, name, ...attr) => {
  const meta = document.createElement('meta');
  meta.setAttribute(name[0], name[1]);
  for (const i in attr) {
    const at = attr[i];
    for (const k in at) {
      meta.setAttribute(at[k][0], getString(vm, at[k][1]))
    }
  }
  document.head.appendChild(meta);
};

const getString = (vm, content) => {
  return typeof content === 'function'
      ? content.call(vm)
      : content
};

export const getMeta = (vm, meta, env) => {
  if (typeof meta !== 'object')
    return;

  if (env) {
    return Object.keys(meta)
        .map(value => {
          return Object.keys(meta[value])
              .map(key => `${key}="${getString(vm, meta[value][key])}"`)
              .join(" ");
        })
        .map(value => `  <meta ${value} >`)
        .join("\n");

  } else {
    return meta
  }
};

const serverHeadMixin = {
  created() {
    const {head} = this.$options;
    if (head) {
      const {title} = head;
      if (title)
        this.$ssrContext.title = getString(this, title);

      const {meta} = head;
      if (meta)
        this.$ssrContext.meta = `\n${getMeta(this, meta, true)}`
    }
  }
};

const clientHeadMixin = {
  mounted() {
    const vm = this;

    const {head} = this.$options;
    if (head) {
      const {title} = head;
      if (title) {
        document.title = getString(this, title)
      }


    }

    if (head) {
      cleanMetas().then(() => {
        const {meta} = head;
        if (meta)
          for (const nm in meta) {
            const name = Object.entries(meta[nm])[0];
            const attr = Object.entries(meta[nm]).splice(1, Object.entries(meta[nm]).length);
            createMeta(vm, name, attr)
          }
      })

    }
  }
};


export default process.env.VUE_ENV === 'server'
    ? serverHeadMixin
    : clientHeadMixin

Link到具有完整配置的存储库

0 个答案:

没有答案