toRef toRefs toRaw
toRef
如果原始对象是非响应式的,就不会更新视图,数据是不会变的
<template>
<div>
<div>foo: {{obj.foo}}</div>
<div>bar: {{obj.bar}}</div>
<div>state: {{state}}</div>
<button @click="change">按钮</button>
</div>
</template>
<script setup lang="ts" >
import { reactive, toRef } from 'vue'
const obj = {
foo: 1,
bar: 1,
}
const state = toRef(obj, 'bar')
// bar 转化为响应式对象
const change = () => {
state.value++
console.log(obj, state)
}
</script>
如果原始对象是响应式的,是会更新视图并且改变数据的。即将obj 设定为reactive对象
toRefs
可以帮我们批量创建ref对象,主要是方便我们解构使用(结构后的数据变化,会直接影响原始数据)
<template>
<div>
<div>foo: {{obj.foo}}</div>
<div>bar: {{obj.bar}}</div>
<div>foo: {{foo}}</div>
<div>bar: {{bar}}</div>
<button @click="change">按钮</button>
</div>
</template>
<script setup lang="ts" >
import { reactive, toRefs } from 'vue'
const obj = reactive({
foo: 1,
bar: 1,
})
let { foo, bar } = toRefs(obj)
// bar 转化为响应式对象
const change = () => {
foo.value++
bar.value++
console.log(foo, bar)
console.log(obj)
}
</script>
toRaw
将响应式对象转化为普通对象
<template>
<div>
<div>foo: {{obj.foo}}</div>
<div>bar: {{obj.bar}}</div>
<button @click="change">按钮</button>
</div>
</template>
<script setup lang="ts" >
import { reactive, toRaw } from 'vue'
const obj = reactive({
foo: 1,
bar: 1,
})
let state = toRaw(obj)
// bar 转化为响应式对象
const change = () => {
console.log(obj, state)
}
</script>
源码解析 toRef
1. 如果是ref对象,直接返回,否则调用 ObjcetRefImpl 创建一个类 ref 对象
2.类 ref 对象只是做了值 的改变,并未处理搜集依赖和触发依赖的过程,所以普通对象无法更新视图
toRefs 源码解析
其实就是把reactive 对象的每一个属性都变成了 ref 对象循环,调用了 toRef
toRaw 源码解析
通过 reactiveFlags 枚举值,去除proxy对象的原始值