# 前言
vue 经历从 2.0 到 3.0 更新之后,简⽽⾔之就是变得更轻,更快,使⽤起来更加⽅便,每⼀次的版本迭代都是对上⼀个版本的升级优化,不管 是对于我们开发者还是对于⽤户体验都是不断地在越来越⽅便,接下来我会着重于开发者来说⼀下两个不同版本的区别,
# 详解
1.vue2.0 和 3.0 的初始化就存在着⼀定区别,⽐如 vue3.0 可以在安装脚⼿架同时提前安装好⼀些项⽬开发必备的插件,并且 3.0 提供了可视 化创建脚⼿架,可以更加⽅便的对插件和依赖进⾏管理和配置,同时两个版本的⽬录结构也是有些许差别的。
2.在开发过程中两个版本的使⽤⽅法虽然在表⾯上没有太⼤的⼀个区别,但是在他的底层⽅⾯去看的话区别还是很⼤的,其中就包括渲染⽅ 式,数据监听,双向绑定,⽣命周期,vue3 更精准变更通知,
这⾥着重说⼀下关于双向绑定的更新,
vue2 的双向数据绑定是利⽤ ES5 的⼀个 API ,Object.definePropert()对数据进⾏劫持 结合 发布订阅模式的⽅式来实现的。
vue3 中使⽤了 es6 的 ProxyAPI 对数据代理,通过 reactive() 函数给每⼀个对象都包⼀层 Proxy,通过 Proxy 监听属性的变化,从⽽ 实现对数据的监控。
这⾥是引相⽐于vue2版本,使⽤proxy的优势如下
1.defineProperty只能监听某个属性,不能对全对象监听
可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可)
2.可以监听数组,不⽤再去单独的对数组做特异性操作,通过Proxy可以直接拦截所有对象类型数据的操作,完美⽀持对数组的监听。
3.另外 vue3 还新增了⼀些内置组件和⽅法,⽐如 vue3 可以默认进⾏懒观察,使⽤ Function-based API,setup 函数,对与插件或对象的⼀ 个按需引⼊,Computed Value ,新加⼊了 TypeScript 以及 PWA 的⽀持等等… 这⾥着重说⼀下 vue3 的⼀个按需引⼊
Vue2.x 中 new 出的实例对象,所有的东西都在这个 vue 对象上,这样其实⽆论你⽤到还是没⽤到,都会跑⼀遍,这样不仅提⾼了性能消耗, 也⽆疑增加了⽤户加载时间。 ⽽ vue3.0 中可以⽤ ES module imports 按需引⼊,如:keep-alive 内置组件、v-model 指令,等等,不仅我们开发起来更加的便捷,减少 了内存消耗,也同时减少了⽤户加载时间,优化⽤户体验
# 创建 vue2 和 vue3 项目的文件发生的变化
//vue2.0
import Vue from "vue";
new Vue({
el: "#app",
render: (h) => h(App),
}).$mpount("#app");
//vue3.0
import { createApp } from "vue";
import App from "./App.vue";
createApp(App).mount("#app");
核心代码: createApp(App).mount('#app') = createApp(根组件).mount('public/index.html 中的 div 容器') 1.vue2.0 中是直接创建了一个 vue 实例 2.vue3.0 中按需导出了一个 createApp (ceateApp 做了什么) 3.vue3 中的 app 单文件不再强制要求必须有根元素 也就是说 在 vue2.0 中必须要有一个根元素,在 vue3 中没这个要求
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js App" />
</template>
# 数据双向绑定原理
Vue2 使⽤的是 Object.defineProperty()进⾏数据劫持,结合发布订阅的⽅式实现。
Vue3 使⽤的是 Proxy 代理,使⽤ ref 或者 reactive 将数据转化为响应式数据
# vue2.0 Object.defineProperty
Object.defineProperty()是 ES5 中提供给我们的 API,它⽀持给对象添加属性, 同时还能监听属性变化。
Object.defineProperty()的参数:
- 第一个参数:要定义或修改的属性名称
- 第二个参数:定义或修改的属性描述符 属性描述符:
- value:指定属性的值
- writable:指定属性是否可以被修改
- enumerable:指定属性是否可以被枚举
- configurable:指定属性是否可以被删除或是否可以再次修改特性
let obj = {};
Object.defineProperty(obj, "name", {
value: "张三",
enumerable: true,
configurable: true,
writable: true,
});
console.log(obj.name); // 张三
obj.name = "李四";
console.log(obj.name); // 李四
# vue3.0 proxy
Proxy 代理的原理:
- 拦截对象属性的读取和赋值
- 拦截数组的读取和赋值
- 拦截函数的调用
const obj = {
name: "张三",
age: 18,
};
const proxy = new Proxy(obj, {
get(target, key) {
return target[key];
},
set(target, key, value) {
target[key] = value;
},
});
console.log(proxy.name); // 张三
proxy.name = "李四";
console.log(proxy.name); // 李四
# vue data
// vue2.0
export default {
data() {
return {
name: "张三",
age: 18,
};
},
};
// vue3.0
export default {
setup() {
return {
name: "张三",
age: 18,
};
},
};
# vue computed
// vue2.0
export default {
data() {
return {
name: "张三",
age: 18,
};
},
computed: {
nameLength() {
return this.name.length;
},
},
};
// vue3.0
export default {
setup() {
return {
name: "张三",
age: 18,
};
},
computed: {
nameLength() {
return this.name.length;
},
},
};
# vue2.0 watch
// vue2.0
export default {
data() {
return {
name: "张三",
age: 18,
};
},
watch: {
name(newName, oldName) {
console.log(newName, oldName);
},
},
};
// vue3.0
export default {
setup() {
return {
name: "张三",
age: 18,
};
},
watch: {
name(newName, oldName) {
console.log(newName, oldName);
},
},
};
# 发布订阅模式
发布订阅模式是⾯向⽅向对象的,⽽ Vue2 使⽤的是对象,⽽ Vue 3 使⽤的是 Proxy 代理,使⽤ ref 或者 reactive 将数据转化为响应式数据
# 数据劫持的缺陷
- 无法监听对象新增的属性
- 无法监听数组的变化