摘要:Vue3新版本的理念成型于 2018 年末,当时的 Vue 2 已经有两岁半了。比起通用软件的生命周期来这好像也没那么久,Vue3在2020年正式推出,在源码和API都有较大变化,性能得到了显著的提升,比Vue2.x快1.2~2倍。

本文分享自华为云社区《【云驻共创】vue3 相比 vue2 的十项优点》,作者: 海拥 。

Vue3新版本的理念成型于 2018 年末,当时的 Vue 2 已经有两岁半了。比起通用软件的生命周期来这好像也没那么久,Vue3在2020年正式推出,在源码和API都有较大变化,性能得到了显著的提升,比Vue2.x快1.2~2倍。

其中,一些比较重要的优点有:

diff算法的优化;hoistStatic 静态提升;cacheHandlers 事件侦听器缓存;ssr渲染;更好的Ts支持;Compostion API: 组合API/注入API;更先进的组件;自定义渲染API;按需编译,体积比vue2.x更小;支持多根节点组件等。下面我们就来具体说说vue3 的优点:

优点1:diff算法的优化

vue2中的虚拟dom是全量的对比(每个节点不论写死的还是动态的都会一层一层比较,这就浪费了大部分事件在对比静态节点上)

vue3新增了静态标记(patchflag)与上次虚拟节点对比时,只对比带有patch flag的节点(动态数据所在的节点);可通过flag信息得知当前节点要对比的具体内容。

例如:下面的模板包含一个div,div内包含三个段落,其中前两个段落是静态固定不变的,而第三个段落的内容绑定的msg属性,当msg改变的时候,Vue会生成新的虚拟DOM然后和旧的进行对比。

<div>
<p>云驻共创</p>
<p>如何评价 vue3</p>
<p>{{msg}}</p>
</div>

当视图更新时,只对动态节点部分进行diff运算,减少了资源的损耗。Patchflag是个枚举,取值为1代表这个元素的文本是动态绑定的,取值为2代表元素的class是动态绑定的。

优点2:hoistStatic 静态提升

vue2无论元素是否参与更新,每次都会重新创建然后再渲染。

vue3对于不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用即可。
例如:下面我们利用Vue 3 Template Explorer,来直观的感受一下:

<div>
<div>共创1</div>
<div>共创2</div>
<div>{{name}}</div>
</div>

静态提升之前

export function render(...) {
return (
_openBlock(),
_createBlock('div', null, [
_createVNode('div', null, '共创1'),
_createVNode('div', null, '共创2'),
_createVNode(
'div',
null,
_toDisplayString(_ctx.name),
1 /* TEXT */
),
])
)
}

静态提升之后

const _hoisted_1 = /*#__PURE__*/ _createVNode(
'div',
null,
'共创1',
-1 /* HOISTED */
)
const _hoisted_2 = /*#__PURE__*/ _createVNode(
'div',
null,
'共创2',
-1 /* HOISTED */
) export function render(...) {
return (
_openBlock(),
_createBlock('div', null, [
_hoisted_1,
_hoisted_2,
_createVNode(
'div',
null,
_toDisplayString(_ctx.name),
1 /* TEXT */
),
])
)
}

从以上代码中我们可以看出,_hoisted_1 和_hoisted_2 两个方法被提升到了渲染函数 render 之外,也就是我们说的静态提升。通过静态提升可以避免每次渲染的时候都要重新创建这些对象,从而大大提高了渲染效率。

优点3:cacheHandlers 事件侦听器缓存

vue2.x中,绑定事件每次触发都要重新生成全新的function去更新,cacheHandlers 是Vue3中提供的事件缓存对象,当 cacheHandlers 开启,会自动生成一个内联函数,同时生成一个静态节点。当事件再次触发时,只需从缓存中调用即可,无需再次更新。

默认情况下onClick会被视为动态绑定,所以每次都会追踪它的变化,但是同一个函数没必要追踪变化,直接缓存起来复用即可。

例如:下面我们同样是通过Vue 3 Template Explorer,来看一下事件监听器缓存的作用:

<div>
<div @click="todo">做点有趣的事</div>
</div>

该段 html 经过编译后变成我们下面的结构(未开启事件监听缓存):

