前言
Vue3 中可以通过响应式 API 来创建响应式对象,相较于 Vue2 中使用 Object.definProperty 来劫持 get 和 set 不同,Vue3 中使用的是 Proxy 来创建响应式对象,使用Proxy有以下几点优势:
1. 对象新增属性不再需要手动 $set 添加响应式,Proxy 默认会监听动态添加属性和属性的删除等操作。
2. 消除无法监听数组索引,length 属性等等,不再需要在数组原型对象上重写数组的方法。
3. Object.defineproperty 是劫持所有对象属性的 get/set 方法,需要遍历递归去实现,Proxy 是代理整个对象。
4. Vue2 只能拦截对象属性的 get 和 set 操作,而 Proxy 拥有 13 种拦截方法。
下面介绍了Vue3中最常用搞定几个响应式函数ref、reactive、computed、watch
ref,接受一个内部值,返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value
ref中可以是基本数据类型也可以是引用数据类型
// 基本类型
let username = ref('xujingliang');
// 引用类型
let submitForm = ref({'username':'xujingliang','password':'123456'})
// 访问值
console.log(username.value);
console.log(submitForm.value.username);
// 修改值
username.value = "liudehua";
submitForm.value.username = "liudehua";
* 在template模版中使用ref响应式数据直接写名字即可
* 但是在js中如果想引用或者修改ref的值则需要加上.value属性来访问和修改值
reactive ,返回一个对象的响应式代理。
reactive中的值只能是引用类型,即对象、数组
let userInfo = reactive({'username':'xujingliang','password':'123456'});
let userList = reactive([
{'username':'xujingliang','password':'123456'},
{'username':'xujingliang','password':'123456'}
]);
// 访问userInfo中的值
console.log(userInfo.username);
// 修改userInfo中的值
userInfo.username = 'liudehua';
* 在template模版中使用reactive响应式数据直接写名字即可
* 与ref不同,在js中访问和修改reactive的值只需要访问变量名即可
总结:ref和reactive学完了,二者都是实现响应式数据,那么什么时候用ref?什么时候用reactive你知道吗?
下面我就总结了常见的几种情况
变量类型 | 使用方式 |
对象 | 当变量为Object时适合使用reactive来定义 |
数组 | 1、如果数组内容赋值后不变动,很适合用reactive,比如从接口请求到的下拉选项,字典; |
数字、字符、布尔值 |
reactive不支持基本数据类型,只能用ref了 |
computed,计算属性computed是依赖于使用它的数据,当数据发生变化时,自定义方法重新调用执行一次计算属性,监测的是依赖值,依赖变化的情况下才会重新计算。
请输入数量:
请输入单价:
数量:{{count}},单价:{{price}},总共{{sum}}
在实例代码中我们定义了响应式变量 商品数量:count 和 响应式变量 商品单价price,通过计算数量和单价之后,获取响应式数据商品总价的值sum;
watch,当需要在数据变化时执行异步或开销较大的操作时,computed是无法操作异步数据的,所以需要使用watch进行侦听。
侦听器watch作用是侦听一个或多个数据的变化,数据变化时执行的回调函数,两个额外参数:immediate(立即执行)和deep(深度侦听)
状态:{{state}}
示例代码中,我们通过点击按钮使响应式数据count自增,通过watch监听count的值变化进行操作。
状态:{{state}}
示例代码中,我们通过点击按钮分别使响应式数据count和price自增,通过watch监听count和price的值变化进行操作。
在上述代码示例中,我添加了两个参数,一个是immediate,一个是deep
immediate:在侦听器创建时立即触发回调,响应式数据变化之后继续执行回调,其语法格式如下。
deep:通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行。