Vue SSR 组件加载问题


Posted in Javascript onMay 02, 2018

Node 端渲染提示 window/document 没有定义

Vue SSR 组件加载问题

业务场景

首先来看一个简单的 Vue 组件 test.vue

<template>
 <div>
  <h2>clientHeight: {{ clientHeight }} px </h2>
 </div>
</template>

<script type="text/babel">
 export default {
  data(){
   return {
   }
  },
  computed :{
   clientHeight() {
    return document.body.clientHeight;
   }
  },
  mounted(){
  }
 }
</script>

上面 test.vue 组件通过 Vue computed 属性 clientHeight 直接获取 document 的文档高度,这段代码在前端渲染是不会报错的,也能拿到正确的值。但如果把这个组件放到 SSR(Server Side Render) 模式下, 就会报如下错误:
ReferenceError: document is not defined

解决方案

通过 typeof 判断是否是存在 document 对象, 如果存在则执行后面代码。 这种方式虽然能解决问题, 但在 Webpack 构建压缩时, 不会执行的代码不会被剔除,也会打包到 js 文件中去, 因为这个是在运行期才知道结果的, 所以在 Webpack 构建方案中,不建议使用 typeof 方式判断。而是使用 Webpack 提供的 webpack.DefinePlugin 插件定义常量解决。

clientHeight() {
  return typeof document === 'object' ? document.body.clientHeight : '';
}

使用 Webpack 提供的 webpack.DefinePlugin 插件定义常量解决。 这里直接使用 easywebpack     https:// github.com/hubcarl/easy    webpack   内置的全局 Webpack 常量 EASY_ENV_IS_BROWSER  http:// hubcarl.github.io/easyw ebpack/webpack/env   进行 判断。 这样在构建压缩期间, 如果是 Node 模式构建, EASY_ENV_IS_BROWSER 会被替换为 false,如果是 Browser 模式构建, EASY_ENV_IS_BROWSER 会被替换为 true,最后构建后代码也就是变成了 true 或者 false 的常量。 因为这个是构建期间执行的,压缩插件剔除永远不会被执行的代码, 也就是

dead_code
clientHeight() {
  return EASY_ENV_IS_BROWSER ? document.body.clientHeight : '';
}

NPM Vue 组件 SSR 支持

针对上面这种自己写的代码,我们可以通过这种方式解决,因为可以直接修改。但如果我们引入的一个 npm Vue 插件想进行SSR渲染, 但这个插件里面使用了 window/docment 等浏览器对象, 并没有对 SSR 模式进行兼容,这个时候该如何解决呢?

一般我们通过 通过 v-if 来决定是否渲染该组件 和 Vue 只在前端挂载组件解决问题 可以解决。

通过 v-if 来决定是否渲染该组件

<template>
 <div v-if="isBrowser">
  <Loading></Loading>
 </div>
</template>
<script type="text/babel">
 export default {
  componets:{
   Loading: () =>import('vue-loading');
  }
  data(){
   return {
    isBrowser: EASY_ENV_IS_BROWSER
   }
  },
  mounted(){
  }
 }
</script>

Vue 只在前端挂载组件解决问题

<template>
 <div>
  <Loading></Loading>
 </div>
</template>

<script type="text/babel">
 export default {
  data(){
   return {
   }
  },
  beforeMount() {
   // 只会在浏览器执行 
   this.$options.components.Loading = () =>import('vue-loading');
  },
  mounted(){
  }
 }
</script>

loading 组件因为没有注册, 在 SSR 模式, <Loading></Loading> 会被原样输出到 HTML 中,不会报错且不能被浏览器识别, 在显示时不会有内容。当 SSR 直出 HTML 后,浏览器模式中执行 beforeMount 挂载组件, 从而达到解决服务端渲染报错的问题

https:// github.com/hubcarl/egg- vue-webpack-boilerplate/blob/master/app/web/page/dynamic/dynamic.vue

总结

