ref.ts 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import { track, trigger } from './effect'
  2. import { OperationTypes } from './operations'
  3. import { isObject } from '@vue/shared'
  4. import { reactive } from './reactive'
  5. export const refSymbol = Symbol(__DEV__ ? 'refSymbol' : undefined)
  6. export interface Ref<T> {
  7. [refSymbol]: true
  8. value: UnwrapNestedRefs<T>
  9. }
  10. export type UnwrapNestedRefs<T> = T extends Ref<any> ? T : UnwrapRef<T>
  11. const convert = (val: any): any => (isObject(val) ? reactive(val) : val)
  12. export function ref<T>(raw: T): Ref<T> {
  13. raw = convert(raw)
  14. const v = {
  15. [refSymbol]: true,
  16. get value() {
  17. track(v, OperationTypes.GET, '')
  18. return raw
  19. },
  20. set value(newVal) {
  21. raw = convert(newVal)
  22. trigger(v, OperationTypes.SET, '')
  23. }
  24. }
  25. return v as Ref<T>
  26. }
  27. export function isRef(v: any): v is Ref<any> {
  28. return v ? v[refSymbol] === true : false
  29. }
  30. export function toRefs<T extends object>(
  31. object: T
  32. ): { [K in keyof T]: Ref<T[K]> } {
  33. const ret: any = {}
  34. for (const key in object) {
  35. ret[key] = toProxyRef(object, key)
  36. }
  37. return ret
  38. }
  39. function toProxyRef<T extends object, K extends keyof T>(
  40. object: T,
  41. key: K
  42. ): Ref<T[K]> {
  43. const v = {
  44. [refSymbol]: true,
  45. get value() {
  46. return object[key]
  47. },
  48. set value(newVal) {
  49. object[key] = newVal
  50. }
  51. }
  52. return v as Ref<T[K]>
  53. }
  54. type BailTypes =
  55. | Function
  56. | Map<any, any>
  57. | Set<any>
  58. | WeakMap<any, any>
  59. | WeakSet<any>
  60. // Recursively unwraps nested value bindings.
  61. export type UnwrapRef<T> = {
  62. ref: T extends Ref<infer V> ? UnwrapRef<V> : T
  63. array: T extends Array<infer V> ? Array<UnwrapRef<V>> : T
  64. object: { [K in keyof T]: UnwrapRef<T[K]> }
  65. stop: T
  66. }[T extends Ref<any>
  67. ? 'ref'
  68. : T extends Array<any>
  69. ? 'array'
  70. : T extends BailTypes
  71. ? 'stop' // bail out on types that shouldn't be unwrapped
  72. : T extends object ? 'object' : 'stop']