07-to系列全家桶
大约 2 分钟
toRef
应用场景 比如你请求拿到一个对象,但是只用其中某个属性,并且是响应式 把属性解构出来
toref
只能修改响应式对象的值 非常响应式视图毫无变化
<template>
<div>
<button @click="change">按钮</button>
{{state}}
</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>
如果原始对象是响应式的是会更新视图并且改变数据的 原因:toRef 源码解析
toRefs
可以帮我们批量创建 ref 对象主要是方便我们解构使用
import { reactive, toRefs } from 'vue'
const obj = reactive({
foo: 1,
bar: 1
})
let { foo, bar } = toRefs(obj)
foo.value++
console.log(foo, bar);
toRaw
将响应式对象转化为普通对象
当你使用响应式获取到了 input 的值,并用来 get,post 时就要原生对象
import { reactive, toRaw } from 'vue'
const obj = reactive({
foo: 1,
bar: 1
})
const state = toRaw(obj)
// 响应式对象转化为普通对象
const change = () => {
console.log(obj, state);
}
toRef 源码解析
如果是 ref 对象直接返回 否则 调用 ObjectRefImpl
创建一个类 ref 对象
没有做收集依赖和触发更新
export function toRef<T extends object, K extends keyof T>(
object: T,
key: K,
defaultValue?: T[K]
): ToRef<T[K]> {
const val = object[key]
return isRef(val)
? val
: (new ObjectRefImpl(object, key, defaultValue) as any)
}
类 ref 对象只是做了值的改变 并未处理 收集依赖 和 触发依赖的过程 所以 普通对象无法更新视图
ref 响应式对象 更新视图是因为调用了 reactive
^ref
class ObjectRefImpl<T extends object, K extends keyof T> {
public readonly __v_isRef = true
constructor(
private readonly _object: T,
private readonly _key: K,
private readonly _defaultValue?: T[K]
) {}
get value() {
const val = this._object[this._key]
return val === undefined ? (this._defaultValue as T[K]) : val
}
set value(newVal) {
this._object[this._key] = newVal
}
}
toRefs 源码解析
其实就是把 reactive 对象的每一个属性都变成了 ref 对象循环 调用了 toRef
export type ToRefs<T = any> = {
[K in keyof T]: ToRef<T[K]>
}
export function toRefs<T extends object>(object: T): ToRefs<T> {
if (__DEV__ && !isProxy(object)) {
console.warn(`toRefs() expects a reactive object but received a plain one.`)
}
const ret: any = isArray(object) ? new Array(object.length) : {}
for (const key in object) {
ret[key] = toRef(object, key)
}
return ret
}
toRaw 源码解析
通过 ReactiveFlags 枚举值 取出 proxy 对象的 原始对象
一句话就是,取出obj
中 obj['__v_raw']
的值
export const enum ReactiveFlags {
SKIP = '__v_skip',
IS_REACTIVE = '__v_isReactive',
IS_READONLY = '__v_isReadonly',
IS_SHALLOW = '__v_isShallow',
RAW = '__v_raw'
}
export function toRaw<T>(observed: T): T {
const raw = observed && (observed as Target)[ReactiveFlags.RAW]
return raw ? toRaw(raw) : observed
}