1. 写法不一样
Vue2 使用选项式 api,逻辑比较分散、可读性差、可维护性差;
Vue3 使用组合式 api,逻辑分明、可维护性高;他也可以向下兼容支持使用选项式 api;
2. 双向数据绑定实现原理不同
Vue2 基于 Object.defineProperties() 方法实现;
Vue3 基于 proxy 实现;
proxy 与 Object.defineProperty(obj, prop, desc) 方式相比有以下优势:
- 丢掉麻烦的备份数据;
- 省去 for in 循环;
- 可以监听数组变化;
- 代码更简化;
- 可以监听动态新增的属性;
- 可以监听删除的属性;
- 可以监听数组的索引和 length 属性;
3. Vdom 对比方式不同
Vue2 每次更新 diff,都是全量对比;
Vue3 则是对动态属性和动态文本打了标记,这个标记就叫做 patch flag(补丁标记),只对比带有标记的,这样大大减少了非动态内容的对比消耗;
patch flag 的强大之处在于,当你的 diff 算法走到 _createBlock 函数的时候,会忽略所有的静态节点,只对有标记的动态节点进行对比,而且在多层的嵌套下依然有效。
尽管 JavaScript 做 Vdom 的对比已经非常的快,但是 patch flag 的出现还是让 Vue3 的 Vdom 的性能得到了很大的提升,尤其是在针对大组件的时候。
4. Vue3 新增 Fragment
Vue3 允许支持多个根节点
<template>
<div>12</div>
<div>23</div>
</template>
同时支持render JSX 写法
render() {
return (
<>
{this.isShow? (
<div>{this.obj.m}</div>
) : (
<div>{this.obj.n}</div>
)}
<input v-model={this.text}></input>
{[3,4,5,6].map((i) => {
return <div>--{i}--</div>;
})}
</>
);
},
Vue3 还同时新增了Suspense teleport 和 多 v-model 用法:
<template>
<Suspense>
<template #fallback>
<div class="loading">Loading...</div>
</template>
<HelloWorld />
</Suspense>
</template>
<script>
import { defineAsyncComponent } from 'vue'
const HelloWorld = defineAsyncComponent(() =>
import('./components/HelloWorld.vue')
)
</script>
Suspense应用场景:对于需要加载外部数据或资源的组件,使用Suspense可以提升用户体验,避免页面出现不完整的组件;
<template>
<div>
<!-- 正常渲染的按钮 -->
<button @click="showModal = true">打开模态框</button>
<!-- Teleport组件,将模态框内容渲染到body标签下 -->
<teleport to="body">
<div v-if="showModal" class="modal">
<!-- 模态框内容 -->
<p>这是一个模态框</p>
<button @click="showModal = false">关闭</button>
</div>
</teleport>
</div>
</template>
<script>
export default {
data() {
return {
showModal: false
};
}
}
</script>
teleport 应用场景:适用于模态框、弹出菜单等需要独立于组件层次结构进行布局的场景;
<template>
<custom-input
v-model:firstName="user.firstName"
v-model:lastName="user.lastName"
/>
</template>
<script>
export default {
components: {
CustomInput: {
props: {
modelValueFirstName: String,
modelValueLastName: String,
},
template: `
<input
:value="modelValueFirstName"
@input="$emit('update:modelValueFirstName', $event.target.value)"
/>
<input
:value="modelValueLastName"
@input="$emit('update:modelValueLastName', $event.target.value)"
/>
`,
},
},
data() {
return {
user: {
firstName: '',
lastName: '',
},
};
},
}
</script>
多 v-model 应用场景:适合复杂表单场景,如一个表单中有多个表单项需要双向绑定;
5. Vue3 Tree shaking
简单来讲,就是在保持代码运行结果不变的前提下,去除无用的代码;
Vue2中,无论我们使用什么功能,它们最终都会出现在生产代码中。主要原因是Vue实例在项目中是单例的,捆绑程序无法检测到该对象的哪些属性在代码中被使用到;
而Vue3源码引入tree shaking特性,将全局 API 进行分块。如果你不使用其某些功能,它们将不会包含在你的基础包中;
就是比如你要用watch 就是import {watch} from 'vue' 其他的computed 没用到就不会给你打包减少体积。
6. 组件使用方式不同
Vue2 中使用组件需要先引入,在注册,然后再使用;
Vue3 中则是引入之后直接就可以使用,无需注册;
<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
</script>
<template>
<div>
<HelloWorld msg="sfes"/>
</div>
</template>