<template> <div> <span>{{inner.content.text}}</span> <span>{{count}}</span> </div> </template> <script setup> const inner = ref({ content: { text: "内部内容" } }); // 你可以通过 ref 定义复杂数据类型 // or const count = ref(20); // 定义普通数据类型 </script>reactive 基本使用
<template> <div> <div>{{wapper.subText}}</div> <div v-for="item in list" :key="item.id">{{item.content}}</div> </div> </template> <script setup> const wapper = reactive({ subText: inner }); const list = reactive([ { id: 1, content: "render" }, { id: 2, content: "render2" } ]); </script>当然你还可以配合 computed od watchEffec使用 这里我就不再过多介绍了。
// ref.ts 文件93 行 export function ref(value?: unknown) { return createRef(value, false) //1 : 提供 ref函数 , false 是否浅复制 } // ref.ts文件第 127行 // 调用 ref 返回一个 创建 的方法 createRef 传入 两个值 /** * @param rawValue ref函数传入的参数 * @param shallow 是否浅复制 */ function createRef(rawValue: unknown, shallow: boolean) { if (isRef(rawValue)) { // 是否是ref对象 如果是 则 直接返回 return rawValue } return new RefImpl(rawValue, shallow) // 否则 创建 ref 对象 传入 rawValue shallow } // ref.ts 文件第 134行 class RefImpl<T> { // 创建一个 ref的 实现类 private _value: T // 创建私有的 _value 变量 private _rawValue: T // 创建私有的 _rawValue 变量 public dep?: Dep = undefined // 是否 dep public readonly __v_isRef = true // 只读的 属性 是否是 ref constructor(value: T, public readonly __v_isShallow: boolean) { // 实例被 new时 执行 constructor 保存 传入的值 this._rawValue = __v_isShallow ? value : toRaw(value) // 是否浅复制 , 如果时 则直接返回 传入的值 否则进行 获取其原始对象 this._value = __v_isShallow ? value : toReactive(value) // 是否浅复制 是 返回原value 否则 转换成 reactive 对象 } get value() { // 获取值的时候 直接将 constructor 保存的值 返回 trackRefValue(this) // 跟踪 ref 的 value return this._value // 获取value 是 返回 _value 对象 } set value(newVal) {// 当 设置值的时候 往下看 // 是否浅复制 or 值身上是否有 __v_isShallow 标识 or 是否是只读的 标识__v_isReadonly const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal); // 如果满足 则 返回新设置的值 , 如果不是 则 取出 新值的原始对象 newVal = useDirectValue ? newVal : toRaw(newVal) // 如果 你一个 浅层对象(普通数据类型) 则 原值返回 否则 判断是否能从 代理对象中 取出源值 if (hasChanged(newVal, this._rawValue)) { // 判断对象是否发生 变化 变了向下走 this._rawValue = newVal // 将最新值 赋给 _rawValue this._value = useDirectValue ? newVal : toReactive(newVal) // 判断是否是基本数据类型 如果 是 则 将最新值返回 否则 继续转换 reactive triggerRefValue(this, newVal) // 触发 ref 的 value 值进行监听更新 } } } // 判断是否 是对象 如果是 则 reactive代理 否则 返回 当前的value export const toReactive = <T extends unknown>(value: T): T => isObject(value) ? reactive(value) : value
以上代码就是 ref 的核心实现 , 相信看来好像源码也没有那么难。
export function reactive(target: object) { // if trying to observe a readonly proxy, return the readonly version. if (isReadonly(target)) { // 如果是 只读的 不允许 写入 则返回只读对象 return target } return createReactiveObject( // 返回一个创建 reactive 的对象 target, // 传入 目标对象 false, // 是否是只读对象 mutableHandlers, //提供 get, set, deleteProperty, has, ownKeys 方法 mutableCollectionHandlers, // 太多了 自己看源码 reactiveMap // 提供一个 weakmap 集合 ) } function createReactiveObject( target: Target, isReadonly: boolean, baseHandlers: ProxyHandler<any> collectionHandlers: ProxyHandler<any>, proxyMap: WeakMap<Target, any> ) { if (!isObject(target)) { // 如果不是一个对象 则 返回当前 traget if (__DEV__) { console.warn(`value cannot be made reactive: ${String(target)}`) } return target } // target is already a Proxy, return it. // exception: calling readonly() on a reactive object if ( target[ReactiveFlags.RAW] && // 如果target 已经是一个 代理对象 则 返回当前对象 !(isReadonly && target[ReactiveFlags.IS_REACTIVE]) ) { return target } // target already has corresponding Proxy const existingProxy = proxyMap.get(target) // 如果对象已经有了代理对象 则直接取值 返回 if (existingProxy) { return existingProxy } // only specific value types can be observed. const targetType = getTargetType(target) // 观察指定类型 if (targetType === TargetType.INVALID) { return target } const proxy = new Proxy( // 将对象进行代理 target, targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers ) proxyMap.set(target, proxy) // 设置目标为代理对象 return proxy // 将对象返回出去 }1.3.5.总结一下 reactive做了什么?