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 相关文章推荐
js 屏蔽鼠标右键脚本附破解方法
Dec 03 Javascript
JQuery Tips(4) 一些关于提高JQuery性能的Tips
Dec 19 Javascript
js中访问html中iframe的文档对象的代码[IE6,IE7,IE8,FF]
Jan 08 Javascript
JS关键字变色实现思路及代码
Feb 21 Javascript
jQuery :first选择器使用介绍
Aug 09 Javascript
JS打开新窗口防止被浏览器阻止的方法
Jan 03 Javascript
jQuery插件slides实现无缝轮播图特效
Apr 17 Javascript
剖析Node.js异步编程中的回调与代码设计模式
Feb 16 Javascript
JavaScript中获取HTML元素值的三种方法
Jun 20 Javascript
JavaScript简单实现合并两个Json对象的方法示例
Oct 16 Javascript
JavaScript设计模式之建造者模式实例教程
Jul 02 Javascript
JS删除String里某个字符的方法
Jan 06 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
apache和php之间协同工作的配置经验分享
2013/04/08 PHP
PHP数据库万能引擎类adodb配置使用以及实例集锦
2014/06/12 PHP
简单谈谈PHP中strlen 函数
2016/02/27 PHP
ThinkPHP3.2框架使用addAll()批量插入数据的方法
2017/03/16 PHP
PHP设计模式之模板方法模式定义与用法详解
2018/04/02 PHP
利用js动态添加删除table行的示例代码
2013/12/16 Javascript
jquery插件jTimer(jquery定时器)使用方法
2013/12/23 Javascript
js拖拽一些常见的思路方法整理
2014/03/19 Javascript
JavaScript实现将UPC转换成ISBN的方法
2015/05/26 Javascript
jquery实现的3D旋转木马特效代码分享
2015/08/25 Javascript
jQuery悬停文字提示框插件jquery.tooltipster.js用法示例【附demo源码下载】
2016/07/19 Javascript
javascript特效实现——当前时间和倒计时效果的简单实例
2016/07/20 Javascript
JavaScript使用prototype原型实现的封装继承多态示例
2018/08/31 Javascript
解决vue跨域axios异步通信问题
2019/04/17 Javascript
VueQuillEditor富文本上传图片(非base64)
2020/06/03 Javascript
Vue实现Header渐隐渐现效果的实例代码
2020/11/05 Javascript
[01:23]2014DOTA2国际邀请赛 球迷无处不在Ti现场世界杯受关注
2014/07/10 DOTA
python使用mailbox打印电子邮件的方法
2015/04/30 Python
Python中for循环和while循环的基本使用方法
2015/08/21 Python
Python与Java间Socket通信实例代码
2017/03/06 Python
对python中的iter()函数与next()函数详解
2018/10/18 Python
pyQt5实时刷新界面的示例
2019/06/25 Python
基于python cut和qcut的用法及区别详解
2019/11/22 Python
python中怎么表示空值
2020/06/19 Python
Anaconda使用IDLE的实现示例
2020/09/23 Python
HTML5触摸事件演化tap事件介绍
2016/03/25 HTML / CSS
Html5元素及基本语法详解
2016/08/02 HTML / CSS
浅谈HTML5中dialog元素尝鲜
2018/10/15 HTML / CSS
Marlies Dekkers内衣美国官方网上商店:高端内衣品牌
2018/11/12 全球购物
德国W家官网,可直邮中国的母婴商城:Windeln.de
2021/03/03 全球购物
迟到早退检讨书
2014/02/10 职场文书
项目经理聘任书
2014/03/29 职场文书
学生安全责任书模板
2014/07/25 职场文书
在 SQL 语句中处理 NULL 值的方法
2021/06/07 SQL Server
python 字典和列表嵌套用法详解
2021/06/29 Python
python开发制作好看的时钟效果
2022/05/02 Python