以上所述是小编给大家介绍的Vue SSR 组件加载问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript圆盘抽奖程序实现原理和完整代码例子
Jun 03 Javascript
js实现编辑div节点名称的方法
Dec 17 Javascript
JavaScript分秒倒计时器实现方法
Feb 02 Javascript
Javascript中this关键字的一些小知识
Mar 15 Javascript
学习vue.js表单控件绑定操作
Dec 05 Javascript
超简单的Vue.js环境搭建教程
Mar 17 Javascript
12个非常有用的JavaScript技巧
May 17 Javascript
使用vue制作FullPage页面滚动效果
Aug 21 Javascript
详解tween.js的使用教程
Sep 14 Javascript
微信小程序开发之IOS和Android兼容的问题
Sep 26 Javascript
JS随机密码生成算法
Sep 23 Javascript
Vue 数据绑定的原理分析
Nov 16 Javascript
基于jquery实现左右上下移动效果
May 02 #jQuery
关于Vue在ie10下空白页的debug小结
May 02 #Javascript
解析Json字符串的三种方法日常常用
May 02 #Javascript
使用vue-cli创建项目的图文教程(新手入门篇)
May 02 #Javascript
vue中的模态对话框组件实现过程
May 01 #Javascript
vue如何通过id从列表页跳转到对应的详情页
May 01 #Javascript
使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
May 01 #Javascript
You might like
星际玩家的三大定律
2020/03/04 星际争霸
967 个函式
2006/10/09 PHP
php disk_free_space 返回目录可用空间
2010/05/10 PHP
php实现微信扫码自动登陆与注册功能
2016/09/22 PHP
XP折叠菜单&amp;仿QQ2006菜单
2006/12/16 Javascript
IE6下focus与blur错乱的解决方案
2011/07/31 Javascript
鼠标滚轮控制网页横向移动实现思路
2013/03/22 Javascript
jquery中获取id值方法小结
2013/09/22 Javascript
jQuery实现的数值范围range2dslider选取插件特效多款代码分享
2015/08/27 Javascript
Javascript中Date类型和Math类型详解
2016/02/27 Javascript
JS从一组数据中找到指定的单条数据的方法
2016/06/02 Javascript
理解javascript中的闭包
2017/01/11 Javascript
JS+html5 canvas实现的简单绘制折线图效果示例
2017/03/13 Javascript
JavaScript实现简单的星星评分效果
2017/05/18 Javascript
基于$.ajax()方法从服务器获取json数据的几种方式总结
2018/01/31 Javascript
Es6 Generator函数详细解析
2018/02/24 Javascript
jquery ajax 请求小技巧实例分析
2019/11/11 jQuery
微信小程序清空输入框信息与实现屏幕往上滚动的示例代码
2020/06/23 Javascript
Python中的生成器和yield详细介绍
2015/01/09 Python
python通过伪装头部数据抵抗反爬虫的实例
2018/05/07 Python
python中使用print输出中文的方法
2018/07/16 Python
Python实现基于POS算法的区块链
2018/08/07 Python
python同时遍历数组的索引和值的实例
2018/11/15 Python
Python 微信之获取好友昵称并制作wordcloud的实例
2019/02/21 Python
TensorFlow梯度求解tf.gradients实例
2020/02/04 Python
为什么python比较流行
2020/06/19 Python
详解Java中一维、二维数组在内存中的结构
2021/02/11 Python
python解决OpenCV在读取显示图片的时候闪退的问题
2021/02/23 Python
法国和欧洲海边和滑雪度假:Pierre & Vacances
2017/01/04 全球购物
Dr.Jart+美国官网:韩国药妆品牌
2019/01/18 全球购物
部队领导证婚词
2014/01/12 职场文书
庆元旦广播稿
2014/02/10 职场文书
护士长2015年终工作总结
2015/04/24 职场文书
房屋租赁意向书范本
2015/05/09 职场文书
Python中常见的反爬机制及其破解方法总结
2021/06/10 Python
开发者首先否认《遗弃》被取消的传言
2022/04/11 其他游戏