更强大的vue ssr实现预取数据的方式


Posted in Javascript onJuly 19, 2019

我在前几天的一篇文章中吹了两个牛皮,截图为证:

更强大的vue ssr实现预取数据的方式

现在可以松口气的说,这两个牛皮都实现了,不过 vue-suspense 改名了,叫做 vue-async-manager 了,他能帮你管理 Vue 应用中的异步组件的加载和 API 的调用,提供了与 React Suspense 同名的 `<Suspense>` 组件,Github:

shuidi-fed/vue-async-manager ​ github.com

更强大的vue ssr实现预取数据的方式

第二个牛皮是在开发 vue-async-manager 的过程中临时产生的一个灵感,觉得相同的技巧可以用在 SSR 预取数据上,但是当时还没有尝试,只是有个想法而已,不过很幸运,我成功了,GitHub:

https://github.com/HcySunYang/vue-ssr-prefetcher ​ github.com

vue-ssr-prefetcher 为 VueSSR 提供更直观更强大的数据预取方式(压缩后仅 1kb )。让我们来看看这张对比图:

更强大的vue ssr实现预取数据的方式

接下来详细介绍一下 vue-ssr-prefetcher:

Why?

Vue 的服务端渲染中做数据预取的方式大概可以总结为两种,一种是以 nuxt/ream 为代表的 asyncData 方案,另一种是 Vue 原生提供的 serverPrefetch 组件选项。然而这两种方案都有一些缺点:

nuxt/reamasyncData

  • 不能访问 this
  • 只能用于路由组件(或 page 组件)
  • 需要通过返回对象(或 promise)将数据暴露到渲染环境

Vue 原生提供的 serverPrefetch

  • 只运行于服务端,客户端需要另外编写数据获取逻辑,并避免数据的重复获取
  • 只能预取 store 数据,无法将数据暴露到组件级别的渲染环境并发送到客户端

以上两种方案还拥有一个共同的弊端: 不够直观 (不直观,因为这与开发 SPA 时编写代码的方式不同), vue-ssr-prefetcher 提供了一种更直观的数据预取方案,换句话说你在预取数据的过程中看不出来任何 SSR 的痕迹,就想在编写 SPA 应用一样。

安装

yarn add vue-ssr-prefetcher

Or use npm :

npm install vue-ssr-prefetcher --save

使用

vue-ssr-prefetcher 提供了两个 vue 插件: serverPluginclientPlugin ,分别用于 server entryclient entry

server entry 中:

import Vue from 'vue'
import createApp from './createApp'
// 1. 引入 serverPlugin
import { serverPlugin } from 'vue-ssr-prefetcher'

// 2. 安装插件
Vue.use(serverPlugin)

export default async context => {
 const { app, router, store } = createApp()

 router.push(context.url)

 await routerReady(router)

 // 3. 设置 context.rendered 为 serverPlugin.done
 context.rendered = serverPlugin.done

 // 4. app.$$selfStore 是 serverPlugin 插件注入的属性
 context.state = {
  $$stroe: store ? store.state : undefined,
  $$selfStore: app.$$selfStore
 }

 return app
}

function routerReady (router) {
 return new Promise(resolve => {
  router.onReady(resolve)
 })
}

serverPlugin 会在根组件实例上注入 app.$$selfStore 属性,存储着组件级别的数据,你只需要将他添加到 context.state 中即可。另外,你还需要将 context.rendered 设置为 serverPlugin.done

client entry 中:

import Vue from 'vue'
import createApp from './createApp'
// 1. 引入插件
import { clientPlugin } from 'vue-ssr-prefetcher'
// 2. 安装插件
Vue.use(clientPlugin)

const { app, router, store } = createApp()

router.onReady(() => {
 // 3. 从 window.__INITIAL_STATE__ 中解构出 $$selfStore
 const { $$selfStore } = window.__INITIAL_STATE__

 // 4. 将数据添加到跟组件实例
 if ($$selfStore) app.$$selfStore = $$selfStore

 app.$mount('#app')
 // 5. 这个非常重要,它用于避免重复获取数据,并且一定要在 $mount() 函数之后
 clientPlugin.$$resolved = true
})

来看看接下来如何做数据预取

按照上面的介绍配置完成后,你就可以在任何组件的 created 钩子中发送请求预取数据:

export default {
 name: 'Example',
 data() {
  return { name: 'Hcy' }
 },
 async created() {

  // this.$createFetcher() 函数是 clientPlugin 注入的
  // 接收一个返回 promise 的函数作为参数,例如用于请求 api 函数
  const fetcher = this.$createFetcher(fetchName)

  const res = await fetcher()

  this.name = res.name
 }
}

如上代码所示,和过去唯一不同的就是你需要调用 this.$createFetcher 函数创建一个 fetcher ,你可能会觉得这不爽,然而实际上 this.$createFetcher 做的事情很简单,下面是它的源码:

Vue.prototype.$createFetcher = function(fetcher) {
 const vm = this
 return function(params: any) {
  const p = fetcher(params)
  vm.$$promises.push(p)
  return p
 }
}

仅仅是一个简单的包装,因此我们可以把通过 this.$createFetcher 函数创建得到的 fetcher 认为与原函数相同。

