instance.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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(map: PublicPropertiesMap) {
  63. const set = (target: any, key: any, val: any) => {
  64. target[key] = val
  65. return target[key]
  66. }
  67. const del = (target: any, key: any) => {
  68. delete target[key]
  69. }
  70. extend(map, {
  71. $set: i => {
  72. assertCompatEnabled(DeprecationTypes.INSTANCE_SET, i)
  73. return set
  74. },
  75. $delete: i => {
  76. assertCompatEnabled(DeprecationTypes.INSTANCE_DELETE, i)
  77. return del
  78. },
  79. $mount: i => {
  80. assertCompatEnabled(
  81. DeprecationTypes.GLOBAL_MOUNT,
  82. null /* this warning is global */,
  83. )
  84. // root mount override from ./global.ts in installCompatMount
  85. return i.ctx._compat_mount || NOOP
  86. },
  87. $destroy: i => {
  88. assertCompatEnabled(DeprecationTypes.INSTANCE_DESTROY, i)
  89. // root destroy override from ./global.ts in installCompatMount
  90. return i.ctx._compat_destroy || NOOP
  91. },
  92. // overrides existing accessor
  93. $slots: i => {
  94. if (
  95. isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, i) &&
  96. i.render &&
  97. i.render._compatWrapped
  98. ) {
  99. return new Proxy(i.slots, legacySlotProxyHandlers)
  100. }
  101. return __DEV__ ? shallowReadonly(i.slots) : i.slots
  102. },
  103. $scopedSlots: i => {
  104. assertCompatEnabled(DeprecationTypes.INSTANCE_SCOPED_SLOTS, i)
  105. return __DEV__ ? shallowReadonly(i.slots) : i.slots
  106. },
  107. $on: i => on.bind(null, i),
  108. $once: i => once.bind(null, i),
  109. $off: i => off.bind(null, i),
  110. $children: getCompatChildren,
  111. $listeners: getCompatListeners,
  112. // inject additional properties into $options for compat
  113. // e.g. vuex needs this.$options.parent
  114. $options: i => {
  115. if (!isCompatEnabled(DeprecationTypes.PRIVATE_APIS, i)) {
  116. return resolveMergedOptions(i)
  117. }
  118. if (i.resolvedOptions) {
  119. return i.resolvedOptions
  120. }
  121. const res = (i.resolvedOptions = extend({}, resolveMergedOptions(i)))
  122. Object.defineProperties(res, {
  123. parent: {
  124. get() {
  125. warnDeprecation(DeprecationTypes.PRIVATE_APIS, i, '$options.parent')
  126. return i.proxy!.$parent
  127. },
  128. },
  129. propsData: {
  130. get() {
  131. warnDeprecation(
  132. DeprecationTypes.PRIVATE_APIS,
  133. i,
  134. '$options.propsData',
  135. )
  136. return i.vnode.props
  137. },
  138. },
  139. })
  140. return res
  141. },
  142. } as PublicPropertiesMap)
  143. const privateAPIs = {
  144. // needed by many libs / render fns
  145. $vnode: i => i.vnode,
  146. // some private properties that are likely accessed...
  147. _self: i => i.proxy,
  148. _uid: i => i.uid,
  149. _data: i => i.data,
  150. _isMounted: i => i.isMounted,
  151. _isDestroyed: i => i.isUnmounted,
  152. // v2 render helpers
  153. $createElement: () => compatH,
  154. _c: () => compatH,
  155. _o: () => legacyMarkOnce,
  156. _n: () => looseToNumber,
  157. _s: () => toDisplayString,
  158. _l: () => renderList,
  159. _t: i => legacyRenderSlot.bind(null, i),
  160. _q: () => looseEqual,
  161. _i: () => looseIndexOf,
  162. _m: i => legacyRenderStatic.bind(null, i),
  163. _f: () => resolveFilter,
  164. _k: i => legacyCheckKeyCodes.bind(null, i),
  165. _b: () => legacyBindObjectProps,
  166. _v: () => createTextVNode,
  167. _e: () => createCommentVNode,
  168. _u: () => legacyresolveScopedSlots,
  169. _g: () => legacyBindObjectListeners,
  170. _d: () => legacyBindDynamicKeys,
  171. _p: () => legacyPrependModifier,
  172. } as PublicPropertiesMap
  173. for (const key in privateAPIs) {
  174. map[key] = i => {
  175. if (isCompatEnabled(DeprecationTypes.PRIVATE_APIS, i)) {
  176. return privateAPIs[key](i)
  177. }
  178. }
  179. }
  180. }