美文网首页
hookPrivider inject

hookPrivider inject

作者: yuanlu954 | 来源:发表于2021-02-05 18:24 被阅读0次

    useChildren

    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,
      };
    }
    
    

    useParent

    import {
      inject,
      computed,
      onUnmounted,
      getCurrentInstance,
      ComponentPublicInstance,
      ComponentInternalInstance,
    } from 'vue';
    
    type ParentProvide<T> = T & {
      link(child: ComponentInternalInstance): void;
      unlink(child: ComponentInternalInstance): void;
      children: ComponentPublicInstance[];
      internalChildren: ComponentInternalInstance[];
    };
    
    export function useParent<T>(key: string | symbol) {
      const parent = inject<ParentProvide<T> | 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 {};
    }
    
    

    相关文章

      网友评论

          本文标题:hookPrivider inject

          本文链接:https://www.haomeiwen.com/subject/slsgtltx.html