写点什么

当使用 Vue2+Babel 时,如何实现组件重新渲染

作者:DisonTangor
  • 2022 年 1 月 16 日
  • 本文字数:2958 字

    阅读完需:约 10 分钟

在以前,我们写好静态的 html 后,多数的动态渲染是交给 jquery 来重写的,这样的操作无疑增加了维护的复杂性。于是,我们开始对老系统前端上使用了Vue 2.0 + Babel的架构。

为什么说 Vue 比 jQuery 好呢?

这主要从他们的原理着手。jq 主要运用 Vanilla JS 的选择器机制。通过选择器筛选整个 html 页面的 DOM,然后使用链式函数来处理数据或重新渲染。相比之下,Vue.js 2.x 引入 Virtual DOM,比 Vue.js 1.x 的初始渲染速度提升了 2-4 倍,并大大降低了内存消耗。Virtual DOM 的概念最初由 Google 工程师提出,后在 Meta 的React框架中得到大规模的运用。相比于频繁的手动去操作 dom 而带来性能问题,vdom 很好的将 dom 做了一层映射关系,进而将在我们本需要直接进行 dom 的一系列操作,映射到了操作 vdom,而 vdom 上定义了关于真实 dom 的一些关键的信息,vdom 完全是用 js 去实现,和宿主浏览器没有任何联系,此外得益于 js 的执行速度,将原本需要在真实 dom 进行的创建节点,删除节点,添加节点等一系列复杂的 dom 操作全部放到 vdom 中进行,这样就通过操作 vdom 来提高直接操作的 dom 的效率和性能。不仅如此,它也受 MVVM 的思想的影响,支持模块化及模板等功能。开发过程在就可以将 html 页面重新组织为多个View Model 从而降低前端开发的重复工作的时间成本。


虽然去年 Vue 升级到了第 3 版,但考虑稳定的生产环境,还是就目前情况推荐文档较多(其他开发者的踩坑文档)的 Vue2。

Babel 让 IE 也能支持 ES6 的编译器

在国内绝大多数的生产环境都还是 2010 年的 Web 产物居多。并不是所有的公司都能拥有如 BAT 这样紧随时代技术的开发人员。例如一些地方的发票系统,还有一些院校或公共设施的后台系统。当然,也有一些例外,12306 据说是委派拥有 BAT 相似能力的公司做的——神奇的验证功能(某个清华毕业生做的)。因此,项目至少需要保留 ES2015 的支持。


由此,我就找到了 babel 这个工具。只能说外国工程师和国内的不一样(腾讯和百度各自直接开发了一个浏览器,兼容当时的 IE、FF、Chrome——加个 Ad 就能 ZQ)。

ES6 和 ES5 的特点

ES6 包括以下重要特性:

ES6 特性

  1. 箭头:这些是由 '=>' 语法描述的函数

  2. 对象:对象字面量用于支持原型分配。

  3. Classes: ES6 类可以通过基于原型的面向对象模式轻松实现

  4. Destructing:它允许绑定模式,这主要基于模式匹配。

  5. 字符串插值

  6. 缺省

  7. 传播

  8. 模块加载器

  9. Weak set

  10. Map

  11. New Library

  12. Promises

  13. Proxies


ECMA Script 的第五版被称为 ES5 和 ECMA Script 2009。ES5 包括以下重要特性:

ES5 功能

  1. Strict Mode:它基本上通过应用更多检查和清理一些现有功能来帮助 javascript 语言更有效地执行

  2. Accessors :它允许用户通过使用方法来实现属性的获取和设置。

  3. 语法变化:

  4. 尾随逗号

  5. 多行字符串文字

  6. 使用保留字的属性键

  7. 附加功能:在 ES5 中引入了一些附加的新功能。

  8. 元编程:不同的原型用于相同的

  9. Object.getPrototypeOf()

  10. Object.create()

  11. Object.defineProperty()

  12. Object.keys()

  13. Object.seal()

  14. Object.freeze() etc.

  15. 新方法

  16. String.prototype.trim()

  17. Array.isArray()

  18. Array.prototype.indexOf()

  19. Array.prototype.map()

  20. 括号运算符的使用

  21. JSON:

  22. JSON.parse()

  23. JSON.stringify()

  24. 特定于 JSON 的内置对象:

  25. Boolean.prototype.toJSON()

  26. Number.prototype.toJSON()

  27. String.prototype.toJSON()


