oboard

oboard

https://oboard.eu.org/
github
email
tg_channel
medium

Vue Vapor Mode深度解析:开启无虚拟DOM的高效JavaScript编译策略

Vapor Mode是 Vue.js没有虚拟 DOM的一种编译策略,将代码编译成高效的 JavaScript 输出,使用占用的内存,减轻运行时的负担,减小编译后的体积,从而提高 Vue.js 应用的性能。
可以通过Vue Vapor SFC Playground体验 Vapor Mode,
通过Vue Volar Template Explorer探究模板的转换方式。

工作方式

性能对比

如何在自己的 Vite 项目中开启 Vapor Mode#

Demo 参考 sxzz/vue-vapor-demo

将 vue 和 @vitejs/plugin-vue 的版本升级为 vapor 版
package.json

"dependencies": {
	"vue": "npm:@vue-vapor/vue@latest"
},
"devDependencies": {
    "@vitejs/plugin-vue": "npm:@vue-vapor/vite-plugin-vue@latest",
}

createApp 改为 createVaporApp

import { createVaporApp } from 'vue/vapor'
import './style.css'
import App from './App.vue'

const create = createVaporApp
create(App as any).mount('#app')

检测 Vapor 是否开启的方法#

import { ref, getCurrentInstance } from 'vue'

const msg = ref('Hello World!')

// @ts-expect-error
const isVapor = getCurrentInstance().vapor

探索 Vapor Mode 编译后的 js#

这里我们编写一个极为简单的 vue 文件,来探索 Vapor Mode 的编译产物

<script setup lang="ts">
import { ref } from 'vue'
const msg = ref('Hello World!')
const classes = ref('p')
</script>

<template>
<h1 :class="classes">{{ msg }}</h1>
</template>

VAPOR ON

/* Analyzed bindings: {
"ref": "setup-const",
"msg": "setup-ref"
} */
import { defineComponent as _defineComponent } from 'vue/vapor'
import { renderEffect as _renderEffect, setText as _setText, setClass as _setClass, template as _template } from 'vue/vapor';
const t0 = _template("<h1></h1>")
import { ref } from 'vue'

const __sfc__ = _defineComponent({
	vapor: true,
	__name: 'App',
	setup(__props) {
	
	const msg = ref('Hello World!')
	
	return (() => {
		const n0 = t0()
		_renderEffect(() => _setText(n0, msg.value))
		_renderEffect(() => _setClass(n0, classes.value))
		return n0
	})()
	}
})
__sfc__.__file = "src/App.vue"
export default __sfc__

VAPOR OFF

/* Analyzed bindings: {
"ref": "setup-const",
"msg": "setup-ref"
} */
import { defineComponent as _defineComponent } from 'vue'
import { toDisplayString as _toDisplayString, normalizeClass as _normalizeClass, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

import { ref } from 'vue'

const __sfc__ = _defineComponent({
	__name: 'App',
	setup(__props) {
		const msg = ref('Hello World!')
		const classes = ref('p')
		return (_ctx,_cache) => {
			return (_openBlock(), _createElementBlock("h1", {
				class: _normalizeClass(classes.value)
			}, _toDisplayString(msg.value), 3 /* TEXT, CLASS */))
		}
	}
})
__sfc__.__file = "src/App.vue"
export default __sfc__

Vapor Mode 开启时的编译产物特点:#

  1. 模板编译:使用_template函数来定义模板,这个函数是 Vue 内部用于生成模板的函数。
  2. 渲染效果:使用_renderEffect来处理响应式数据的渲染,这是一个优化版的渲染函数,用于在 Vapor Mode 下更高效地更新 DOM。
  3. 文本设置:使用_setText函数来设置元素的文本内容,这表明 Vapor Mode 使用了一种更直接的方式来更新文本节点。

Vapor Mode 关闭时的编译产物特点:#

  1. 模板编译:使用传统的createElementBlock来创建元素,这是 Vue 标准编译流程中用于生成虚拟 DOM 节点的函数。
  2. 文本转换:使用_toDisplayString来将数据转换为可显示的字符串,这是 Vue 在处理数据绑定时的标准做法。
  3. 块级渲染:使用_openBlock来处理块级渲染,这是 Vue 在处理多个同级节点时的标准做法。

编译产物的对比:#

  • 性能优化:Vapor Mode 的编译产物进行了更多的优化,以减少运行时的 DOM 操作和提高渲染效率。
  • API 使用:Vapor Mode 下使用的 API(如_renderEffect_setText)与标准模式下的 API 有所不同,为了实现更高效的渲染逻辑。

Vapor Mode API#

  1. renderEffect:此函数负责监听类、属性和文本的更改,以确保在更新时对这些节点进行正确的更改。
  2. setClass:顾名思义,此函数将类分配给节点元素。它接受两个参数:一个 element(或 node)和它分配给元素的 class。
  3. setDynamicProp:此函数用于设置元素上的动态属性。它需要三个参数:element、key 和 value。这些用于确定每次调用此函数时分配或更新的适当值。
  4. setText:此函数接受一个 node 和可能的值。它将给定的值设置为节点的 textContent,同时还验证内容是否已被修改。
  5. template:此函数接受一个有效的 HTML 字符串并从中创建一个元素。检查该函数时,我们可以看到它使用基本的 DOM 操作方法。具体来说,使用 document.createElement 创建元素。然后使用 innerHTML 追加元素的内容,innerHTML 接受 HTML 字符串。

总结#

2024 年,Vue 的 Vapor Mode 革新了前端开发领域,以其卓越的性能提升,为 Vue 生态系统带来了前所未有的变革。我们满怀期待地展望 Vapor Mode 在未来的表现,相信它将为开发者带来更加流畅和高效的开发体验。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。