toRef toRefs toRaw
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>
如果原始对象是响应式的是会更新视图并且改变数据的
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
将响应式对象转化为普通对象
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 对象只是做了值的改变 并未处理 收集依赖 和 触发依赖的过程 所以 普通对象无法更新视图
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 对象的 原始对象
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 }