相较而言两者语法:我更觉得 ES6 有了很多编译型语言的特性,而且语法更为简易,事实上也属于 ES5 和 TS 之间的过渡语言。最重要的是可以基于面对对象(原型)进行开发和维护。

Vue 坑:

在 Vue 中,也存在一些坑。我就简单介绍一个常见的

Vue 重新渲染

Vue 重新渲染的方法其实有很多种。如 Michael Thiessen 所言:


  • 可怕的方式:重新加载整个页面

  • 可怕的方式:使用 v-if hack

  • 更好的方法:使用 Vue 的内置 forceUpdate 方法

  • 最佳方法:在组件上更换 Key

可怕的方式:重新加载整个页面

相当于每次要关闭应用程序时重新启动计算机


window.location.reload();
复制代码
可怕的方式:使用 v-if hack

Vue 附带了一个指令,该指令仅在为 true 时才会呈现组件。如果为 false,则该组件将根本不存在于 DOM.


以下是我们如何设置它以使 hack 工作.


你可以添加 template


<template>    <component v-if="renderComponent" /></template>
复制代码


在你的方法中使用 scriptnextTick


export default {    data() {        return {            renderComponent: true,        };    },    methods: {        forceRerender() {            // Remove component from the DOM            this.renderComponent = false;
this.$nextTick(() => { // Add the component back in this.renderComponent = true; }) } }}
复制代码


这里主要是通过 Vue 的生命周期原理来实现的。

更好的方法:使用 Vue 的内置 forceUpdate 方法

如果 Vue 在事情发生变化时自动更新,我们为什么要强制更新?


原因是有时 Vue 的反应系统可能会令人困惑,我们认为 Vue 会对某个属性或变量的更改做出反应,但实际上并非如此。在某些情况下,Vue 的反应系统根本不会检测到任何变化。


因此,就像最后的方法一样,如果您需要它来重新渲染组件,则可能有更好的方法。


您可以通过两种不同的方式在组件实例本身上以及全局调用 :forceUpdate


// Globallyimport Vue from 'vue';Vue.forceUpdate();
// Using the component instanceexport default { methods: { methodThatForcesUpdate() { // ... this.$forceUpdate(); // Notice we have to use a $ here // ... } }}
复制代码
最佳方法:在组件上更换 Key

Vue 中 key 属性的作用



最简单的做法:


<template>    <component-to-re-render :key="componentKey" /></template>
export default { data() { return { componentKey: 0 }; }, methods: { forceRerender() { this.componentKey += 1; } }}
复制代码


每次被调用时,我们的道具都会改变。当这种情况发生时,Vue 将知道它必须销毁组件并创建一个新组件。forceRerendercomponentKey


你得到的是一个子组件,它将重新初始化自身并"重置"它的状态。


一个简单而优雅的方式来解决我们的问题!


但是,如果您确实需要重新渲染某些内容,请选择 key-changing 方法而不是其他任何方法。

Babel 中 this 定义为 undefined

在 Babel 的箭头语法中会出现 this 定义为 undefined。遇到这种情况往往需要将自己的箭头函数改为常用的 function 语句就可以了。

babel 编译

package.js


"dependencies": {    "babel-cli": "^6.26.0",    "babel-polyfill": "^6.26.0",    "babel-preset-env": "^1.7.0",    "babel-preset-es2015": "^6.24.1",    "babel-preset-es2015-ie": "^6.7.0"}
复制代码


命令为:


$ ./node_modules/babel-cli/bin/babel.js --presets babel-preset-es2015-ie \    target.js -o output.js
复制代码


推荐编写 bash、zsh、bat 之类的脚本来实现批处理。

感谢

写作不宜,请多多支持。同时也非常感谢参考文档中的作者。


参考文档:


  1. Priya Pedamkar 的 Difference Between ES6 vs ES5

  2. Michael Thiessen 的 强制 Vue 重新渲染组件的正确方法

  3. 考拉比利 的 Vue中key属性的作用

  4. michaelnthiessen.com 的 The Key Changing Technique

  5. Babel replaces this with undefined

发布于: 刚刚阅读数: 2
用户头像

DisonTangor

关注

怀揣一个武侠梦的男孩 2020.07.29 加入

还未添加个人简介

评论

发布
暂无评论
当使用Vue2+Babel时,如何实现组件重新渲染