《Vue进阶教程》第三十四课:toRefs的使用
往期内容:
《Vue进阶教程》第二十三课:渲染计算属性的结果
《Vue进阶教程》第二十四课:优化
《Vue进阶教程》第二十五课:watch基本概念
《Vue进阶教程》第二十六课:实现侦听函数
《Vue进阶教程》第二十七课:实现侦听对象
《Vue进阶教程》第二十八课:实现新旧值
《Vue进阶教程》第二十九课:立即执行的回调
《Vue进阶教程》第三十课:watchEffect
《Vue进阶教程》第三十一课:ref的初步实现
《Vue进阶教程》第三十二课:ref响应丢失问题
《Vue进阶教程》第三十三课:toRef的使用
1) 基本使用
为了解决在赋值过程中响应丢失问题, Vue3提供了两个API
- toRef: 解决赋值问题
- toRefs: 解决展开, 解构问题
toRefs的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://unpkg.com/vue@3.2.41/dist/vue.global.js"></script>
</head>
<body>
<script>
const { reactive, effect, toRef, toRefs } = Vue
// obj是reactive创建的响应式数据(proxy代理对象)
const obj = reactive({ foo: 1, bar: 2 })
// 使用toRefs解构赋值 取代 {foo, bar} = obj
const { foo, bar } = toRefs(obj)
effect(() => {
console.log('bar.value具有响应性', bar.value)
})
</script>
</body>
</html>
toRefs的实现
基本实现
function toRefs(obj) {
const ret = {}
for (const key in obj) {
ret[key] = toRef(obj, key)
}
return ret
}
原码解读
1源码中对obj的类型做了判断
a如果不是reactive类型的对象, 提示警告
b支持代理是数组的情况
vue3.2.41源码- toRefs实现
function toRefs(object) {
// 如果传入的对象不具备响应性, 提示警告
if (!isProxy(object)) {
console.warn(
`toRefs() expects a reactive object but received a plain one.`
)
}
// 支持代理是数组的情况
// - 对象的情况: toRefs(reactive({foo: 1, bar: 2})) => {foo: ref(1), bar: ref(2)}
// - 数组的情况: toRefs(reactive(['foo', 'bar'])) => [ref('foo'), ref('bar')]
const ret = isArray(object) ? new Array(object.length) : {}
for (const key in object) {
ret[key] = toRef(object, key)
}
return ret
}
测试用例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="./reactive.js"></script>
</head>
<body>
<script>
// obj是响应式数据
const obj = reactive({ foo: 1, bar: 2 })
// 解构赋值
const { foo, bar } = toRefs(obj)
effect(() => {
console.log('foo.value具备响应性:', foo.value)
})
</script>
</body>
</html>