toRef / toRefs
作用
toRef 和 toRefs 可以用来复制 reactive 里面的属性然后转成 ref,而且它既保留了响应式,也保留了引用,也就是你从 reactive 复制过来的属性进行修改后,除了视图会更新,原有 ractive 里面对应的值也会跟着更新,如果你知道 浅拷贝 的话那么这个引用就很好理解了,它复制的其实就是引用 + 响应式 ref
不加 s 和 加 s 的区别就是这样:
toRef: 复制 reactive 里的单个属性并转成 ref
toRefs: 复制 reactive 里的所有属性并转成 ref
下面我会为这两个属性举一些使用案例
使用方式
toRef
<template>
<h2>
reactive-greet: {{ info.greet }}
</h2>
<h2>
toRef-greet: {{ rGreet }}
</h2>
<button @click="onChangeGreet">更换问候语</button>
</template>
<script>
import { reactive, toRef } from 'vue'
export default {
setup() {
let info = reactive({
name: 'Tony',
greet: 'Hello'
})
// 复制 info 里的 greet 属性
let rGreet = toRef(info, 'greet')
// 更改 rGreet
const onChangeGreet = () => {
rGreet.value = 'world!'
}
return {
info,
rGreet,
onChangeGreet
}
}
}
</script>
我们可以看到,更改了 rRgeet
也同时更改了原有的 info.greet
属性
<template>
<h2>
reactive-info-greet: {{ info.greet }}
</h2>
// 要带上 .value
<h2>
toRefs-rInfo-greet: {{ rInfo.greet.value }}
</h2>
<button @click="onChangeGreet">更新</button>
</template>
<script>
import { reactive, toRefs } from 'vue'
export default {
setup() {
let info = reactive({
name: 'Tony',
greet: 'Hello'
})
// 复制整个 info
let rInfo = toRefs(info)
// 更改 rInfo.greet
const onChangeGreet = () => {
rInfo.greet.value = 'world!'
}
return {
info,
rInfo,
onChangeGreet
}
}
}
</script>
怎么样,是不是很简单,这两个属性作用是一样的,唯一的区别就是访问方式不同
- template 要想访问 toRefs 的值,需要带上
.value
如果不带上,就会出现双引号。- template 要想访问 toRef 的值,不需要带上
.value
<template>
<h2>
x: {{ x }}
</h2>
<h2>
y: {{ y }}
</h2>
</template>
<script>
import { reactive, toRefs } from 'vue'
export default {
setup() {
// 封装位置函数
function usePosition(state, x, y) {
const position = reactive({
x: 0,
y: 0
})
// 绑定鼠标移动事件
const onMouseMove = (event) => {
position.x = event.x
position.y = event.y
}
window.addEventListener('mousemove', onMouseMove)
// 返回出去
return toRefs(position)
}
// 接受 x, y 位置
const {x, y} = usePosition()
return {
x,
y
}
}
}
</script>
我们可以看到,案例中将提前封装好的 usePosition 函数通过 toRefs 返回一个响应式的数据,然后直接拿来就用。
我们还可以将它放到 js 文件里面去,在需要的地方引入进来即可,无需再去重复声明,笔者甚至认为这两属性就是用来避免重复声明 reactive 的。