所以,避免状态单例,我们不应该直接创建一个应用程序实例,而是应该暴露一个可以重复执行的工厂函数,为每个请求创建新的应用程序实例,同样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方法,此方法通常用于等待异步的导航钩子完成,比如在进行服务端渲染的时候,例子代码如下: