首页 > 编程笔记 > JavaScript笔记
阅读:265
Vue3 toRefs()和toRef()函数的用法(附带实例)
在介绍 toRefs() 与 toRef() 函数之前,先来演示使用 reactive() 函数进行代码简化的问题,下面是简化前的代码:
在模板中,每次获取 reactive() 函数中的数据都要写上“state.”,如果需要获取多次,则操作会重复多次。现在想简化一下代码,去掉“state.”,也就是像下面这样编写代码:
同样在 setup() 函数中返回的代码也需要做相应的修改,将 reactive 对象中的 msg、person 和 courses 取出后分别放入返回的对象中。
或者利用扩展运算符简化代码:
如何让从 reactive 对象中读取出的属性也是响应式的呢?答案是:可以利用本节介绍的 toRefs() 和 toRef() 函数。toRefs() 函数能一次性将 reactive 对象包含的所有属性值都包装成 ref 对象,而 toRef 函数只能一次处理一个属性。
详细来说,toRefs() 函数接收一个 reactive 对象,内部会包装每个属性值生成 ref 对象,最后返回包含所有属性值的 ref 对象的对象。而 toRef() 函数接收 reactive 对象和属性名,内部会创建此属性名对应属性值的 ref 对象,并返回这个 ref 对象。
一般我们会使用 toRefs() 函数来解决上面的问题,代码如下:
当然可以进一步简化代码,直接用扩展运算符解构 toRefs() 函数生成的对象。
那么如果使用 toRef() 函数来处理,要如何编写代码呢?可以先多次调用 toRef() 函数生成各个属性的 ref 对象,再添加到返回对象中,代码如下:
当然可以进一步优化成如下代码:
<div id="app">
<ul>
<li>msg: {{state.msg}}</li>
<li>person: {{state.person}}</li>
<li>courses: {{state.courses}}</li>
</ul>
<button @click="updateState">更新 state</button>
</div>
<script>
const { createApp, reactive } = Vue;
createApp({
setup(props, context) {
const state = reactive({
msg: 'Hello World!',
person: { name: 'Tom', age: 22 },
courses: ['JavaScript', 'BOM', 'DOM'],
});
const updateState = () => {
state.msg += '--';
state.person = { name: 'Jack', age: 33 };
state.courses = ['JavaScript2', 'BOM2', 'DOM2'];
};
return {
state,
updateState,
};
},
}).mount('#app');
</script>
在模板中,每次获取 reactive() 函数中的数据都要写上“state.”,如果需要获取多次,则操作会重复多次。现在想简化一下代码,去掉“state.”,也就是像下面这样编写代码:
<ul>
<li>msg: {{msg}}</li>
<li>person: {{person}}</li>
<li>courses: {{courses}}</li>
</ul>
同样在 setup() 函数中返回的代码也需要做相应的修改,将 reactive 对象中的 msg、person 和 courses 取出后分别放入返回的对象中。
return {
msg: state.msg,
person: state.person,
courses: state.courses,
updateMsg,
};
或者利用扩展运算符简化代码:
return {
...state,
updateMsg
};
但是,运行代码并点击按钮更新 msg 后,发现页面上的 msg 显示不会更新。这是因为后面的两种方式传入的 msg、person 和 course 属性值都是非响应式数据,而要想页面能自动更新,必须要求 setup() 函数返回对象中的属性是 ref 对象或 reactive 对象。如何让从 reactive 对象中读取出的属性也是响应式的呢?答案是:可以利用本节介绍的 toRefs() 和 toRef() 函数。toRefs() 函数能一次性将 reactive 对象包含的所有属性值都包装成 ref 对象,而 toRef 函数只能一次处理一个属性。
详细来说,toRefs() 函数接收一个 reactive 对象,内部会包装每个属性值生成 ref 对象,最后返回包含所有属性值的 ref 对象的对象。而 toRef() 函数接收 reactive 对象和属性名,内部会创建此属性名对应属性值的 ref 对象,并返回这个 ref 对象。
一般我们会使用 toRefs() 函数来解决上面的问题,代码如下:
// 生成包含多个 ref 对象的对象
const stateRefs = toRefs(state);
return {
msg: stateRefs.msg,
person: stateRefs.person,
courses: stateRefs.courses,
updateState,
};
当然可以进一步简化代码,直接用扩展运算符解构 toRefs() 函数生成的对象。
return {
...toRefs(state),
updateState,
};
那么如果使用 toRef() 函数来处理,要如何编写代码呢?可以先多次调用 toRef() 函数生成各个属性的 ref 对象,再添加到返回对象中,代码如下:
// 生成各个属性的 ref 对象
const msgRef = toRef(state, 'msg');
const personRef = toRef(state, 'person');
const coursesRef = toRef(state, 'courses');
return {
msg: msgRef,
person: personRef,
courses: coursesRef,
updateState,
};
当然可以进一步优化成如下代码:
return {
msg: toRef(state, 'msg'),
person: toRef(state, 'person'),
courses: toRef(state, 'courses'),
updateState
};
虽然使用 toRefs() 和 toRef() 函数都能解决解构 reactive 对象的属性读取响应式丢失的问题,但从代码可读性上来看,明显使用 toRefs() 函数的代码更简洁。toRef() 函数更适用于只对单个属性进行处理的场景,而 toRefs() 函数更适用于对所有属性进行处理的场景。
ICP备案:
公安联网备案: