diff --git a/packages/vant-use/src/useRelation/index.ts b/packages/vant-use/src/useRelation/index.ts index 6ca02f4da..c56a40646 100644 --- a/packages/vant-use/src/useRelation/index.ts +++ b/packages/vant-use/src/useRelation/index.ts @@ -1,129 +1,2 @@ -import { - VNode, - inject, - isVNode, - provide, - computed, - reactive, - onUnmounted, - getCurrentInstance, - VNodeNormalizedChildren, - ComponentPublicInstance as PublicInstance, - ComponentInternalInstance as InternalInstance, -} from 'vue'; - -export function flattenVNodes(children: VNodeNormalizedChildren) { - const result: VNode[] = []; - - const traverse = (children: VNodeNormalizedChildren) => { - if (Array.isArray(children)) { - children.forEach((child) => { - if (isVNode(child)) { - result.push(child); - - if (child.component?.subTree) { - traverse(child.component.subTree.children); - } - - if (child.children) { - traverse(child.children); - } - } - }); - } - }; - - traverse(children); - - return result; -} - -// sort children instances by vnodes order -export function sortChildren( - parent: InternalInstance, - publicChildren: PublicInstance[], - internalChildren: InternalInstance[] -) { - const vnodes = flattenVNodes(parent.subTree.children); - - internalChildren.sort( - (a, b) => vnodes.indexOf(a.vnode) - vnodes.indexOf(b.vnode) - ); - - const orderedPublicChildren = internalChildren.map((item) => item.proxy!); - - publicChildren.sort((a, b) => { - const indexA = orderedPublicChildren.indexOf(a); - const indexB = orderedPublicChildren.indexOf(b); - return indexA - indexB; - }); -} - -export function useChildren(key: string | symbol) { - const publicChildren: PublicInstance[] = reactive([]); - const internalChildren: InternalInstance[] = reactive([]); - const parent = getCurrentInstance()!; - - const linkChildren = (value: any) => { - const link = (child: InternalInstance) => { - if (child.proxy) { - internalChildren.push(child); - publicChildren.push(child.proxy); - sortChildren(parent, publicChildren, internalChildren); - } - }; - - const unlink = (child: InternalInstance) => { - const index = internalChildren.indexOf(child); - publicChildren.splice(index, 1); - internalChildren.splice(index, 1); - }; - - provide(key, { - link, - unlink, - children: publicChildren, - internalChildren, - ...value, - }); - }; - - return { - children: publicChildren, - linkChildren, - }; -} - -type ParentProvide = T & { - link(child: InternalInstance): void; - unlink(child: InternalInstance): void; - children: PublicInstance[]; - internalChildren: InternalInstance[]; -}; - -export function useParent(key: string | symbol) { - const parent = inject | null>(key, null); - - if (parent) { - const instance = getCurrentInstance(); - - if (instance) { - const { link, unlink, internalChildren, ...rest } = parent; - - link(instance); - - onUnmounted(() => { - unlink(instance); - }); - - const index = computed(() => internalChildren.indexOf(instance)); - - return { - parent: rest, - index, - }; - } - } - - return {}; -} +export * from './useParent'; +export * from './useChildren'; diff --git a/packages/vant-use/src/useRelation/useChildren.ts b/packages/vant-use/src/useRelation/useChildren.ts new file mode 100644 index 000000000..53de68d75 --- /dev/null +++ b/packages/vant-use/src/useRelation/useChildren.ts @@ -0,0 +1,92 @@ +import { + VNode, + isVNode, + provide, + reactive, + getCurrentInstance, + VNodeNormalizedChildren, + ComponentPublicInstance, + ComponentInternalInstance, +} from 'vue'; + +export function flattenVNodes(children: VNodeNormalizedChildren) { + const result: VNode[] = []; + + const traverse = (children: VNodeNormalizedChildren) => { + if (Array.isArray(children)) { + children.forEach((child) => { + if (isVNode(child)) { + result.push(child); + + if (child.component?.subTree) { + traverse(child.component.subTree.children); + } + + if (child.children) { + traverse(child.children); + } + } + }); + } + }; + + traverse(children); + + return result; +} + +// sort children instances by vnodes order +export function sortChildren( + parent: ComponentInternalInstance, + publicChildren: ComponentPublicInstance[], + internalChildren: ComponentInternalInstance[] +) { + const vnodes = flattenVNodes(parent.subTree.children); + + internalChildren.sort( + (a, b) => vnodes.indexOf(a.vnode) - vnodes.indexOf(b.vnode) + ); + + const orderedPublicChildren = internalChildren.map((item) => item.proxy!); + + publicChildren.sort((a, b) => { + const indexA = orderedPublicChildren.indexOf(a); + const indexB = orderedPublicChildren.indexOf(b); + return indexA - indexB; + }); +} + +export function useChildren(key: string | symbol) { + const publicChildren: ComponentPublicInstance[] = reactive([]); + const internalChildren: ComponentInternalInstance[] = reactive([]); + const parent = getCurrentInstance()!; + + const linkChildren = (value: any) => { + const link = (child: ComponentInternalInstance) => { + if (child.proxy) { + internalChildren.push(child); + publicChildren.push(child.proxy); + sortChildren(parent, publicChildren, internalChildren); + } + }; + + const unlink = (child: ComponentInternalInstance) => { + const index = internalChildren.indexOf(child); + publicChildren.splice(index, 1); + internalChildren.splice(index, 1); + }; + + provide(key, { + link, + unlink, + children: publicChildren, + internalChildren, + ...value, + }); + }; + + return { + children: publicChildren, + linkChildren, + }; +} diff --git a/packages/vant-use/src/useRelation/useParent.ts b/packages/vant-use/src/useRelation/useParent.ts new file mode 100644 index 000000000..af669b378 --- /dev/null +++ b/packages/vant-use/src/useRelation/useParent.ts @@ -0,0 +1,42 @@ +import { + inject, + computed, + onUnmounted, + getCurrentInstance, + ComponentPublicInstance, + ComponentInternalInstance, +} from 'vue'; + +type ParentProvide = T & { + link(child: ComponentInternalInstance): void; + unlink(child: ComponentInternalInstance): void; + children: ComponentPublicInstance[]; + internalChildren: ComponentInternalInstance[]; +}; + +export function useParent(key: string | symbol) { + const parent = inject | null>(key, null); + + if (parent) { + const instance = getCurrentInstance(); + + if (instance) { + const { link, unlink, internalChildren, ...rest } = parent; + + link(instance); + + onUnmounted(() => { + unlink(instance); + }); + + const index = computed(() => internalChildren.indexOf(instance)); + + return { + parent: rest, + index, + }; + } + } + + return {}; +}