vue3 对 vue2 有什么优势

news2024/12/27 12:46:54
1、diff算法的优化--静态标记(PatchFlag)

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

vue3编译模板时,动态节点做标记
标记分为不同的类型,如TEXT,PROPS
diff算法时,可以区分静态节点,以及不同类型的动态节点

vue3新增了静态标记(patchflag)与上次虚拟节点对比时,只对比带有patch flag的节点(动态数据所在的节点);可通过flag信息得知当前节点要对比的具体内容。
我们在Vue Template Explorer 上做测试,我们可以直观的看到对应的静态标记

vue3 静态标记的内容

上面的模板中前第一个段落是静态固定不变的,而第二个段落的内容绑定的HelloWorld属性,当HelloWorld改变的时候,Vue会生成新的虚拟DOM然后和旧的进行对比。

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

算法对比

从上图中可以看出 在vue3中如果是静态文本,更新时则不需要对比,只需要对只对动态节点部分进行diff运算

静态标记枚举了十几个类型,如下:


export const enum PatchFlags {
  
  TEXT = 1,// 1 动态的文本节点
  CLASS = 1 << 1,  // 2 动态的 class
  STYLE = 1 << 2,  // 4 动态的 style
  PROPS = 1 << 3,  // 8 动态属性,不包括类名和样式
  FULL_PROPS = 1 << 4,  // 16 动态 key,当 key 变化时需要完整的 diff 算法做比较
  HYDRATE_EVENTS = 1 << 5,  // 32 表示带有事件监听器的节点
  STABLE_FRAGMENT = 1 << 6,   // 64 一个不会改变子节点顺序的 Fragment
  KEYED_FRAGMENT = 1 << 7, // 128 带有 key 属性的 Fragment
  UNKEYED_FRAGMENT = 1 << 8, // 256 子节点没有 key 的 Fragment
  NEED_PATCH = 1 << 9,   // 512  表示只需要non-props修补的元素
  DYNAMIC_SLOTS = 1 << 10,  // 1024 动态的solt
  DEV_ROOT_FRAGMENT = 1 << 11, //2048 表示仅因为用户在模板的根级别放置注释而创建的片段。 这是一个仅用于开发的标志,因为注释在生产中被剥离。
 
  //以下两个是特殊标记
  HOISTED = -1,  // 表示已提升的静态vnode,更新时调过整个子树
  BAIL = -2 // 指示差异算法应该退出优化模式
}
2、hoistStatic 静态提升

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

  1. 将静态节点的定义,提升到父作用域,缓存起来
  2. 多个相邻的静态节点,会被合并起来,一起定义,这样就会定义一次,避免多次定义

所以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>
11、Teleport
eleport 是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术。
如果我们嵌套在 Vue 的某个组件内部,那么处理嵌套组件的定位、z-index 和样式就会变得很困难。使用Teleport 就可以方便的解决组件间 css 层级问题。

