服务端渲染 Node 层直接获取数据
在 Egg 项目如果使用模板引擎规范时通是过 render 方法进行模板渲染,render 的第一个参数模板路径,第二个参数时模板渲染数据. 如如下调用方式:
async index(ctx) { // 获取数据,可以是从数据库,后端 Http 接口 等形式 const list = ctx.service.article.getArtilceList(); // 对模板进行渲染,这里的 index.js 是 vue 文件通过 Webpack 构建的 JSBundle 文件 await ctx.render('index.js', { list }); }
从上面的例子可以看出,这种使用方式是非常典型的也容易理解的模板渲染方式。在实际业务开发时,对于常规的页面渲染也建议使用这种方式获取数据没,然后进行页面渲染。Node 获取数据后,在 Vue 的根 Vue 文件里面就可以通过 this.list 的方式拿到 Node 获取的数据,然后就可以进行 vue 模板文件数据绑定了。
在这里有个高阶用法,可以直接把 ctx 等 Node 对象传递到 第二个参数里面, 这个时候你在模板里面就直接拿到 ctx 这些对象。 但这个时候就需要自己处理好 SSR 渲染时导致的 hydrate 问题,因为前端hydrate时并没有 ctx 对象。
async index(ctx) { // 获取数据,可以是从数据库,后端 Http 接口 等形式 const list = ctx.service.article.getArtilceList(); // 对模板进行渲染,这里的 index.js 是 vue 文件通过 Webpack 构建的 JSBundle 文件 await ctx.render('index.js', { ctx, list }); }
服务端渲染 asyncData 方式获取数据
在 Vue 单页面 SSR 时涉及数据的请求方式,Node 层获取数据方式可以继续使用,但当路由切换时(页面直接刷新),Node 层就需要根据路由获取不同页面的数据,同时还要考虑前端路由切换的情况,这个时候路由是不会走 Node 层路由,而是直接进行的前端路由,这个时候也要考虑数据的请求方式。
基于以上使用的优雅问题,这里提供一种 asyncData 获取数据的方式解决单页面 SSR 刷新不走 SSR 问题。 Node 不直接获取数据,获取数据的代码直接写到前端代码里面。这里需要解决如下两个问题:
前端路由匹配 asyncData 调用
这里根据路由切换 url 获取指定的路由 componet 组件,然后检查是否有 aysncData,如果有就进行调用。调用之后,数据会放到 Vuex 的 store 里面。
return new Promise((resolve, reject) => { router.onReady(() => { // url 为当前请求路由,可以通过服务端传递到前端页面 const matchedComponents = router.getMatchedComponents(url); if (!matchedComponents) { return reject({ code: '404' }); } return Promise.all( matchedComponents.map(component => { // 关键代码 if (component.methods && component.methods.asyncData) { return component.methods.asyncData(store); } return null; }) ).then(() => { context.state = { ...store.state, ...context.state }; return resolve(new Vue(options)); }); }); });
Vue 模板定义 asyncData 方法
前端通过 Vuex 进行数据管理,把数据统一放到 store 里面,前端通过 this.$store.state 方式可以获取数据,Node 和 前端都可以获取到。
<script type="text/babel"> export default{ computed: { isLoading(){ return false; }, articleList() { return this.$store.state.articleList; } }, methods: { asyncData ({ state, dispatch, commit }) { return dispatch('FETCH_ARTICLE_LIST') } } } </script>
前端 asyncData 数据统一调用
在服务端 asyncData 调用时,可以解决单页面 SSR 刷新问题,那直接在前端切换路由时因不走服务端路由,那数据如何处理?
在 Vue 单页面实现时,通常都会使用 Vue-Router,这个时候可以借助 Vue-Router 提供 afterEach 钩子进行统一数据请求,可以直接调用 Vue 模板定义的 asyncData 方法。代码如下:
const options = this.create(window.__INITIAL_STATE__); const { router, store } = options; router.beforeEach((route, redirec, next) => { next(); }); router.afterEach((route, redirec) => { if (route.matched && route.matched.length) { const asyncData = route.matched[0].components.default.asyncData; if (asyncData) { asyncData(store); } } });
最后贴上可以用的完整代码,请根据实际需要进行修改, 实际可运行例子见 https://github.com/easy-team/egg-vue-webpack-boilerplate/tree/feature/green/spa
Vue 页面初始化统一封装
import Vue from 'vue'; import { sync } from 'vuex-router-sync'; import './vue/filter'; import './vue/directive'; export default class App { constructor(config) { this.config = config; } bootstrap() { if (EASY_ENV_IS_NODE) { return this.server(); } return this.client(); } create(initState) { const { index, options, createStore, createRouter } = this.config; const store = createStore(initState); const router = createRouter(); sync(store, router); return { ...index, ...options, router, store }; } client() { Vue.prototype.$http = require('axios'); const options = this.create(window.__INITIAL_STATE__); const { router, store } = options; router.beforeEach((route, redirec, next) => { next(); }); router.afterEach((route, redirec) => { console.log('afterEach', route); if (route.matched && route.matched.length) { const asyncData = route.matched[0].components.default.asyncData; if (asyncData) { asyncData(store); } } }); const app = new Vue(options); const root = document.getElementById('app'); const hydrate = root.childNodes.length > 0; app.$mount('#app', hydrate); return app; } server() { return context => { const options = this.create(context.state); const { store, router } = options; router.push(context.state.url); return new Promise((resolve, reject) => { router.onReady(() => { const matchedComponents = router.getMatchedComponents(); if (!matchedComponents) { return reject({ code: '404' }); } return Promise.all( matchedComponents.map(component => { if (component.asyncData) { return component.asyncData(store); } return null; }) ).then(() => { context.state = { ...store.state, ...context.state }; return resolve(new Vue(options)); }); }); }); }; } }
页面入口代码
// index.js 'use strict'; import App from 'framework/app.js'; import index from './index.vue'; import createStore from './store'; import createRouter from './router'; const options = { base: '/' }; export default new App({ index, options, createStore, createRouter, }).bootstrap();
前端 router / store 定义
// store/index.js 'use strict'; import Vue from 'vue'; import Vuex from 'vuex'; import actions from './actions'; import getters from './getters'; import mutations from './mutations'; Vue.use(Vuex); export default function createStore(initState = {}) { const state = { articleList: [], article: {}, ...initState }; return new Vuex.Store({ state, actions, getters, mutations }); } // router/index.js import Vue from 'vue'; import VueRouter from 'vue-router'; import ListView from './list'; Vue.use(VueRouter); export default function createRouter() { return new VueRouter({ mode: 'history', base: '/', routes: [ { path: '/', component: ListView }, { path: '/list', component: ListView }, { path: '/detail/:id', component: () => import('./detail') } ] }); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]