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
属性
toRefs
<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
的。
好了,内容就这么多,喜欢就点个小赞,欢迎有问题的小伙伴到下方评论。