虽然看上去和开发 SPA 应用时没什么不同,但 vue-ssr-prefetcher 为你做了很多事情,让我们来对比一下,还是刚才的那种图:

更强大的vue ssr实现预取数据的方式

当然了 vue-ssr-prefetcher 还为你做了:

  • 避免重复获取数据
  • 当路由跳转时应该能够正常发送请求

而你几乎什么都不需要做, 唯一需要做的就是使用 this.$createFetcher 函数创建 fetcher ,但这真的没有任何黑科技。

为了配合 vuex 一块使用,你只需要:

export default {
 name: 'Example',
 async created() {
  const fetcher = this.$createFetcher(() => this.$store.dispatch('someAction'))

  fetcher()
 }
}

当然了使用 mapActions 将 action 映射为 methods 也是可以的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 添加和移除函数的通用方法
Oct 20 Javascript
jquery 图片 上一张 下一张 链接效果(续篇)
Apr 20 Javascript
Jquery和JS用外部变量获取Ajax返回的参数值的方法实例(超简单)
Jun 17 Javascript
window.print打印指定div指定网页指定区域的方法
Aug 04 Javascript
js进行表单验证实例分析
Feb 10 Javascript
javascript+HTML5 Canvas绘制转盘抽奖
May 16 Javascript
浅谈bootstrap源码分析之tab(选项卡)
Jun 06 Javascript
单行 JS 实现移动端金钱格式的输入规则
May 22 Javascript
jQuery图片查看插件Magnify开发详解
Dec 25 jQuery
element-ui table span-method(行合并)的实现代码
Dec 20 Javascript
JS Ajax请求会话过期处理问题解决方法分析
Nov 16 Javascript
uniapp电商小程序实现订单30分钟倒计时
Nov 01 Javascript
bootstrap table.js动态填充单元格数据的多种方法
Jul 18 #Javascript
bootstrap table实现横向合并与纵向合并
Jul 18 #Javascript
微信小程序判断用户是否需要再次授权获取个人信息
Jul 18 #Javascript
Vue动态生成表格的行和列
Jul 18 #Javascript
vue通过数据过滤实现表格合并
Nov 30 #Javascript
Vue实现数据表格合并列rowspan效果
Nov 30 #Javascript
小程序分页实践之编写可复用分页组件
Jul 18 #Javascript
You might like
Windows 下的 PHP-PEAR 安装方法
2010/11/20 PHP
PHP页面中文乱码分析
2013/10/29 PHP
php抛出异常与捕捉特定类型的异常详解
2016/10/26 PHP
php提交表单时保留多个空格及换行的文本样式的方法
2017/06/20 PHP
laravel实现简单用户权限的示例代码
2019/05/28 PHP
dwr spring的集成实现代码
2009/03/22 Javascript
prototype 学习笔记整理
2009/07/17 Javascript
跟我学Node.js(四)---Node.js的模块载入方式与机制
2014/06/04 Javascript
angularJS结合canvas画图例子
2015/02/09 Javascript
JavaScript实现表格点击排序的方法
2015/05/11 Javascript
JavaScript中字符串拼接的基本方法
2015/07/07 Javascript
jQuery下拉美化搜索表单效果代码分享
2015/08/25 Javascript
javascript检测flash插件是否被禁用的方法
2016/01/14 Javascript
jQuery页面元素动态添加后绑定事件丢失方法,非 live
2016/06/16 Javascript
AngularJS实现单独作用域内的数据操作
2016/09/05 Javascript
js创建对象几种方式的优缺点对比
2016/09/28 Javascript
NPM 安装cordova时警告:npm WARN deprecated minimatch@2.0.10: Please update to minimatch 3.0.2 or higher to
2016/12/20 Javascript
js+html5实现半透明遮罩层弹框效果
2020/08/24 Javascript
mui 打开新窗口的方式总结及注意事项
2017/08/20 Javascript
聊聊那些使用前端Javascript实现的机器学习类库
2017/09/18 Javascript
基于JavaScript实现前端数据多条件筛选功能
2020/08/19 Javascript
基于Vuejs的搜索匹配功能实现方法
2018/03/03 Javascript
基于VUE的v-charts的曲线显示功能
2019/10/01 Javascript
Vue过渡效果之CSS过渡详解(结合transition,animation,animate.css)
2020/02/05 Javascript
vue数据响应式原理知识点总结
2020/02/16 Javascript
JS实现iframe中子父页面跨域通讯的方法分析
2020/03/10 Javascript
python实现dnspod自动更新dns解析的方法
2014/02/14 Python
深入源码解析Python中的对象与类型
2015/12/11 Python
Python判断值是否在list或set中的性能对比分析
2016/04/16 Python
Python实现数字的格式化输出
2020/08/01 Python
Python爬虫回测股票的实例讲解
2021/01/22 Python
aden + anais官方网站:婴儿襁褓、毯子、尿布和服装
2017/06/21 全球购物
viagogo意大利票务平台:演唱会、体育比赛、戏剧门票
2018/01/26 全球购物
Molton Brown美国官网:奢华美容、香水、沐浴和身体护理
2020/09/02 全球购物
北京-环亚运商测试题.net程序员初步测试题
2013/05/28 面试题
分享几个JavaScript运算符的使用技巧
2021/04/24 Javascript