前面说了两种客户端数据预取的方式。
有一种情况当组件复用(/foo/1到/foo/2),由于是同一个路由组件的生命周期不会运行,数据不会更新需要单独处理。
vue-router导航守卫里有个beforeRouteUpdate,会在复用的组件里调用该守卫。
同样使用全局混入解决
Vue.mixin({
beforeRouteUpdate(to, from, next) {
const {
asyncData } = this.$options
if (asyncData) {
asyncData({
store: this.$store,
route: to
})
.then(next)
.catch(next)
} else {
next()
}
},
})
前面获取异步的方式是在store里面初始化数据,在组件的asyncData中异步修改数据,当数据多了以后手动在store里添加数据会很麻烦,我们稍作修改。
思路是调用asyncData时将获取到的数据通过store.registerModule注册到store中,每个组件以组件名注册一个模块,并在生命周期destoryed中删除此模块。
//main.js
import Vue from 'vue'
import app from './App.vue'
import {
createRouter } from './router.js'
import {
createStore } from './store.js'
import {
sync } from 'vuex-router-sync'
// 加了一个工具文件,里面封装了一个注册storeModule的方法
import utils from '../utils.js'
// import '../assets/global.less'
export function createApp() {
const router = createRouter()
const store = createStore()
// 新添加的
sync(store, router)
const vueApp = new Vue({
router,
store,
render: h => (h(app))
})
return {
vueApp, router, store, utils }
}
sync(store, router)在store中注册了一个叫route的模块,模块的内容是路由状态(router)的一些信息,并添加了watch,观察route数据是否有变化,并更新route数据。如果你觉得用不着可以不用加。
此时可以看到服务端传过来的html中的window.__INITIAL_STATE已经添加route的数据
//utils.js
export default {
registerStore(store, compName, compData) {
if (!store.hasModule(compName)) {
let mutationObj = {
}
Object.keys(compData).forEach(prop => {
mutationObj[prop] = (state, payload) => {
state[prop] = payload[prop]
}
})
store.registerModule(compName, {
namespaced: true,
state: () => {
return compData
},
mutations: mutationObj
})
} else {
Object.keys(compData).forEach(prop => {
store.commit(compName + '/' + prop, compData)
})
}
}
}
再修改router.js
const routes = [
//这里加了一个新组建index.vue,自己去创建一个ind