在entry-server.js中,我们可以通过路由获得与router.getMatchedComponents()相匹配的组件,如果组件暴露出asyncData,我们就调用这个方法。然后我们需要将解析完成的状态,附加到渲染上下文中。
- const createApp = require('./app');
- module.exports = context => {
- return new Promise((resolve, reject) => {
- const { app, router, store } = createApp(context);
- // 针对没有Vue router 的Vue实例,在项目中为列表页,直接resolve app
- if (!router) {
- resolve(app);
- }
- // 设置服务器端 router 的位置
- router.push(context.url.replace('/base', ''));
- // 等到 router 将可能的异步组件和钩子函数解析完
- router.onReady(() => {
- const matchedComponents = router.getMatchedComponents();
- // 匹配不到的路由,执行 reject 函数,并返回 404
- if (!matchedComponents.length) {
- return reject('匹配不到的路由,执行 reject 函数,并返回 404');
- }
- Promise.all(matchedComponents.map(Component => {
- if (Component.asyncData) {
- return Component.asyncData({
- store,
- route: router.currentRoute,
- });
- }
- })).then(() => {
- // 在所有预取钩子(preFetch hook) resolve 后,
- // 我们的 store 现在已经填充入渲染应用程序所需的状态。
- // 当我们将状态附加到上下文,并且 `template` 选项用于 renderer 时,
- // 状态将自动序列化为 `window.__INITIAL_STATE__`,并注入 HTML。
- context.state = store.state;
- resolve(app);
- }).catch(reject);
- }, reject);
- });
- }
客户端托管全局状态
当服务端使用模板进行渲染时,context.state将作为window.__INITIAL_STATE__状态,自动嵌入到最终的HTML 中。而在客户端,在挂载到应用程序之前,store就应该获取到状态,最终我们的entry-client.js被改造为如下所示:
- import createApp from './app';
- const { app, router, store } = createApp();
- // 客户端把初始化的store替换为window.__INITIAL_STATE__
- if (window.__INITIAL_STATE__) {
- store.replaceState(window.__INITIAL_STATE__);
- }
- if (router) {
- router.onReady(() => {
- app.$mount('#app')
- });
- } else {
- app.$mount('#app');
- }
常见问题的解决方案
至此,基本的代码改造也已经完成了,下面说的是一些常见问题的解决方案:
(编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|