本文已参与「新人创作礼」活动,一起开启掘金创作之路,符合活动条件。
1.关于toRefs
vue官网这样介绍:
将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref
2.为什么需要toRefs
先看一个🌰
<template>
<div>{{count}}</div>
<button @click="changeCount">changeCount</button>
</template>
<script lang='ts'>
import { reactive} from 'vue'
export default {
setup() {
let state=reactive({
count:1
})
function changeCount(){
state.count++
}
return {
...state,
changeCount,
}
}
};
</script>
我们想要的效果: 我在代码中声明了一个state响应式数据,当点击按钮的时候,count会+1
实际上:我们点击按钮的时候,count并不会累加
为什么? return出去的state,相当于
return{
count:1
}
所以,我们需要一个媒介,当我们访问count值的时候,访问到state.count的值
3.先易后难
我们知道,vue3还提供了另一个api:toRef
可以用来为源响应式对象上的某个 property 新创建一个 ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。
比如我们有一个state响应式数据
const state = reactive({
foo: 1,
bar: 2
})
const fooRef = toRef(state, 'foo')
fooRef.value++
console.log(state.foo) // 2
state.foo++
console.log(fooRef.value) // 3
这样我们通过业务逻辑修改state.count的值的时候,模板也会随之修改,那我们该如何toRef实现呢?
4.实现toRef
思路及分析
1.向toRef函数里面传递一个响应式数据state及属性foo,toRef会返回一个对象fooRef,对象上面有一个value属性
2.当读取value属性的时候,会把state.foo的值返回
3.当修改fooRef.value的值的时候,state.foo的值也会同步修改
4.当修改state.foo的值的时候,fooRef.value的值也会同步修改
实现
function toRef(obj,key){
const warpper={
get value(){
//基于第二个问题,读取value,返回state.foo
return obj[key]
},
set value(newValue){
//基于第三个问题,修改时会把新的数据给到state.foo
obj[key]=newValue
}
}
//基于第一个问题,返回一个对象
return warpper
}
基于第四个问题,修改state.foo.state.foo会改变,这是reactive做的事情
这样是不是清晰了很多了
5.实现toRefs
接下来实现toRefs,我们还拿官网的例子来说事情
const state = reactive({
foo: 1,
bar: 2
})
const stateAsRefs = toRefs(state)
/*
stateAsRefs 的类型:
{
foo: Ref<number>,
bar: Ref<number>
}
*/
// ref 和原始 property 已经“链接”起来了
state.foo++
console.log(stateAsRefs.foo.value) // 2
stateAsRefs.foo.value++
console.log(state.foo) // 3
思路及分析
1.将响应式数据作为参数传递给toRefs,返回一个对象stateAsRefs,对象里面有state里面所有的属性:foo和bar
2.读取stateAsRefs.foo.value的值,会将state.foo的值返回回来
2.修改state.foo的值,stateAsRefs.foo.value的值会跟着改变
3.修改stateAsRefs.foo.value的值,state.foo的值也会跟着改变
咦,这个和toRef神似! 之前是将单个属性和响应式数据搭建一个桥梁,现在是将所有的属性和响应式数据state搭建一个桥梁
实现
遍历对象,使每一个属性都toRef一下
function toRefs(obj){
const warpper={}
for (const key in obj) {
//将state所有的属性都放在wrapper里面,并将他们的值toRef,这样就可以和响应式数据的属性搭建起“桥梁”
warpper[key]=toRef(obj,key)
}
//基于第一个问题,返回了一个对象,包裹了state所有的属性
return warpper
}
以上,toRef和toRefs就已经实现了~