所以,避免状态单例,我们不应该直接创建一个应用程序实例,而是应该暴露一个可以重复执行的工厂函数,为每个请求创建新的应用程序实例,同样router和store入口文件也需要重新创建一个实例。
为了配合webpack动态加载路由配置,这里会改写常规路由引入写法,这样可以根据路由路径来判断加载相应的组件代码:
import Home from '../views/index/index.vue'
// 改写成
component: () => ('../views/index/index.vue')
以下是路由的基本写法router,对外会抛出一个createRouter方法来创建一个新的路由实例:
import Vue from 'vue'
import Router from 'vue-router';
Vue.use(Router)
export function createRouter() {
return new Router({
mode: 'history',
routes: [{
name:'Home',
path: '/',
component: () =>
import ('../views/index/index.vue')
}]
})
}
以下是store状态管理的基本写法,对外暴露了一个createStore方法,方便每次访问创建一个新的实例:
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import getters from './getters'
import modules from './modules/index'
Vue.use(Vuex)
export function createStore() {
return new Vuex.Store({
actions,
getters,
modules,
strict: false
})
}
结合写好的router和store入口文件代码来编写整个项目的入口文件app.js代码内容,同样最终也会对外暴露一个createApp方法,在每次创建app的时候保证router,store,app都是新创建的实例,这里还引入了一个vue路由插件vuex-router-sync,主要作用是同步路由状态(route state)到 store,以下是app.js完整代码:
import Vue from 'vue'
import App from './App.vue'
import { createRouter } from './router'
import { createStore } from './store'
import { sync } from 'vuex-router-sync'
require('./assets/style/css.less');
export function createApp () {
// 创建 router 和 store 实例
const router = createRouter()
const store = createStore()
// 同步路由状态(route state)到 store
sync(store, router)
// 创建应用程序实例,将 router 和 store 注入
const app = new Vue({
router,
store,
render: h => h(App)
})
// 暴露 app, router 和 store。
return { app, router, store }
}
entry-client.js代码编写:
首页引入从app文件中暴露出来的createApp方法,在每次调用客户端的时候,重新创建一个新的app,router,store,部分代码如下:
import { createApp } from './app'
const { app, router, store } = createApp()
这里我们会使用到onReady方法,此方法通常用于等待异步的导航钩子完成,比如在进行服务端渲染的时候,例子代码如下:

