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 相关文章推荐
JQuery 获得绝对,相对位置的坐标方法
Feb 09 Javascript
多浏览器兼容性比较好的复制到剪贴板的js代码
Oct 09 Javascript
Javascript 浮点运算的问题分析与解决方法
Aug 27 Javascript
让复选框只能选择一项的方法
Oct 08 Javascript
JS+CSS实现DIV层的展开、收缩效果
Jan 28 Javascript
jQuery插件HighCharts绘制2D带Label的折线图效果示例【附demo源码下载】
Mar 08 Javascript
详解Vue微信授权登录前后端分离较为优雅的解决方案
Jun 29 Javascript
node.js中express模块创建服务器和http模块客户端发请求
Mar 06 Javascript
javascript自定义右键菜单插件
Dec 16 Javascript
Vue实现剪贴板复制功能
Dec 31 Javascript
vue 调用 RESTful风格接口操作
Aug 11 Javascript
JavaScript实现网页下拉菜单效果
Nov 20 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
ThinkPHP模板引擎之导入资源文件方法详解
2014/06/18 PHP
PHP和MySql中32位和64位的整形范围是多少
2016/02/18 PHP
传智播客学习之JavaScript基础篇
2009/11/13 Javascript
javascript获取鼠标位置部分的实例代码(兼容IE,FF)
2013/08/05 Javascript
原生js事件的添加和删除的封装
2014/07/01 Javascript
常用的JS验证和函数汇总
2014/12/23 Javascript
jQuery中:selected选择器用法实例
2015/01/04 Javascript
JavaScript学习笔记之JS事件对象
2015/01/22 Javascript
JavaScript的jQuery库中function的存在和参数问题
2015/08/13 Javascript
关于JavaScript数组你所不知道的3件事
2016/08/24 Javascript
学习JavaScript图片预加载模块
2016/11/07 Javascript
JavaScript实现鼠标点击导航栏变色特效
2017/02/08 Javascript
VueJS 组件参数名命名与组件属性转化问题
2018/12/03 Javascript
mpvue微信小程序多列选择器用法之省份城市选择的实现
2019/03/07 Javascript
vue element-ui读取pdf文件的方法
2019/11/26 Javascript
js实现无缝轮播图特效
2020/05/09 Javascript
[05:01]3.19DOTA2发布会 我们都是刀塔人
2014/03/25 DOTA
10个易被忽视但应掌握的Python基本用法
2015/04/01 Python
Python实现文件按照日期命名的方法
2015/07/09 Python
Python的requests网络编程包使用教程
2016/07/11 Python
Python 搭建Web站点之Web服务器与Web框架
2016/11/06 Python
Python解决走迷宫问题算法示例
2018/07/27 Python
解决python xlrd无法读取excel文件的问题
2018/12/25 Python
解决Python3 控制台输出InsecureRequestWarning问题
2019/07/15 Python
如何修复使用 Python ORM 工具 SQLAlchemy 时的常见陷阱
2019/11/19 Python
墨尔本照明批发商店:Mica Lighting
2017/12/28 全球购物
Ruby如何进行文件操作
2014/07/17 面试题
社区国庆节活动方案
2014/02/05 职场文书
个人自我剖析材料
2014/02/07 职场文书
二手房购房协议书范本
2014/10/05 职场文书
中学教师师德师风承诺书
2015/04/28 职场文书
2016年大学生暑假爱心支教活动策划书
2015/11/26 职场文书
详解python中[-1]、[:-1]、[::-1]、[n::-1]使用方法
2021/04/25 Python
vue3获取当前路由地址
2022/02/18 Vue.js
Python中的嵌套循环详情
2022/03/23 Python
nginx配置限速限流基于内置模块
2022/05/02 Servers