跳到主要内容

如何理解 ref、toRef 和 toRefs

ref、toRef 和 toRefs 是什么

ref 是什么

  • 生成值类型的响应式数据
  • 可用于模板和 reactive
  • 通过 .value 修改值
  • 通过 ref 获取 dom

代码演示

<template>
<p ref="elemRef">ref demo {{ nameRef }} {{ state.age }}</p>
</template>

<script>
import {ref, reactive, onMounted} from 'vue'

export default {
name: "Ref",
setup() {
// 值类型 响应式
const nameRef = ref('lzw.')
const ageRef = ref(20)

const state = reactive({
name: nameRef,
age: ageRef
})

// 通过 .value 获取值修改值
setTimeout(() => {
console.log('ageRef', ageRef.value)
ageRef.value = 25 // .value 修改值
nameRef.value = 'lzw. A'
}, 2000)

// 通过 ref 获取 dom 元素
const elemRef = ref(null)
onMounted(() => {
console.log('elemRef', elemRef.value.innerHTML) // elemRef ref demo lzw. 20
})

return {
nameRef,
state,
elemRef
}
}
}
</script>

toRef 是什么

  • 针对一个响应式对象(reactive 封装)的 prop(属性)
  • 创建一个 ref,具有响应式
  • 两者保持引用关系

代码演示

<template>
<p ref="elemRef">toRef demo {{ state.name }}{{ state.age }} - {{ ageRef }}</p>
</template>

<script>
import {toRef, reactive} from 'vue'

export default {
name: "Ref",
setup() {
// 对象实现响应式,使用 reactive
const state = reactive({
name: 'lzw.',
age: 20
})

// toRef 如果用于非响应式对象,产出的结果不具备响应式
// const state = {
// name: 'lzw.',
// age: 20
// }

// 响应式对象的一个属性实现响应式,使用 toRef
const ageRef = toRef(state, 'age')
setTimeout(() => {
state.age = 25 // state.age 和 ageRef 保持引用关系
}, 1000)
setTimeout(() => {
ageRef.value = 30 // state.age 和 ageRef 保持引用关系
}, 1000)

return {
state,
ageRef
}
}
}
</script>

toRefs 是什么

  • 将响应是对象(reactive 封装)转为普通对象
  • 对象的每个 prop(属性) 都是对应的 ref
  • 两者保持引用关系

代码演示

<template>
<p ref="elemRef">toRefs demo {{ name }} {{ age }}</p>
</template>

<script>
import {toRefs, reactive} from 'vue'

export default {
name: "toRefs",
setup() {
// 对象实现响应式,使用 reactive
const state = reactive({
name: 'lzw.',
age: 20
})

// 将响应式对象变为普通对象,同时保留响应式
const stateAsRefs = toRefs(state)

// 每个属性,都是 ref 对象
// const {name: nameRef, age: ageRef} = stateAsRefs

setTimeout(() => {
state.age = 25
},1000)

return stateAsRefs
}
}
</script>

ref toRef 和toRefs 的最佳使用方式

合并函数返回响应式对象,比如

// 定义函数
function useFeatureX() {
const state = reactive({
x: 1,
y: 2
})

// 返回时转为 ref
return toRefs(state)
}

export default {
setup() {
// 可以在不失去响应性的情况下破坏结构
const {x, y} = useFeatureX()
return {x, y}
}
}
  • 用 reactive 做对象的响应式,用 ref 做值类型响应式
  • setup 中返回 toRefs(state),或者 toRef(state,'xxx')
  • ref 的变量命名都用 xxxRef
  • 合并函数返回响应式对象时,使用 toRefs