diff --git a/packages/runtime-core/src/compat/children.ts b/packages/runtime-core/src/compat/children.ts new file mode 100644 index 000000000..c444d2eed --- /dev/null +++ b/packages/runtime-core/src/compat/children.ts @@ -0,0 +1,28 @@ +import { ShapeFlags } from '@vue/shared/src' +import { ComponentInternalInstance } from '../component' +import { ComponentPublicInstance } from '../componentPublicInstance' +import { VNode } from '../vnode' +import { DeprecationTypes, warnDeprecation } from './deprecations' + +export function getInstanceChildren( + instance: ComponentInternalInstance +): ComponentPublicInstance[] { + __DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_CHILDREN) + const root = instance.subTree + const children: ComponentPublicInstance[] = [] + if (root) { + walk(root, children) + } + return children +} + +function walk(vnode: VNode, children: ComponentPublicInstance[]) { + if (vnode.component) { + children.push(vnode.component.proxy!) + } else if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) { + const vnodes = vnode.children as VNode[] + for (let i = 0; i < vnodes.length; i++) { + walk(vnodes[i], children) + } + } +} diff --git a/packages/runtime-core/src/compat/deprecations.ts b/packages/runtime-core/src/compat/deprecations.ts index f71d77ff0..a371649c1 100644 --- a/packages/runtime-core/src/compat/deprecations.ts +++ b/packages/runtime-core/src/compat/deprecations.ts @@ -20,6 +20,7 @@ export const enum DeprecationTypes { INSTANCE_DESTROY, INSTANCE_EVENT_EMITTER, INSTANCE_EVENT_HOOKS, + INSTANCE_CHILDREN, OPTIONS_DATA_FN, OPTIONS_DATA_MERGE, @@ -148,6 +149,13 @@ const deprecations: Record = { link: `https://v3.vuejs.org/api/composition-api.html#lifecycle-hooks` }, + [DeprecationTypes.INSTANCE_CHILDREN]: { + message: + `vm.$children has been removed. Consider refactoring your logic ` + + `to avoid relying on direct access to child components.`, + link: `https://v3.vuejs.org/guide/migration/children.html` + }, + [DeprecationTypes.OPTIONS_DATA_FN]: { message: `The "data" option can no longer be a plain object. ` + diff --git a/packages/runtime-core/src/compat/instance.ts b/packages/runtime-core/src/compat/instance.ts index a7158addb..557706f26 100644 --- a/packages/runtime-core/src/compat/instance.ts +++ b/packages/runtime-core/src/compat/instance.ts @@ -1,5 +1,6 @@ import { extend, NOOP } from '@vue/shared' import { PublicPropertiesMap } from '../componentPublicInstance' +import { getInstanceChildren } from './children' import { DeprecationTypes, warnDeprecation } from './deprecations' import { off, on, once } from './eventEmitter' @@ -33,6 +34,7 @@ export function installCompatInstanceProperties(map: PublicPropertiesMap) { }, $on: i => on.bind(null, i), $once: i => once.bind(null, i), - $off: i => off.bind(null, i) + $off: i => off.bind(null, i), + $children: getInstanceChildren } as PublicPropertiesMap) }