vue3-yuanma/packages/reactivity/src/ref.ts

83 lines
1.8 KiB
TypeScript
Raw Normal View History

2019-08-16 21:42:46 +08:00
import { track, trigger } from './effect'
import { OperationTypes } from './operations'
import { isObject } from '@vue/shared'
import { reactive } from './reactive'
export const refSymbol = Symbol(__DEV__ ? 'refSymbol' : undefined)
2019-10-10 02:01:53 +08:00
export interface Ref<T = any> {
[refSymbol]: true
2019-08-16 22:52:45 +08:00
value: UnwrapNestedRefs<T>
2019-08-16 21:42:46 +08:00
}
2019-10-10 02:01:53 +08:00
export type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRef<T>
2019-08-16 22:52:45 +08:00
2019-08-16 21:42:46 +08:00
const convert = (val: any): any => (isObject(val) ? reactive(val) : val)
export function ref<T>(raw: T): Ref<T> {
raw = convert(raw)
const v = {
[refSymbol]: true,
2019-08-16 21:42:46 +08:00
get value() {
track(v, OperationTypes.GET, '')
return raw
},
set value(newVal) {
raw = convert(newVal)
trigger(v, OperationTypes.SET, '')
}
}
2019-08-20 21:38:00 +08:00
return v as Ref<T>
2019-08-16 21:42:46 +08:00
}
2019-10-10 02:01:53 +08:00
export function isRef(v: any): v is Ref {
return v ? v[refSymbol] === true : false
2019-08-20 21:38:00 +08:00
}
export function toRefs<T extends object>(
object: T
): { [K in keyof T]: Ref<T[K]> } {
const ret: any = {}
for (const key in object) {
ret[key] = toProxyRef(object, key)
}
return ret
}
function toProxyRef<T extends object, K extends keyof T>(
object: T,
key: K
): Ref<T[K]> {
const v = {
[refSymbol]: true,
2019-08-20 21:38:00 +08:00
get value() {
return object[key]
},
set value(newVal) {
object[key] = newVal
}
}
return v as Ref<T[K]>
2019-08-16 21:42:46 +08:00
}
type BailTypes =
| Function
| Map<any, any>
| Set<any>
| WeakMap<any, any>
| WeakSet<any>
// Recursively unwraps nested value bindings.
export type UnwrapRef<T> = {
ref: T extends Ref<infer V> ? UnwrapRef<V> : T
array: T extends Array<infer V> ? Array<UnwrapRef<V>> : T
object: { [K in keyof T]: UnwrapRef<T[K]> }
stop: T
2019-10-10 02:01:53 +08:00
}[T extends Ref
? 'ref'
: T extends Array<any>
? 'array'
2019-08-16 21:42:46 +08:00
: T extends BailTypes
? 'stop' // bail out on types that shouldn't be unwrapped
: T extends object ? 'object' : 'stop']