Skip to content

如何理解 ref、toRef 和 toRefs

ref、toRef 和 toRefs 是什么

ref 是什么

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

代码演示

js
<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,具有响应式
  • 两者保持引用关系

代码演示

js
<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
  • 两者保持引用关系

代码演示

js
<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 的最佳使用方式

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

js
// 定义函数
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

基于 MIT 许可发布