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

在以前,我们写好静态的 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. 附加功能:在 ES5 中引入了一些附加的新功能。
    • 元编程:不同的原型用于相同的
      • Object.getPrototypeOf()
      • Object.create()
      • Object.defineProperty()
      • Object.keys()
      • Object.seal()
      • Object.freeze() etc.
    • 新方法
      • String.prototype.trim()
      • Array.isArray()
      • Array.prototype.indexOf()
      • Array.prototype.map()
    • 括号运算符的使用
    • JSON:
      • JSON.parse()
      • JSON.stringify()
    • 特定于 JSON 的内置对象:
      • Boolean.prototype.toJSON()
      • Number.prototype.toJSON()
      • String.prototype.toJSON()

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

Vue坑:

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

Vue重新渲染

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

  • 可怕的方式:重新加载整个页面
  • 可怕的方式:使用v-if hack
  • 更好的方法:使用 Vue 的内置forceUpdate方法
  • 最佳方法:在组件上更换Key
可怕的方式:重新加载整个页面

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

扫描二维码关注公众号,回复: 13667200 查看本文章
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

// Globally
import Vue from 'vue';
Vue.forceUpdate();

// Using the component instance
export 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

猜你喜欢

转载自juejin.im/post/7053673994884481054
今日推荐