vue3【详解】 vue3 比 vue2 快的原因

简介: vue3【详解】 vue3 比 vue2 快的原因

使用 Proxy 实现响应式

vue3使用的 Proxy 在处理属性的读取和写入时,比vue2使用的defineProperty 有更好的性能(速度加倍的同时,内存还能减半!)

更新类型标记 Patch Flag

在编译模板时(将vue语法转换为js描述的虚拟节点vdom), vue3 对动态节点添加了标记,效果如下:

  • 静态节点无标记
<!-- 静态节点 -->
<span>你好</span>

编译后

_createElementVNode("span", null, "你好")
  • 动态文本节点会标记为1/*TEXT*/
<span>{{msg}}</span>

编译后

_createElementVNode("span", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)

更多vue3模板编译效果可通过下方网站预览

https://template-explorer.vuejs.org/


有了这些动态节点标记,vue3 在diff 算法时便可以跳过对不会发生变化的静态节点的比较,只比较可能发生变化的动态节点,从而提升了 diff 算法的性能,比需要比较静态节点的 vue2 更快!

缓存静态节点 hoistStatic

是一种典型的拿空间换时间的优化策略,具体操作如下:

  • 将静态节点的定义,提升到父作用域,缓存起来(缓存后,就能在之后的编译中跳过编译,从而提升编译速度!)
<span>你好</span>
<span>{{msg}}</span>

编译后

import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

const _hoisted_1 = /*#__PURE__*/_createElementVNode("span", null, "你好", -1 /* HOISTED */)

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createElementBlock(_Fragment, null, [
    _hoisted_1,
    _createElementVNode("span", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ], 64 /* STABLE_FRAGMENT */))
}

可见静态节点被定义为 _hoisted_1 提升到了父作用域,进行了缓存

  • 对超过9个的相邻静态节点进行合并(合并后,优化了代码结构,减小了编译后代码的体积,实现了编译速度的提升!)
<span>你好1</span>
<span>你好2</span>
<span>你好3</span>
<span>你好4</span>
<span>你好5</span>
<span>你好6</span>
<span>你好7</span>
<span>你好8</span>
<span>你好9</span>
<span>你好10</span>

编译后

import { createElementVNode as _createElementVNode, createStaticVNode as _createStaticVNode } from "vue"

const _hoisted_1 = /*#__PURE__*/_createStaticVNode("<span>你好1</span><span>你好2</span><span>你好3</span><span>你好4</span><span>你好5</span><span>你好6</span><span>你好7</span><span>你好8</span><span>你好9</span><span>你好10</span>", 10)

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return _hoisted_1
}

缓存事件 cacheHandler

也是一种典型的拿空间换时间的优化策略,具体操作如下:

  • 给事件添加缓存(在之后的编译中跳过编译,提升编译速度!)
<button @click='save'>保存</button>

编译后

import { openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createElementBlock("button", {
    onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.save && _ctx.save(...args)))
  }, "保存"))
}

_cache[0] || (_cache[0] = ... 的部分,可见使用了缓存(已有缓存,则使用缓存,若无缓存,则重新编译)

SSR 优化

静态节点直接输出,绕过了 vdom

<span>你好</span>
<span>{{msg}}</span>

编译后

import { ssrRenderAttrs as _ssrRenderAttrs, ssrInterpolate as _ssrInterpolate } from "vue/server-renderer"

export function ssrRender(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) {
  const _cssVars = { style: { color: _ctx.color }}
  _push(`<!--[--><span${
    _ssrRenderAttrs(_cssVars)
  }>你好</span><span${
    _ssrRenderAttrs(_cssVars)
  }>${
    _ssrInterpolate(_ctx.msg)
  }</span><!--]-->`)
}

动态节点还是需要动态渲染

tree-shaking

编译时,根据不同的情况,引入不同的 API

<span>你好</span>

编译后

import { openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createElementBlock("span", null, "你好"))
}

再增加一个动态节点

<span>你好</span>
<span>{{msg}}</span>

编译后

import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createElementBlock(_Fragment, null, [
    _createElementVNode("span", null, "你好"),
    _createElementVNode("span", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ], 64 /* STABLE_FRAGMENT */))
}

可见因增加了动态节点,增加了 import 的 API,如 createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, Fragment as _Fragment

目录
相关文章
|
4天前
|
缓存 监控 UED
升级 Vue3 时,如何减少打包体积的增加?
升级 Vue3 时,如何减少打包体积的增加?
81 59
|
3天前
|
JavaScript
在vue3中(vite)引入unocss,安装配置unocss
在vue3中(vite)引入unocss,安装配置unocss
|
5天前
|
缓存 JavaScript 前端开发
「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系
该文章全面覆盖了Vue.js从基础知识到进阶原理的48个核心知识点,包括Vue CLI项目结构、组件生命周期、响应式原理、Composition API的使用等内容,并针对Vue 2与Vue 3的不同特性进行了详细对比与讲解。
「offer来了」从基础到进阶原理,从vue2到vue3,48个知识点保姆级带你巩固vuejs知识体系
|
4天前
|
API UED
如何实现Vue2项目升级Vue3?
如何实现Vue2项目升级Vue3?
11 1
|
6天前
|
JavaScript 前端开发 API
vue3的传送门teleport究竟有多神奇?suspense发起异步请求有多简约?
该文章介绍了Vue3中新特性Teleport和Suspense的使用方法,演示了如何使用Teleport进行DOM节点的非父子关系传送,以及Suspense在处理异步组件加载时的优雅展示和错误处理技巧。
|
4天前
|
API UED
升级 Vue3 后,项目的打包体积会有什么变化?
升级 Vue3 后,项目的打包体积会有什么变化?
9 0
|
5天前
|
JavaScript API
再不学vue3就没有人要你了!速来围观vue3
这篇技术文章介绍了作者从最初对学习 Vue3 抵触到最终决定投入学习的心路历程,展示了 Vue3 相较于 Vue2 的诸多改进和新特性,如更优的性能、更小的代码体积及更佳的 TypeScript 支持。文章重点阐述了 Vue3 中 createApp 的使用变化、emits 机制、多事件处理、Fragment 的引入等重要功能升级。此外,还深入探讨了 Composition API 和 Options API 的区别,强调 Composition API 在代码组织和逻辑复用方面的优势,并给出了在不同项目规模中选择合适 API 的建议。
15 0
|
6天前
|
JavaScript 前端开发 UED
组件库实战 | 用vue3+ts实现全局Header和列表数据渲染ColumnList
该文章详细介绍了如何使用Vue3结合TypeScript来开发全局Header组件和列表数据渲染组件ColumnList,并提供了从设计到实现的完整步骤指导。
|
6天前
|
JavaScript API
模块化妙用!用vue3实现一个鼠标追踪器和异步加载组件
该文章展示了如何使用Vue3的Composition API实现鼠标追踪器功能,并介绍了创建异步加载组件的方法,利用TS泛型增强了组件的灵活性与可维护性。
|
5天前
|
JavaScript
vue组件中的插槽
本文介绍了Vue中组件的插槽使用,包括单个插槽和多个具名插槽的定义及在父组件中的使用方法,展示了如何通过插槽将父组件的内容插入到子组件的指定位置。
下一篇
无影云桌面