export function render(...) {
return (_openBlock(),_createBlock('div', null, [
_createVNode('div',{ onClick: _ctx.todo}, '做点有趣的事', 8 /* PROPS */,
['onClick']),
])
)
}

当我们开启事件监听器缓存后:

export function render(...) {
return (_openBlock(),_createBlock('div', null, [
_createVNode('div',{
onClick: //开启监听后
_cache[1] || (_cache[1] = (...args) =>_ctx.todo(...args)),
},'做点有趣的事'),
])
)
}

我们可以对比开启事件监听缓存前后的代码,转换之后的代码, 大家可能还看不懂, 但是不要紧,我们只需要观察有没有静态标记即可,在Vue3的diff算法中, 只有有静态标记的才会进行比较, 才会进行追踪。

优点4:ssr渲染

Vue2 中也是有 SSR 渲染的,但是 Vue3 中的 SSR 渲染相对于 Vue2 来说,性能方面也有对应的提升。

当存在大量静态内容时,这些内容会被当作纯字符串推进一个 buffer 里面,即使存在动态的绑定,会通过模版插值潜入进去。这样会比通过虚拟 dmo 来渲染的快上很多。

当静态内容大到一个量级的时候,会用_createStaticVNode 方法在客户端去生成一个 static node,这些静态 node,会被直接 innerHtml,就不需要再创建对象,然后根据对象渲染。

优点5:更好的Ts支持

vue2不适合使用ts,原因在于vue2的Option API风格。options是个简单对象,而ts是一种类型系统、面向对象的语法。两者有点不匹配。

在vue2结合ts的具体实践中,要用 vue-class-component 强化 vue 组件,让 Script 支持 TypeScript 装饰器,用 vue-property-decorator 来增加更多结合 Vue 特性的装饰器,最终搞的ts的组件写法和js的组件写法差别挺大。

在vue3中,量身打造了defineComponent函数,使组件在ts下,更好的利用参数类型推断 。Composition API 代码风格中,比较有代表性的api就是 ref 和 reactive,也很好的支持了类型声明。

