ref
ref 用于生成值类型的响应式数据,可用于模板和 reactive。在 reactive 和模板中不需要使用 .value
来读取和修改值,其他 JS 代码中都需要使用 .value
来读取和修改值。
1 | <p>Ref demo {{ageRef}} {{state.name}}</p> |
1 | import { ref, reactive } from 'vue' |
为什么要用 .value ?
ref 函数接受参数并将其包装在具有 value 属性的对象中,然后将其用于访问或更改反应变量的值:
1 | import { ref } from 'vue' |
因为值类型会丢失响应式,因此需要引用类型。因此把 ref 函数返回对象,把真正要存的值放在这个对象的 value 属性里,通过 value 属性的 get 和 set 实现响应式。因此读取值的时候也需要加上 .value
,而用于模板、reactive 时,不需要使用 .value
。(因为模板和 reactive 都是经过 Vue 编译的,Vue 内部会给它解决,而其他情况得自己解决。)
补充:ref 还可以用于获取 dom 节点
1 | <p ref="elemRef">我是一行文字</p> |
1 | import { ref, onMounted } from 'vue' |
toRef
toRef 针对一个响应式对象(reactive 封装)的 prop,创建一个 ref,然后可以将 ref 传递出去,从而保持对其源属性的响应性连接。
1 | const state = reactive({ |
toRef 如果用于普通对象(就是非 reactive 封装的 非响应式对象),则产出的结果可以显示出来,但是不具备响应式。
toRefs
将响应式对象(reactive 封装)转换成普通对象,其中所得对象的每个属性都 ref 指向原始对象的相应属性。
1 | const state = reactive({ |
为什么需要 toRefs ?
我们先看一个示例:
1 | <p>{{state.age}} - {{state.name}}</p> |
1 | export default { |
我们可以看到,我们使用 state 属性的时候,前面都需要加上 state.
,这样很麻烦。
我们在看一个使用了 toRefs 的示例:
1 | <p>{{age}} - {{name}}</p> |
1 | export default { |
变成普通对象后可以直接返回,在模板中使用时不用再使用 state.XXX
的形式了,便捷了很多。
但是为什么不能直接像下面这样将 state 解构返回,再在模板中使用 和 呢?
1 | return { |
因为这样会将 age 和 name 的响应性破坏掉!这样解构出来的属性是没有响应性的。
因此 toRefs 用于合成函数返回响应式对象非常有用,它可以使组件可以对返回的对象进行解构/扩展而不会失去响应性:
1 | function useFeatureX() { |
toRef 和 toRefs 的初衷就是在不丢失响应式的情况下,把对象数据解构,针对的是 reactive 封装的响应式对象而非普通对象。
注意:toRef 和 toRefs 不是创造响应式,而是延续响应式(创造响应式是 ref 和 reactive 的事情)