instance.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import {
  2. NOOP,
  3. extend,
  4. looseEqual,
  5. looseIndexOf,
  6. looseToNumber,
  7. toDisplayString,
  8. } from '@vue/shared'
  9. import type {
  10. ComponentPublicInstance,
  11. PublicPropertiesMap,
  12. } from '../componentPublicInstance'
  13. import { getCompatChildren } from './instanceChildren'
  14. import {
  15. DeprecationTypes,
  16. assertCompatEnabled,
  17. isCompatEnabled,
  18. warnDeprecation,
  19. } from './compatConfig'
  20. import { off, on, once } from './instanceEventEmitter'
  21. import { getCompatListeners } from './instanceListeners'
  22. import { shallowReadonly } from '@vue/reactivity'
  23. import { legacySlotProxyHandlers } from './componentFunctional'
  24. import { compatH } from './renderFn'
  25. import { createCommentVNode, createTextVNode } from '../vnode'
  26. import { renderList } from '../helpers/renderList'
  27. import {
  28. legacyBindDynamicKeys,
  29. legacyBindObjectListeners,
  30. legacyBindObjectProps,
  31. legacyCheckKeyCodes,
  32. legacyMarkOnce,
  33. legacyPrependModifier,
  34. legacyRenderSlot,
  35. legacyRenderStatic,
  36. legacyresolveScopedSlots,
  37. } from './renderHelpers'
  38. import { resolveFilter } from '../helpers/resolveAssets'
  39. import type { Slots } from '../componentSlots'
  40. import { resolveMergedOptions } from '../componentOptions'
  41. export type LegacyPublicInstance = ComponentPublicInstance &
  42. LegacyPublicProperties
  43. export interface LegacyPublicProperties {
  44. $set<T extends Record<keyof any, any>, K extends keyof T>(
  45. target: T,
  46. key: K,
  47. value: T[K],
  48. ): void
  49. $delete<T extends Record<keyof any, any>, K extends keyof T>(
  50. target: T,
  51. key: K,
  52. ): void
  53. $mount(el?: string | Element): this
  54. $destroy(): void
  55. $scopedSlots: Slots
  56. $on(event: string | string[], fn: Function): this
  57. $once(event: string, fn: Function): this
  58. $off(event?: string | string[], fn?: Function): this
  59. $children: LegacyPublicProperties[]
  60. $listeners: Record<string, Function | Function[]>
  61. }
  62. export function installCompatInstanceProperties(
  63. map: PublicPropertiesMap,
  64. ): void {
  65. const set = (target: any, key: any, val: any) => {
  66. target[key] = val
  67. return target[key]
  68. }
  69. const del = (target: any, key: any) => {
  70. delete target[key]
  71. }
  72. extend(map, {
  73. $set: i => {
  74. assertCompatEnabled(DeprecationTypes.INSTANCE_SET, i)
  75. return set
  76. },
  77. $delete: i => {
  78. assertCompatEnabled(DeprecationTypes.INSTANCE_DELETE, i)
  79. return del
  80. },
  81. $mount: i => {
  82. assertCompatEnabled(
  83. DeprecationTypes.GLOBAL_MOUNT,
  84. null /* this warning is global */,
  85. )
  86. // root mount override from ./global.ts in installCompatMount
  87. return i.ctx._compat_mount || NOOP
  88. },
  89. $destroy: i => {
  90. assertCompatEnabled(DeprecationTypes.INSTANCE_DESTROY, i)
  91. // root destroy override from ./global.ts in installCompatMount
  92. return i.ctx._compat_destroy || NOOP
  93. },
  94. // overrides existing accessor
  95. $slots: i => {
  96. if (
  97. isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, i) &&
  98. i.render &&
  99. i.render._compatWrapped
  100. ) {
  101. return new Proxy(i.slots, legacySlotProxyHandlers)
  102. }
  103. return __DEV__ ? shallowReadonly(i.slots) : i.slots
  104. },
  105. $scopedSlots: i => {
  106. assertCompatEnabled(DeprecationTypes.INSTANCE_SCOPED_SLOTS, i)
  107. return __DEV__ ? shallowReadonly(i.slots) : i.slots
  108. },
  109. $on: i => on.bind(null, i),
  110. $once: i => once.bind(null, i),
  111. $off: i => off.bind(null, i),
  112. $children: getCompatChildren,
  113. $listeners: getCompatListeners,
  114. // inject additional properties into $options for compat
  115. // e.g. vuex needs this.$options.parent
  116. $options: i => {
  117. if (!isCompatEnabled(DeprecationTypes.PRIVATE_APIS, i)) {
  118. return resolveMergedOptions(i)
  119. }
  120. if (i.resolvedOptions) {
  121. return i.resolvedOptions
  122. }
  123. const res = (i.resolvedOptions = extend({}, resolveMergedOptions(i)))
  124. Object.defineProperties(res, {
  125. parent: {
  126. get() {
  127. warnDeprecation(DeprecationTypes.PRIVATE_APIS, i, '$options.parent')
  128. return i.proxy!.$parent
  129. },
  130. },
  131. propsData: {
  132. get() {
  133. warnDeprecation(
  134. DeprecationTypes.PRIVATE_APIS,
  135. i,
  136. '$options.propsData',
  137. )
  138. return i.vnode.props
  139. },
  140. },
  141. })
  142. return res
  143. },
  144. } as PublicPropertiesMap)
  145. const privateAPIs = {
  146. // needed by many libs / render fns
  147. $vnode: i => i.vnode,
  148. // some private properties that are likely accessed...
  149. _self: i => i.proxy,
  150. _uid: i => i.uid,
  151. _data: i => i.data,
  152. _isMounted: i => i.isMounted,
  153. _isDestroyed: i => i.isUnmounted,
  154. // v2 render helpers
  155. $createElement: () => compatH,
  156. _c: () => compatH,
  157. _o: () => legacyMarkOnce,
  158. _n: () => looseToNumber,
  159. _s: () => toDisplayString,
  160. _l: () => renderList,
  161. _t: i => legacyRenderSlot.bind(null, i),
  162. _q: () => looseEqual,
  163. _i: () => looseIndexOf,
  164. _m: i => legacyRenderStatic.bind(null, i),
  165. _f: () => resolveFilter,
  166. _k: i => legacyCheckKeyCodes.bind(null, i),
  167. _b: () => legacyBindObjectProps,
  168. _v: () => createTextVNode,
  169. _e: () => createCommentVNode,
  170. _u: () => legacyresolveScopedSlots,
  171. _g: () => legacyBindObjectListeners,
  172. _d: () => legacyBindDynamicKeys,
  173. _p: () => legacyPrependModifier,
  174. } as PublicPropertiesMap
  175. for (const key in privateAPIs) {
  176. map[key] = i => {
  177. if (isCompatEnabled(DeprecationTypes.PRIVATE_APIS, i)) {
  178. return privateAPIs[key](i)
  179. }
  180. }
  181. }
  182. }