import { defineComponent, ref } from 'vue'
const Component = defineComponent({
props: {
success: { type: String },
student: {
type: Object as PropType<Student>,
required: true
}
},
setup() {
const year = ref(2020)
const month = ref<string | number>('9')
month.value = 9 // OK
const result = year.value.split('')
}

优点6:Compostion API: 组合API/注入API

传统的网页是html/css/javascript(结构/样式/逻辑)分离。vue通过组件化的方式,将联系紧密的结构/样式/逻辑放在一起,有利于代码的维护。compostion api更进一步,着力于JS(逻辑)部分,将逻辑相关的代码放在一起,这样更有利于代码的维护。

在vue2的组件内使用的是Option API风格(data/methods/mounted)来组织的代码,这样会让逻辑分散,举个例子就是我们完成一个计数器功能,要在data里声明变量,在methods定义响应函数,在mounted里初始化变量,如果在一个功能比较多、代码量比较大的组件里,你要维护这样一个功能,就需要在data/methods/mounted反复的切换到对应位置,然后进行代码的更改。

而在vue3中,使用setup函数。如下所示跟count相关的逻辑,都放到counter.js文件里,跟todo相关的逻辑放到todos.js里。

import useCounter from './counter'
import useTodo from './todos' setup(){
let { val, todos, addTodo } = useTodo()
let {count,add} = useCounter()
return {
val, todos, addTodo,
count,add,
}

优点7:更先进的组件

vue2是不允许这样写的,组件必须有一个跟节点,现在可以这样写,vue将为我们创建一个虚拟的Fragment节点。

<template>
<div>华为云享专家</div>
<div>全栈领域博主</div>
</template>

在Suspended-component完全渲染之前,备用内容会被显示出来。如果是异步组件,Suspense可以等待组件被下载,或者在设置函数中执行一些异步操作。

优点8:自定义渲染API

vue2.x项目架构对于weex(移动端跨平台方案)和myvue(小程序上使用)等渲染到不同平台不太友好,vue3.0推出了自定义渲染API解决了该问题。下面我们先看vue2和vue3的入口写法有哪些不同。

vue2

import Vue from 'vue'
import App from './App.vue'
new Vue({ => h(App)}).$mount('#app')

vue3

const { createApp } from 'vue'
import App from "./src/App"
createApp(App).mount(('#app')

vue官方实现的 createApp 会给我们的 template 映射生成 html 代码,但是要是你不想渲染生成到 html ,而是要渲染生成到 canvas 之类的不是html的代码的时候,那就需要用到 Custom Renderer API 来定义自己的 render 渲染生成函数了。

import { createApp } from "./runtime-render";
import App from "./src/App"; // 根组件
createApp(App).mount('#app');

使用自定义渲染API,如weex和myvue这类方案的问题就得到了完美解决。只需重写createApp即可。

优点9:按需编译,体积比vue2.x更小

框架的大小也会影响其性能。这是 Web 应用程序的唯一关注点,因为需要即时下载资源,在浏览器解析必要的 JavaScript 之前该应用程序是不可交互的。对于单页应用程序尤其如此。尽管 Vue 一直是相对轻量级的(Vue 2 的运行时大小压缩为 23 KB)。

在 Vue 3 中,通过将大多数全局 API 和内部帮助程序移至 ES 模块导出来,实现了这一目标。这使现代的打包工具可以静态分析模块依赖性并删除未使用的导出相关的代码。模板编译器还会生成友好的 Tree-shaking 代码,在模板中实际使用了该功能时才导入该功能的帮助程序。

框架的某些部分永远不会 Tree-shaking,因为它们对于任何类型的应用都是必不可少的。我们将这些必不可少的部分的度量标准称为基准尺寸。尽管增加了许多新功能,但 Vue 3 的基准大小压缩后约为 10 KB,还不到 Vue 2 的一半。

优点10:支持多根节点组件

Vue3 一个模板不再限制有多个根节点,(多个根节点上的 Attribute 继承) 需要显式定义 attribute 应该分布在哪里。否则控制台会给出警告提示。

在 Vue 3 中,组件现在正式支持多根节点组件,即片段!

在 2.x 中,不支持多根组件,当用户意外创建多根组件时会发出警告,因此,为了修复此错误,许多组件被包装在一个中。如下

<template>
<div>
<header>...</header>
<main>...</main>
<footer>...</footer>
</div>
</template>

在 3.x 中,组件现在可以有多个根节点!但是,这确实要求开发者明确定义属性应该分布在哪里。

<template>
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
</template>

结尾想说的

Vue是国内最火的前端框架之一。性能提升,运行速度是vue2的1.2-2倍。

  • 体积更小,按需编译体积vue2要更小。
  • 类型推断,更好的支持ts这个也是趋势。
  • 高级给予,暴露了更底层的API和提供更先进的内置组件。
  • 组合API,能够更好的组织逻辑,封装逻辑,复用逻辑

对未来的展望:

技术总是越新越好,越来越多的企业都升级了vue3;

大型项目,由于对TS的友好越来越多的大型项目可以使用vue3;

作为程序员,我们就应该适应市场,提高自己的竞争力,为加薪提供空间。

点击关注,第一时间了解华为云新鲜技术~

vue3,对比 vue2 有什么优点?的更多相关文章

  1. 简单对比vue2.x与vue3.x响应式及新功能

    简单对比vue2.x与vue3.x响应式 对响应方式来讲:Vue3.x 将使用Proxy ,取代Vue2.x 版本的 Object.defineProperty. 为何要将Object.defineP ...

  2. 想知道Vue3与Vue2的区别?五千字教程助你快速上手Vue3!

    从Vue3发布以来,我就一直对其非常感兴趣,就一直想着将其投入公司的生产中,但是开始考虑到很多不确定性就暂时对一些很小的功能进行一些尝试:慢慢的发现组合式Api的形式非常适合开发(个人感觉),尤其是V ...

  3. vue2升级vue3:vue2 vue-i18n 升级到vue3搭配VueI18n v9

    项目从vue2 升级vue3,VueI18n需要做适当的调整.主要是Vue I18n v8.x 到Vue I18n v9 or later 的变化,其中初始化: 具体可以参看:https://vue- ...

  4. vue3和vue2的区别

    一.Vue3介绍 Vue 新版本的理念成型于 2018 年末,当时 Vue 2 的代码库已经有两岁半了.比起通用软件的生命周期来这好像也没那么久,但在这段时期,前端世界已经今昔非比了 在更新(和重写) ...

  5. 第三十一篇:vue3和vue2的不同

    好家伙 1.为什么会有vue3? Vue2和Vue3的区别 - 简书 (jianshu.com) 貌似是因为他的对手太优秀,所以他也必须进步 2.什么是api? 从文件操作开始谈API. 以C语言为例 ...

  6. vue3与vue2的区别

    全局属性 vue2 对于一些第三方插件,vue2中通常使用prototype原型来挂载到vue对象中 import Vue from 'vue' Vue.prototype.$http=Axiox V ...

  7. vue3和vue2 的区别,vue3和vu2到底哪个好呢?

    vue3 正式发布有两年多了,之前也做过一些学习和研究.vue3 发布后给某培训机构开发了一套vue3课程课件,自己也开源了一套基于vue3的后台管理系统(因为个人懒的原因,半年后才上传到gitHub ...

  8. Vue3 相比 vue2

    Vue3 使用Proxy替代了defineProperty. Proxy 相比于 defineProperty 的优势 Object.defineProperty() 的问题主要有三个: 不能监听数组 ...

  9. 创建vue3项目

    最近准备做一个vue的小项目关于vue3的使用. 首先在vscode全局安装vue脚手架,npm i -g @vue/cli. 然后创建vue项目,vue create mydemo(项目名). 接下 ...

  10. vue3响应式模式设计原理

    vue3响应式模式设计原理 为什么要关系vue3的设计原理?了解vue3构建原理,将有助于开发者更快速上手Vue3:同时可以提高Vue调试技能,可以快速定位错误 1.vue3对比vue2 vue2的原 ...

随机推荐

  1. .Net Core 3.1 服务端配置跨域

    一.在Startup.cs 的 ConfigureServices 配置好跨域策略 原文链接:https://www.jianshu.com/p/534b9a6a6ed5 public void Co ...

  2. JavaScript 简介与引用

    作者:WangMin 格言:努力做好自己喜欢的每一件事 我们通常写好的HTML网页是处于一个静态的效果,在用户体验这一方面就不是很好,给人一种死板的感觉.这里我们就可以用到JavaScript来为网页 ...

  3. UIKit Inside: frame bounds position anchorPoint center

    iOS 中UIView的属性:frame.bounds.center以及CALayer的属性:position.anchorPoint与视图的位置与大小相关,理解这些属性是进行 iOS 视图编码的基础 ...

  4. 企业微信获取code

    String url="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+AuthUtil.APPID   + ...

  5. Go 14周年

    原文在这里. 由 Russ Cox, for the Go team 发布于2023年11月10日 今天,我们庆祝Go开源发布的第十四个生日!Go在过去一年里取得了巨大的进展,发布了两个功能丰富的版本 ...

  6. JavaScript Date转字符串格式

    JavaScript Date转字符串格式

  7. python列表之部分列表——切片

    目录 切片 全索引 半索引 负数索引 遍历切片 复制列表 切片 全索引 我们平常可能需要使用一个列表中的子列表,也就是部分元素,这个时候我们就需要用到切片这个功能啦 要创建切片,就如同range()函 ...

  8. 数据分析人员需要掌握sql到什么程度?

    SQL(Structured Query Language)是用于管理和操作关系型数据库的标准化语言,对于数据分析人员来说,掌握SQL是至关重要的. 在本文中,我们将详细探讨数据分析人员需要掌握SQL ...

  9. 07-Shell运算符

    1.算术运算符 1.1 expr命令 expr 是 evaluate expressions 的缩写,译为"求值表达式".Shell expr 是一个功能强大,并且比较复杂的命令, ...

  10. 吉特日化MES配料工艺参数标准版-第二版

    作者:情缘 出处:http://www.cnblogs.com/qingyuan/ 关于作者:从事仓库,生产软件方面的开发,在项目管理以及企业经营方面寻求发展之路 版权声明:本文版权归作者和博客园共有 ...