Teleport 的使用
[Teleport](https://v3.cn.vuejs.org/guide/teleport.html#%E4%B8%8E-vue-components-%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8)

[teleport API](https://v3.cn.vuejs.org/api/built-in-components.html#teleport)
最后编辑于:2024-09-25 21:03:31


喜欢的朋友记得点赞、收藏、关注哦!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2197121.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

给新手学ComfyUI的建议,以及几个免费工作流的分享!

前言 这是我学ComfyUI的经历&#xff0c;分享给你们&#xff0c;也许你们可以少走一些弯路。 给新手建议 刚开始学ComfyUI的时候&#xff0c;是想做AI写真的&#xff0c;但是SD一次AI写真都没做过&#xff0c;所以相当于SD零基础。然后我就去哔哩哔哩找教程看&#xff0c;跟…

日常记账:解锁生活财务管理的秘密钥匙

在日常生活的纷繁复杂中&#xff0c;我们往往容易忽视那些细微却重要的财务流动。每一笔支出&#xff0c;无论大小&#xff0c;都是生活乐章中的一个音符。而日常记账&#xff0c;就是那把能够解锁生活财务管理秘密的钥匙。它不仅仅是一种简单的记录行为&#xff0c;更是一种对…

【大学学习-大学之路-回顾-电子计算机相关专业-学习方案-自我学习-大一新生(1)】

【大学学习-大学之路-回顾-电子&计算机相关专业-学习方案-自我学习-大一新生&#xff08;1&#xff09;】 1-前言2-整体说明&#xff08;1&#xff09;打字训练&#xff08;1&#xff09;字母区分大小写&#xff1a;&#xff08;2&#xff09;自动换行&不自动换行&…

Vue3中提到的Tree-shaking

我们知道&#xff0c;Vue3中提到一个叫Tree-shaking的东西&#xff0c;其实也并不是一个新的东西&#xff0c;有人称之为"摇树优化"&#xff0c;什么意思&#xff1f; 按照作者的原话解释&#xff0c;Tree-shaking其实就是&#xff1a;把无用的模块进行“剪枝”&…

小程序配置文件

Author&#xff1a;Dawn_T17&#x1f965; 目录 官方开发文档 配置文件 全局配置文件—app.json pages字段 window字段 tabBar字段 页面配置文件—*.json 项目配置文件 project.config.json 和 project.private.config.json 配置sass以及不同的*SS区别 预处理器…

学习Flask框架

Flask简介 Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug &#xff0c;模板引擎则使用 Jinja2 。Flask使用 BSD 授权。 Flask也被称为 “microframework” &#xff0c;因为它使用简单的核心&#xff0c;用 extension 增加其他功能。Flask没…

ssm淘乐乐员工购物商城

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 目 录 III 第1章 绪论 1 1.1 课题背景 1 1.2 课题意义 1 1.3 研究内容 2 第2章 开发环境与技术 3 …

函数编程:让开发完全专注于代码

作为一名开发者&#xff0c;我过去常常被各种环境配置和部署问题困扰&#xff0c;特别是当项目依赖复杂时&#xff0c;总要花费大量时间在配置服务器、调试环境上。最近&#xff0c;我在使用 TitanIDE 后有了一些全新的开发体验&#xff0c;尤其是它的 函数编程 功能&#xff0…

七、安全运营—概念

控制特权帐号&#xff1a; 账号类型&#xff1a;

众数信科AI智能体智慧文旅解决方案——智能旅行助手

智慧文旅解决方案 智能旅行助手方案 利用先进的AI算法 提供个性化旅游体验的智能服务 众数信科AI智能体 产品亮点 旅游路线智能规划 旅游景点智能问答 旅行游记智能生成等 构建旅行实用指南 让旅游更加便捷、高效、智能化 关于我们 众数信科成立于2021年&#xff0c;由…

操作系统 | 学习笔记 | 王道 | 4.1 文件系统基础

4.文件管理 4.1 文件系统基础 4.1.1 文件的基本概念 定义 文件是以计算机硬盘为载体的存储在计算机上的信息集合&#xff0c;在用户进行的输入、输出中&#xff0c;以文件位基本单位。 文件管理系统是实现的文件的访问、修改和保存&#xff0c;对文件维护管理的系统。 文件的…

Ngx+Lua+Redis 快速存储POST数据

系统几万台设备有windows有安卓还有linux系统&#xff0c;每个设备三分钟就会向服务器post设备的硬件信息&#xff0c;数据格式json&#xff0c;后台管理界面只需要最新的数据&#xff0c;不需要历史数据&#xff0c;业务逻辑非常简单&#xff0c;PHP代码就几行&#xff0c;已经…

Python selenium库学习使用实操四

系列文章目录 Python selenium库学习使用实操 Python selenium库学习使用实操二 Python selenium库学习使用实操三 文章目录 系列文章目录[TOC](文章目录) 前言一、元素获取二、选项解析总结 前言 在Python selenium库学习使用实操二中提到了下拉框的操作&#xff0c;一种是标…

Redis持久化机制(RDBAOF详解)

目录 一、Redis持久化介绍二、Redis持久化方式1、RDB持久化(1) 介绍(2) RDB持久化触发机制(3) RDB优点和缺点(4) RDB流程 2、AOF(append only file)持久化(1) 介绍(2) AOF优点和缺点(3) AOF文件重写(4) AOF文件重写流程 三、AOF和RDB持久化注意事项 一、Redis持久化介绍 Redis…

YOLOv5复现(论文复现)

YOLOv5复现&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 YOLOv5复现&#xff08;论文复现&#xff09;概述模型结构正负样本匹配策略损失计算数据增强使用方式训练测试验证Demo 概述 YOLOv5是由Ultralytics公司于2020年6月开源的目标检…

uniapp顶部提示栏实现

效果&#xff1a; 用途&#xff1a;用于展示较短系统通知 实现逻辑&#xff1a; 1.通过请求获取该显示的通知内容&#xff0c;目前所考虑的字段有&#xff1a; {id: 200, // 通知标识&#xff0c;后续会用其阻止用户关闭后无休止开启message: "请勿以系统规定的其它…

与ZoomEye功能类似的搜索引擎还有哪些?(渗透课作业)

与ZoomEye功能类似的搜索引擎有&#xff1a; Shodan&#xff1a;被誉为“物联网的搜索引擎”&#xff0c;专注于扫描和索引连接到互联网的各种设备&#xff0c;如智能家居设备、工业控制系统、摄像头、数据库等。它提供全球互联网设备的可视化视图&#xff0c;帮助用户了解网络…

ssm图书管理系统的设计与实现

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 摘 要 I Abstract II 第1章 绪论 1 1.1 课题研究背景 1 1.2课题研究现状 1 1.3课题实现目的和意义 …

【C++】模拟实现hash_table(哈希表)

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:实战项目集 ⚙️操作环境:Visual Studio 2022 目录 一.了解项目功能 二.逐步实现项目功能模块及其逻辑详解 &#x1f4cc;实现HashNode类模板 &#x1f38f;构造HashNode类成员变量 &#x1f38f;实现HashNode类构造函数…

高效研究:Zotero的7个插件让你事半功倍

还在为海量文献管理头疼吗?还在为找不到合适的插件犯愁吗?别急,今天我就要带你解锁Zotero的终极武器 - 那些让你爱不释手的必备插件! 作为一个从小白到文献管理达人的过来人,我可以负责任地说:没有这些插件,你的Zotero只能发挥一半功力!安装了这些插件,你的效率绝对能飙升! …