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验证表单第二部分
Nov 25 Javascript
JavaScript截取字符串的Slice、Substring、Substr函数详解和比较
Mar 20 Javascript
JS 排序输出实现table行号自增前端动态生成的tr
Aug 13 Javascript
了不起的node.js读书笔记之node.js中的特性
Dec 22 Javascript
jQuery中dom元素上绑定的事件详解
Apr 24 Javascript
js获取url传值的方法
Dec 18 Javascript
jQuery焦点图轮播效果实现方法
Dec 19 Javascript
Bootstrap + AngularJS 实现简单的数据过滤字符查找功能
Jul 27 Javascript
layui框架中layer父子页面交互的方法分析
Nov 15 Javascript
微信小程序自定义组件的实现方法及自定义组件与页面间的数据传递问题
Oct 09 Javascript
JS sort方法基于数组对象属性值排序
Jul 10 Javascript
Vue如何循环提取对象数组中的值
Nov 18 Vue.js
基于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
解析php addslashes()与addclashes()函数的区别和比较
2013/06/24 PHP
php实现天干地支计算器示例
2014/03/14 PHP
PHP合并静态文件详解
2014/11/14 PHP
php 生成签名及验证签名详解
2016/10/26 PHP
Laravel框架中缓存的使用方法分析
2019/09/06 PHP
js异或加解密效果代码
2008/06/25 Javascript
验证用户是否修改过页面的数据的实现方法
2008/09/26 Javascript
javascript 表格排序和表头浮动效果(扩展SortTable)
2009/04/07 Javascript
使用jQuery实现dropdownlist的联动效果(sharepoint 2007)
2011/03/30 Javascript
javascript简单事件处理和with用法介绍
2013/09/16 Javascript
nodeJs爬虫获取数据简单实现代码
2016/03/29 NodeJs
jquery实现全选功能效果的实现代码
2016/05/05 Javascript
每日十条JavaScript经验技巧(二)
2016/06/23 Javascript
vue.js指令v-model实现方法
2016/12/05 Javascript
Webpack中publicPath路径问题详解
2018/05/03 Javascript
用react-redux实现react组件之间数据共享的方法
2018/06/08 Javascript
vue-cli脚手架build目录下utils.js工具配置文件详解
2018/09/14 Javascript
JS/HTML5游戏常用算法之碰撞检测 像素检测算法实例详解
2018/12/12 Javascript
vue + any-touch实现一个iscroll 实现拖拽和滑动动画效果
2019/04/08 Javascript
Python编程实现控制cmd命令行显示颜色的方法示例
2017/08/14 Python
用Python将mysql数据导出成json的方法
2018/08/21 Python
对Python协程之异步同步的区别详解
2019/02/19 Python
Python缓存技术实现过程详解
2019/09/25 Python
有趣的Python图片制作之如何用QQ好友头像拼接出里昂
2020/04/22 Python
python爬虫要用到的库总结
2020/07/28 Python
Python截图并保存的具体实例
2021/01/14 Python
python爬取2021猫眼票房字体加密实例
2021/02/19 Python
HTML5在手机端实现视频全屏展示方法
2020/11/23 HTML / CSS
猫咪家具:CatsPlay
2018/11/03 全球购物
PHP经典面试题
2016/09/03 面试题
营销总经理的岗位职责
2013/12/15 职场文书
开业庆典邀请函
2014/01/08 职场文书
金融保险专业求职信
2014/09/03 职场文书
2014学习优秀共产党员先进事迹材料思想汇报
2014/09/14 职场文书
会计岗位职责
2015/02/03 职场文书
python中tkinter复选框使用操作
2021/11/11 Python