toRef
- 作用:创建一个ref对象,其value值指向另一个对象中的某个属性。
- 语法:const name = toRef(person,‘name’)
- 应用:要将响应式中的某个属性单独提供给外部使用时。
- 扩展:toRefs与toRef功能一致,但可以批量创建多个ref对象。
代码示例
<template>
<h2>个人信息</h2>
<p>姓名:{{ person.name }}</p>
<p>姓名:{{ person.age }}</p>
<p>工资:{{ person.job.salary.current }}</p>
<button @click="person.age++">++</button>
<button @click="person.job.salary.current++">++工资</button>
<button @click="person.name += '!'">打招呼</button>
</template>
<script>
import { reactive } from "vue";
export default {
setup() {
const person = reactive({
name: "张三",
age: 18,
job: {
salary: {
current: 20,
},
},
});
return {
person,
};
},
};
</script>
先来看一个问题,如下修改为什么数据不是响应式的。
<template>
<h2>个人信息</h2>
<p>姓名:{{ name }}</p>
<p>姓名:{{ age }}</p>
<p>工资:{{ current }}</p>
<button @click="age++">++</button>
<button @click="current++">++工资</button>
<button @click="name += '!'">打招呼</button>
</template>
<script>
import { reactive } from "vue";
export default {
setup() {
const person = reactive({
name: "张三",
age: 18,
job: {
salary: {
current: 20,
},
},
});
return {
name: person.name,
age: person.age,
current: person.job.salary,
};
},
};
</script>
通过一个例子可以说明这种情况
<script>
let person = {
name: "张三",
age: 18,
};
let p = new Proxy(person, {
set(target, propName, value) {
console.log(`${propName}被修改了`);
Reflect.set(target, propName, value);
},
});
</script>
这是正常的响应式。修改一下代码,再打印
<script>
let person = {
name: "张三",
age: 18,
};
let p = new Proxy(person, {
set(target, propName, value) {
console.log(`${propName}被修改了`);
Reflect.set(target, propName, value);
},
});
let name = p.name;
</script>
打印后会发现,并没有打印代表响应式的一段关键console.log。name只是新定义的一个变量。写let name = p.name,实际上是let name = “张三”,是个普通的字符串,上面的vue中一段代码,其实就以下示例代码,说明了以上vue中为什么这样写,数据不是响应式的原因。
<script>
import { reactive } from "vue";
export default {
setup() {
const person = reactive({
name: "张三",
age: 18,
job: {
salary: {
current: 20,
},
},
});
return {
name: "张三",
age: 18,
current: 20,
};
},
};
</script>
toRef
<template>
<h2>个人信息</h2>
<p>姓名:{{ person.name }}</p>
<p>姓名:{{ person.age }}</p>
<p>工资:{{ person.job.salary.current }}</p>
<button @click="person.age++">++</button>
<button @click="person.job.salary.current++">++工资</button>
<button @click="person.name += '!'">打招呼</button>
</template>
<script>
import { reactive, toRef } from "vue";
export default {
setup() {
const person = reactive({
name: "张三",
age: 18,
job: {
salary: {
current: 20,
},
},
});
const name1 = person.name;
console.log("---", name1);
const name2 = toRef(person, "name");
return {
person,
};
},
};
</script>
toRef将普通的数据转换成Ref对象 修改代码如下,打印如下
<template>
<h2>个人信息</h2>
<p>姓名:{{ name }}</p>
<p>姓名:{{ person.age }}</p>
<p>工资:{{ person.job.salary.current }}</p>
<button @click="person.age++">++</button>
<button @click="person.job.salary.current++">++工资</button>
<button @click="person.name += '!'">打招呼</button>
</template>
<script>
import { reactive, toRef } from "vue";
export default {
setup() {
const person = reactive({
name: "张三",
age: 18,
job: {
salary: {
current: 20,
},
},
});
return {
name: toRef(person, "name"),
person,
};
},
};
</script>
显示正常 再来看一个例子和打印
<template>
<h2>个人信息</h2>
<p>姓名:{{ name }}</p>
<p>姓名:{{ age }}</p>
<p>工资:{{ current }}</p>
<button @click="age++">++</button>
<button @click="current++">++工资</button>
<button @click="name += '!'">打招呼</button>
</template>
<script>
import { ref, reactive, toRef } from "vue";
export default {
setup() {
const person = reactive({
name: "张三",
age: 18,
job: {
salary: {
current: 20,
},
},
});
return {
name: ref(person.name),
age: ref(person.age),
current: ref(person.job.salary.current),
};
},
};
</script>
你会发现页面可以正常更新。 再来试验以下,实际更新情况
<template>
<h2>个人信息{{person}}</h2>
<p>姓名:{{ name }}</p>
<p>姓名:{{ age }}</p>
<p>工资:{{ current }}</p>
<button @click="age++">++</button>
<button @click="current++">++工资</button>
<button @click="name += '!'">打招呼</button>
</template>
<script>
import { ref, reactive, toRef } from "vue";
export default {
setup() {
const person = reactive({
name: "张三",
age: 18,
job: {
salary: {
current: 20,
},
},
});
return {
person,
name: ref(person.name),
age: ref(person.age),
current: ref(person.job.salary.current),
};
},
};
</script>
打印会发现,源数据没有发生变化,这种情况是因为 用toRef存在引用关系,在以上代码return时用Ref仅仅是修改自定义的(person.name,person.age,…)值,相当于复制源数据的name,age并修改,并不是修改源数据。 最终改成
<template>
<h2>个人信息{{ person }}</h2>
<p>姓名:{{ name }}</p>
<p>姓名:{{ age }}</p>
<p>工资:{{ current }}</p>
<button @click="age++">++</button>
<button @click="current++">++工资</button>
<button @click="name += '!'">打招呼</button>
</template>
<script>
import { ref, reactive, toRef } from "vue";
export default {
setup() {
const person = reactive({
name: "张三",
age: 18,
job: {
salary: {
current: 20,
},
},
});
return {
person,
name: toRef(person, "name"),
age: toRef(person, "age"),
current: toRef(person.job.salary, "current"),
};
},
};
</script>
toRefs
toRefs是可以批量处理属性
<template>
<!-- <h2>个人信息{{ person }}</h2>
<p>姓名:{{ name }}</p>
<p>年龄:{{ age }}</p>
<p>工资:{{ current }}</p> -->
<button @click="age++">++</button>
<button @click="current++">++工资</button>
<button @click="name += '!'">打招呼</button>
</template>
<script>
import { reactive, toRefs } from "vue";
export default {
setup() {
const person = reactive({
name: "张三",
age: 18,
job: {
salary: {
current: 20,
},
},
});
const a = toRefs(person);
console.log("a", a);
return {
};
},
};
</script>
你会发现,返回的是一个ref对象,注意,最终return时不能直接return toRefs(person),必须通过…toRefs(person)结构,不然就是返回一个对象,是会报语法错误的。这样写的好处就是在模板中不用像ref,返回person,模板中也要用到person,更加方便一些。
|