Vue.js 3.0 在 Vue 2.0 的基础上进行了全面升级,以下是主要区别和核心改进:
1. 响应式系统重构
特性 | Vue 2.0 | Vue 3.0 |
---|
实现方式 | 基于 Object.defineProperty | 基于 Proxy (原生代理) |
性能 | 递归遍历对象属性,初始化较慢 | 按需代理,性能提升 2~3 倍 |
数组监听 | 需重写数组方法(如 push ) | 直接监听数组索引变化 |
动态属性增删 | 需用 Vue.set /Vue.delete | 直接操作对象即可 |
2. Composition API
特性 | Vue 2.0(Options API) | Vue 3.0(Composition API) |
---|
代码组织 | 按选项(data , methods )分隔 | 按逻辑功能聚合(类似 React Hooks) |
复用性 | Mixins 容易冲突 | 自定义 Hook 函数,复用无副作用 |
TypeScript 支持 | 有限 | 完美支持 |
示例 | ```js | ```js |
| export default { | import { ref, computed } from 'vue'; |
| data() { return { count: 0 } }, | export default { |
| methods: { increment() { ... }} | setup() { |
| } | const count = ref(0); |
| | const double = computed(() => count.value * 2); |
| | return { count, double }; |
| | } |
| | } |
3. 性能优化
特性 | Vue 2.0 | Vue 3.0 |
---|
虚拟 DOM | 全量比对(性能较低) | 静态标记(Patch Flag),跳过静态节点比对 |
Tree-Shaking | 不支持,全量引入 | 支持按需引入,打包体积减少 41% |
SSR 优化 | 传统流式渲染 | 基于 @vue/server-renderer ,性能更高 |
4. 新特性
特性 | Vue 2.0 | Vue 3.0 |
---|
Fragment | 单根节点限制 | 支持多根节点(减少无意义包裹) |
Teleport | 无 | 传送组件到指定位置 |
Suspense | 无 | 支持异步组件加载状态管理 |
自定义渲染器 | 实现复杂 | 通过 createRenderer 轻松扩展(如小程序渲染) |
5. 生命周期变化
Vue 2.0 | Vue 3.0(Composition API) |
---|
beforeCreate | 无(使用 setup 替代) |
created | 无(使用 setup 替代) |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
errorCaptured | onErrorCaptured |
6. 废弃特性
Vue 2.0 特性 | Vue 3.0 状态 |
---|
Filters (过滤器) | 废弃,推荐用计算属性或方法替代 |
EventBus (全局事件总线) | 推荐用 provide/inject 或第三方库(如 Mitt) |
$on /$off | 移除,改用第三方事件库 |
7. 生态兼容
工具/库 | Vue 2.0 | Vue 3.0 |
---|
Vue Router | Vue Router 3 | Vue Router 4 |
Vuex | Vuex 3 | Vuex 4(或推荐 Pinia) |
DevTools | 支持 | 全新插件,支持 Composition API |
Vue 2.0:基于 Object.defineProperty
的响应式
实现原理
对象劫持:
- 通过
Object.defineProperty
递归遍历对象的所有属性,将每个属性转换为 getter/setter
。 - 缺点:初始化时需要全量遍历,性能较差(尤其是大对象)。
function defineReactive(obj, key) {
let value = obj[key];
Object.defineProperty(obj, key, {
get() {
// 依赖收集(将当前 Watcher 添加到 Dep 中)
dep.depend();
return value;
},
set(newVal) {
if (newVal === value) return;
value = newVal;
// 触发更新(通知所有 Watcher)
dep.notify();
}
});
}
数组监听:
- 重写数组的
push
、pop
、shift
、unshift
、splice
、sort
、reverse
方法,手动触发更新。 - 缺点:无法检测通过索引直接修改数组(如
arr[0] = 1
)。
const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(method => {
const original = arrayProto[method];
Object.defineProperty(arrayMethods, method, {
value: function(...args) {
const result = original.apply(this, args);
// 手动触发更新
this.__ob__.dep.notify();
return result;
}
});
});
动态属性限制:
- 新增或删除属性时无法自动触发更新,需使用
Vue.set
或 Vue.delete
。
Vue 3.0:基于 Proxy
的响应式
实现原理
代理对象:
- 使用
Proxy
代理整个对象,通过 get
和 set
陷阱函数实现动态监听。 - 优点:无需递归遍历,按需代理,性能显著提升。
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
// 依赖收集
track(target, key);
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
const oldValue = target[key];
const result = Reflect.set(target, key, value, receiver);
if (oldValue !== value) {
// 触发更新
trigger(target, key);
}
return result;
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key);
// 删除属性时触发更新
trigger(target, key);
return result;
}
});
}
- 惰性依赖收集:
- 只有在访问属性时才会收集依赖(
track
),避免不必要的性能损耗。
- 深度代理:
- 数组和集合类型的支持:
- 原生支持数组索引操作(如
arr[0] = 1
)。 - 支持
Map
、Set
、WeakMap
、WeakSet
等复杂数据结构。
function get(target, key) {
const res = Reflect.get(target, key);
// 如果是对象,继续代理
return isObject(res) ? reactive(res) : res;
}
核心对比
特性 | Vue 2.0 | Vue 3.0 |
---|
实现方式 | Object.defineProperty (属性级) | Proxy (对象级) |
初始化性能 | 全量递归,性能低 | 按需代理,性能高 |
动态属性 | 需 Vue.set /Vue.delete | 直接操作即可触发响应 |
数组监听 | 重写方法,无法监听索引操作 | 原生支持索引操作 |
复杂数据结构 | 不支持 Map /Set | 完整支持 |
内存占用 | 每个属性创建闭包,内存占用高 | 共享代理,内存占用低 |
示例代码对比
Vue 2.0 的动态属性问题
javascript复制// 需要 Vue.set 触发更新
this.$set(this.obj, 'newKey', 'value');
// 直接赋值无效
this.obj.newKey = 'value'; // 不会触发更新
Vue 3.0 的直接操作
javascript复制// 直接操作即可触发更新
this.obj.newKey = 'value'; // 自动触发响应
delete this.obj.oldKey; // 自动触发响应
总结
- Vue 2.0 的响应式系统通过
Object.defineProperty
实现,存在性能瓶颈和动态属性限制。 - Vue 3.0 基于
Proxy
重构,实现了按需代理、动态属性监听、复杂数据结构支持,性能提升显著。