我正在为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到具有完整配置的存储库