From dd124e994b69fb881280b25bdfed133663a98c57 Mon Sep 17 00:00:00 2001 From: LaamGinghong <351390560@qq.com> Date: Thu, 31 Dec 2020 18:36:33 +0800 Subject: [PATCH] fix(comp: divider): dynamic slot fix #76 --- packages/cdk/utils/__tests__/vNode.spec.ts | 55 +++++++++++++++++++ packages/cdk/utils/index.ts | 1 + packages/cdk/utils/vNode.ts | 41 ++++++++++++++ packages/components/divider/demo/with-text.md | 0 packages/components/divider/src/Divider.vue | 30 ++++++---- 5 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 packages/cdk/utils/__tests__/vNode.spec.ts create mode 100644 packages/cdk/utils/vNode.ts mode change 100755 => 100644 packages/components/divider/demo/with-text.md diff --git a/packages/cdk/utils/__tests__/vNode.spec.ts b/packages/cdk/utils/__tests__/vNode.spec.ts new file mode 100644 index 000000000..a666b80f3 --- /dev/null +++ b/packages/cdk/utils/__tests__/vNode.spec.ts @@ -0,0 +1,55 @@ +import type { VNode, VNodeChild } from 'vue' + +import { Comment, Fragment, Text } from 'vue' + +import { getFirstValidNode, isValidElementNode } from '../vNode' + +const TEMPLATE = 'template' + +type FakeVNode = Partial> & { children?: FakeVNode[] } + +const vNode: FakeVNode = { + type: Comment, +} + +vNode.children = [vNode] + +describe('vNode.ts', () => { + test('getFirstValidNode work', async () => { + const undefinedValue = undefined + expect(getFirstValidNode(undefinedValue)).toBeUndefined() + + const arrayValue: FakeVNode[] = [vNode] + expect(getFirstValidNode(arrayValue as VNodeChild)).toBeUndefined() + expect(getFirstValidNode(vNode as VNodeChild)).toBeUndefined() + + vNode.type = Fragment + expect(getFirstValidNode(arrayValue as VNodeChild, 0)).toBeUndefined() + expect(getFirstValidNode(vNode as VNodeChild, 0)).toBeUndefined() + expect(getFirstValidNode(arrayValue as VNodeChild, 1)).toBeUndefined() + expect(getFirstValidNode(vNode as VNodeChild, 1)).toBeUndefined() + + vNode.type = TEMPLATE + expect(getFirstValidNode(arrayValue as VNodeChild, 0)).toBeUndefined() + expect(getFirstValidNode(vNode as VNodeChild, 0)).toBeUndefined() + expect(getFirstValidNode(arrayValue as VNodeChild, 1)).toBeUndefined() + expect(getFirstValidNode(vNode as VNodeChild, 1)).toBeUndefined() + + vNode.type = Text + expect(getFirstValidNode(arrayValue as VNodeChild, 0)).toEqual(vNode) + expect(getFirstValidNode(vNode as VNodeChild, 0)).toEqual(vNode) + expect(getFirstValidNode(arrayValue as VNodeChild, 1)).toEqual(vNode) + expect(getFirstValidNode(vNode as VNodeChild, 1)).toEqual(vNode) + }) + + test('isValidElementNode work', async () => { + vNode.type = Comment + expect(isValidElementNode(vNode as VNodeChild)).toBeFalsy() + + vNode.type = Fragment + expect(isValidElementNode(vNode as VNodeChild)).toBeFalsy() + + vNode.type = Text + expect(isValidElementNode(vNode as VNodeChild)).toBeTruthy() + }) +}) diff --git a/packages/cdk/utils/index.ts b/packages/cdk/utils/index.ts index 0b7dea23c..c54a87d9e 100644 --- a/packages/cdk/utils/index.ts +++ b/packages/cdk/utils/index.ts @@ -1,3 +1,4 @@ export * from './convert' export * from './propTypes' export * from './typeof' +export * from './vNode' diff --git a/packages/cdk/utils/vNode.ts b/packages/cdk/utils/vNode.ts new file mode 100644 index 000000000..39bd2183e --- /dev/null +++ b/packages/cdk/utils/vNode.ts @@ -0,0 +1,41 @@ +import type { VNode, VNodeChild } from 'vue' + +import { Comment, Fragment } from 'vue' + +import { isUndefined } from './typeof' + +const TEMPLATE = 'template' + +export const isFragment = (node: VNodeChild) => (node as VNode).type === Fragment +export const isComment = (node: VNodeChild) => (node as VNode).type === Comment +export const isTemplate = (node: VNodeChild) => (node as VNode).type === TEMPLATE + +function getChildren(node: VNode, depth: number): undefined | VNode { + if (isComment(node)) return + if (isFragment(node) || isTemplate(node)) { + return depth > 0 ? getFirstValidNode(node.children as VNodeChild, depth - 1) : undefined + } + return node +} + +/** + * get first valid child node (not fragment not comment) + * @param nodes {VNode} node to be searched + * @param maxDepth {number} depth to be searched, default is 3 + */ +export function getFirstValidNode(nodes?: VNodeChild, maxDepth = 3): ReturnType { + if (isUndefined(nodes)) return + if (Array.isArray(nodes)) { + return getChildren(nodes[0] as VNode, maxDepth) + } + return getChildren(nodes as VNode, maxDepth) +} + +/** + * determine whether an element is valid (not fragment not comment) + * @param node {VNode} node to be determined + * @returns {boolean} + */ +export function isValidElementNode(node: VNodeChild): boolean { + return !(isFragment(node) || isComment(node)) +} diff --git a/packages/components/divider/demo/with-text.md b/packages/components/divider/demo/with-text.md old mode 100755 new mode 100644 diff --git a/packages/components/divider/src/Divider.vue b/packages/components/divider/src/Divider.vue index 20a3e5b2f..2909288f1 100644 --- a/packages/components/divider/src/Divider.vue +++ b/packages/components/divider/src/Divider.vue @@ -6,13 +6,15 @@