vue3 响应式
学会ref, reactive, toRef, toRefs彻底掌握vue3响应式应用。
1. ref
ref函数一般用于基本数据类型,包括(string,number,boolean等),也可以用于对象,但是该对象仅仅包含一属性,例如({age:20});
1.1 ref 基本数据类型
<div class="home">
<h1>员工姓名原始值:{{ name }}</h1>
<h1>员工姓名:{{ ref_name }}</h1>
<h1>年龄:{{ age }}</h1>
<button @click="change">修改</button>
</div>
setup() {
let name = "zha san";
let ref_name = ref(name);
console.log(ref_name);
}
return {
name,
ref_name,
age,
change,
};
打印输出的ref返回的是一个RefIml对象,响应值存在这个对象的value属性中。
所以如果我们想修改响应数据的值,必须修改ref_name的value值,界面的值才会发生刷新。
function change() {
ref_name.value = "li si";
console.log("name:", name);
console.log(ref_name);
}
此处我们需要注意,原始值name的值并没有改变,依旧是“zha san”。
修改后页面展示如下:
另外我们可以改变原始值,但是原始值{{ name }}的绑定并不会更新成“wang wu”.
function change() {
name = "wang wu";
}
1.2 Ref 单属性对象
<div class="home">
<h1>员工姓名原始值:{{ data.name }}</h1>
<h1>员工姓名:{{ ref_data.name }}</h1>
<button @click="change">修改</button>
</div>
setup() {
let data = { name: "zha san" };
let ref_data = ref(data);
console.log(data.name);
console.log(ref_data);
function change() {
ref_data.value.name = "li si";
console.log("原始name值依旧是:", data.name);
console.log(ref_data);
}
return {
data,
ref_data,
change,
};
点击修改后:
可见用对象作为Ref参数,原始值也受到了影响,因为对象传递的是引用值。
1.3 Ref对象属性
与1.2的代码改动如下:
<h1>员工姓名:{{ ref_data }}</h1>
let ref_data = ref(data.name);
修改后:
发现原始值并没有改变,因为这是值拷贝。
2. reactive
reactive函数的参数一般为引用类型,如(Object, Array),如果我们直接传入基本数据类型,vue会给我们一个警告,并且直接返回基本数据类型的值。
通过以上的示例我们发现,用Ref变量,当我们需要修改绑定数据的时候需要修改value属性(template里不需要加value是因为编译时已经处理过了),那么我们能不能优化一下上面的代码,不使用value呢? 答案是肯定的,就是用reactive。
<div class="home">
<h1>员工姓名原始值:{{ name }}</h1>
<h1>员工姓名:{{ reactive_data.name }}</h1>
<h1>年龄:{{ reactive_data.age }}</h1>
<button @click="change">修改</button>
</div>
setup() {
let data = {
name: "zha san",
age: 18,
};
let reactive_data = reactive(data);
console.log(reactive_data);
function change() {
reactive_data.name = "li si2";
console.log("原始name值改变为:", data.name);
console.log(reactive_data);
}
return {
data,
reactive_data,
change,
};
},
我们来看一下reactive长什么样子:
点击修改后:
我们发现原始值和响应值都改变了,这也是引用传递的结果。
这里我们顺便解构一下reacitvie对象,已不是响应式对象:
console.log({ ...reactive_data });
3. toRefs
细心的读者可能已经发现了,我们上面teplate绑定的时候还是需要加一个data前缀,我们改如何去掉它呢?对了,就是用toRefs函数。toRefs对象接受一个reactive对象,代码如下:
<div class="home">
<h1>员工姓名原始值:{{ data.name }}</h1>
<h1>员工姓名:{{ name }}</h1>
<h1>年龄:{{ age }}</h1>
<button @click="change">修改</button>
</div>
setup() {
let data = {
name: "zha san",
age: 18,
};
let reactive_data = reactive(data);
let refs = toRefs(reactive_data);
console.log(refs);
function change() {
reactive_data.name = "li si2";
console.log("原始name值改变为:", data.name);
console.log(refs);
}
return {
data,
...refs,
change,
};
},
refs对象如下:
点击修改后toRefs的值为:
4 toRef
此函数接收两个参数,第一个参数为原对象,第二个参数为对象中的某一个属性名。
<div class="home">
<h1>员工姓名原始值:{{ data.name }}</h1>
<h1>员工姓名:{{ ref }}</h1>
<button @click="change">修改</button>
</div>
setup() {
let data = {
name: "zha san",
};
let ref = toRef(data, "name");
console.log(ref);
function change() {
ref.value = "li si2";
console.log("原始name值改变为:", data.name);
console.log(ref);
}
return {
data,
ref,
change,
};
},
toRef返回对象格式如下:
点击修改后:
发现原始值也改变了,证明这里跟Ref比,传递的是引用值,实际上是就是同一个对象。
但是修改数据后界面并不会刷新!!!
只要大家掌握了这几种响应式的区别,明白响应式的核心是proxy。开发中可以根据实际情况灵活运用,并不拘泥用哪一个~~~
最后如有疑问,欢迎各位提出宝贵意见~~