ref.ts 1.9 KB

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