如何理解 ref
toRef
toRefs
细节的知识点,在整个 Composition API 中算是比较难理解的。
ref 和 reactive 结合起来使用,更是难以理解。 既然有 reactive ,为何还要 ref 呢
ref
( 创建响应式对象一般用 reactive
)
用法 :
第一,响应式 (代码参考
RefBasic.vue
)
生成值类型的响应式数据
可直接用于模板和 reactive中 ( 不需要
.value
)可通过
.value
修改值
第二,模板引用 -> 获取dom元素(代码参考
RefTemplate.vue
)
toRef
可以用来为源响应式对象上的 property 新创建一个 ref。然后可以将 ref 传递出去,从而保持对其源 property 的响应式连接。
针对一个响应式对象 ( reactive 封装 )的 property
创建一个 ref 具有响应式
两者保持引用关系
【注意】必须是响应式对象,普通对象不具有响应式。
toRefs
代码参考 ToRefs.vue
将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref 。
将响应式对象 ( reactive 封装 )转换为普通对象 obj
对象的每个属性都是对应的 ref
保持引用关系
【注意】必须是响应式对象,普通对象不具有响应式。
当从合成函数返回响应式对象时,toRefs 非常有用。
( 直接使用 ...解构
响应式对象会使得其丢失响应性)
这样消费组件就可以在不丢失响应性的情况下对返回的对象进行分解/扩散:
function useFeatureX() {
const state = reactive({
x: 1,
y: 2
})
// 逻辑运行状态,省略 N 行
// 返回时转换为ref
return toRefs(state)
}
export default {
setup() {
// 可以在不失去响应性的情况下破坏结构
const { x, y } = useFeatureX()
return {
x,
y
}
}
}
ref 和 reactive
既然有 reactive ,为何还要 ref 呢?
返回值类型,会丢失响应式
如在 setup、computed、合成函数,都有可能返回值类型
Vue 如不定义 ref ,用户将自造 ref ,反而混乱
代码参考 ref/WhyRef.vue
为何需要 .value
因为要保证响应式,需要把值类型封装成一个对象形式,所以用
.value
表示这个值通过 .value 属性的 get 和 set 实现响应式
模板中 和 reactive 使用时,不需要
.value
其他情况都需要
.value
结合 computed 的内部实现,可如下解释:
// 伪代码:不具有响应式,即改变值不会触发渲染
function computed(getter) {
let value
watchEffect(() => {
value = getter() // value 是值类型,值拷贝,value 的变化不会传递到下游
})
return value
}
// 伪代码:具有响应式
function computed(getter) {
const ref = {
value: null,
}
watchEffect(() => {
ref.value = getter() // ref 是引用类型,指针拷贝,ref 的变化会传递到下游
})
return ref
}
上述代码,可以把 watchEffect
改为 setTimeout
模拟一下
再聊 toRef 和 toRefs
设计初衷:不丢失响应性的情况下对返回的对象进行分解/扩散
必须存在:因为直接 property 或者
...state
,会直接拿到属性的值。如果属性是值类型,则会丢失响应式 !!!(响应式是 Proxy 实现的)注意事项:不创造响应式,而是延续响应式 (所以针对普通对象不行,必须是响应式对象)
toRef toRefs 必须针对一个响应式对象,普通对象是无法变成响应式的。 它俩的设计初衷,本来也是针对响应式对象的 组合式 API 常见问答 | Vue.js 即,想要实现响应式,只有两个方法:ref
reactive
ref
创造响应式
toRef
和toRefs
延续响应式
为何必须使用 toRef(state, 'name')
和 toRefs(state)
??? 因为直接 property 或者 ...state
,会直接拿到属性的值。如果属性是值类型,则会丢失响应式。(响应式是 Proxy 实现的) 这也是引入 ref
的根源!!! 也是引入 Composition API ,抛弃 this ,带来的结果。
从使用角度
理解和应用要分开总结,这很重要。即便你听不懂原理,也要知道如何使用。
ref 值类型响应式
ref 模板引用
setup 返回时用
toRefs(state)
用于第三方的逻辑函数,如 demo 中的
useMousePosition
为所有的 ref 名加类似
xxxRef
的后缀
ref 和 reactive 混合起来,真的非常乱。 相比之下,React Hooks 只有 useState
,反而简单很多。—— 当然它也有其他的一些理解成本。