From 1c4baae2d355394e551e1a805ec6fa740e035886 Mon Sep 17 00:00:00 2001 From: ikeq Date: Mon, 21 Feb 2022 22:03:25 +0800 Subject: [PATCH 1/5] fix(select): Improve options initial parsing logic --- src/popup/popup.tsx | 2 +- src/select/select.tsx | 64 +++++++++++--------- test/ssr/__snapshots__/ssr.test.js.snap | 77 +++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 29 deletions(-) diff --git a/src/popup/popup.tsx b/src/popup/popup.tsx index 0467f7406..1010a572b 100644 --- a/src/popup/popup.tsx +++ b/src/popup/popup.tsx @@ -336,7 +336,7 @@ export default Vue.extend({ } as VNodeDirective, ], on: { - mousedown: () => { + click: () => { this.contentClicked = true; }, ...(hasTrigger.hover && { diff --git a/src/select/select.tsx b/src/select/select.tsx index 9ee91fe4a..f6f357b28 100644 --- a/src/select/select.tsx +++ b/src/select/select.tsx @@ -685,37 +685,45 @@ export default mixins(getConfigReceiverMixins('select')).exte ); }, - }, + /** + * Parse options from slots before popup, execute only once + */ + initOptions() { + if (this.realOptions.length || this.isInited) return; - updated() { - if (this.realOptions.length || this.isInited) return; + const children = renderTNodeJSX(this, 'default'); + if (children) { + this.realOptions = parseOptions(children); + this.isInited = true; + } - // Parse options from slots before popup, execute only once - const children = renderTNodeJSX(this, 'default'); - if (children) { - this.realOptions = parseOptions(children); - this.isInited = true; - } + function parseOptions(vnodes: VNode[]): TdOptionProps[] { + if (!vnodes) return []; + return vnodes.reduce((options, vnode) => { + if (vnode.componentOptions?.tag === 't-option') { + const propsData = vnode.componentOptions.propsData as any; + return options.concat({ + label: propsData.label, + value: propsData.value, + disabled: propsData.disabled, + content: propsData.content, + default: propsData.default, + }); + } + if (vnode.componentOptions?.tag === 't-option-group') { + return options.concat(parseOptions(vnode.componentOptions.children)); + } + return options; + }, []); + } + }, + }, - function parseOptions(vnodes: VNode[]): TdOptionProps[] { - if (!vnodes) return []; - return vnodes.reduce((options, vnode) => { - if (vnode.componentOptions.tag === 't-option') { - const propsData = vnode.componentOptions.propsData as any; - return options.concat({ - label: propsData.label, - value: propsData.value, - disabled: propsData.disabled, - content: propsData.content, - default: propsData.default, - }); - } - if (vnode.componentOptions.tag === 't-option-group') { - return options.concat(parseOptions(vnode.componentOptions.children)); - } - return options; - }, []); - } + mounted() { + this.initOptions(); + }, + updated() { + this.initOptions(); }, render(): VNode { diff --git a/test/ssr/__snapshots__/ssr.test.js.snap b/test/ssr/__snapshots__/ssr.test.js.snap index 66da774e1..673d19e96 100644 --- a/test/ssr/__snapshots__/ssr.test.js.snap +++ b/test/ssr/__snapshots__/ssr.test.js.snap @@ -10636,6 +10636,83 @@ exports[`ssr snapshot test renders ./examples/table/demos/custom-cell.vue correc `; +exports[`ssr snapshot test renders ./examples/table/demos/custom-col.vue correctly 1`] = ` +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
序号平台类型默认值是否必传详情信息
0共有String-读取 0 个数据的嵌套信息值
1私有Number0读取 1 个数据的嵌套信息值
2共有Array[]读取 2 个数据的嵌套信息值
3私有Object{}读取 3 个数据的嵌套信息值
4共有String-读取 4 个数据的嵌套信息值
+
+
+
+
+`; + exports[`ssr snapshot test renders ./examples/table/demos/custom-header.vue correctly 1`] = `
From 027508b55f423a8ffec3276b8b1c330024f10cc2 Mon Sep 17 00:00:00 2001 From: ikeq Date: Tue, 22 Feb 2022 15:03:50 +0800 Subject: [PATCH 2/5] fix(select): improve empty ui --- src/select/select.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/select/select.tsx b/src/select/select.tsx index f6f357b28..1718ae8ac 100644 --- a/src/select/select.tsx +++ b/src/select/select.tsx @@ -673,7 +673,7 @@ export default mixins(getConfigReceiverMixins('select')).exte {loading &&
{loadingTextSlot}
} - {!loading && !displayOptions.length && !showCreateOption &&
  • {emptySlot}
  • } + {!loading && !displayOptions.length && !showCreateOption &&
    {emptySlot}
    } {!this.hasOptions && displayOptions.length && !loading ? ( this.renderDataWithOptions() ) : ( From 198c2a1131daa92969577773f9e3440e1a6bf2c4 Mon Sep 17 00:00:00 2001 From: ikeq Date: Tue, 22 Feb 2022 15:54:16 +0800 Subject: [PATCH 3/5] fix(popup): improve robustness --- src/popup/popup.tsx | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/popup/popup.tsx b/src/popup/popup.tsx index 1010a572b..daf53b697 100644 --- a/src/popup/popup.tsx +++ b/src/popup/popup.tsx @@ -53,6 +53,10 @@ export default Vue.extend({ /** if a trusted action (opening or closing) is prevented, increase this flag */ visibleState: 0, mouseInRange: false, + /** + * mark popup as clicked when mousedown + * consume this flag right after click event bubbles up to document + */ contentClicked: false, refClicked: false, }; @@ -328,17 +332,24 @@ export default Vue.extend({ directives: destroyOnClose ? undefined : [ - { - name: 'show', - rawName: 'v-show', - value: visible, - expression: 'visible', - } as VNodeDirective, + { + name: 'show', + rawName: 'v-show', + value: visible, + expression: 'visible', + } as VNodeDirective, ], on: { - click: () => { + mousedown: () => { this.contentClicked = true; }, + mouseup: () => { + // make sure to execute after document click is triggered + setTimeout(() => { + // make sure flag is consumed + this.contentClicked = false; + }); + }, ...(hasTrigger.hover && { mouseenter: this.onMouseEnter, mouseleave: this.onMouseLeave, From 058c753506b56dab0a6db0b7a57a3a9d1c611f54 Mon Sep 17 00:00:00 2001 From: ikeq Date: Tue, 22 Feb 2022 16:53:21 +0800 Subject: [PATCH 4/5] fix(select): Improve options initial parsing logic --- src/select/select.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/select/select.tsx b/src/select/select.tsx index 1718ae8ac..d6991d998 100644 --- a/src/select/select.tsx +++ b/src/select/select.tsx @@ -700,18 +700,19 @@ export default mixins(getConfigReceiverMixins('select')).exte function parseOptions(vnodes: VNode[]): TdOptionProps[] { if (!vnodes) return []; return vnodes.reduce((options, vnode) => { - if (vnode.componentOptions?.tag === 't-option') { - const propsData = vnode.componentOptions.propsData as any; + const { componentOptions } = vnode; + if (componentOptions?.tag === 't-option') { + const propsData = componentOptions.propsData as any; return options.concat({ label: propsData.label, value: propsData.value, disabled: propsData.disabled, - content: propsData.content, + content: componentOptions.children ? () => componentOptions.children : propsData.content, default: propsData.default, }); } - if (vnode.componentOptions?.tag === 't-option-group') { - return options.concat(parseOptions(vnode.componentOptions.children)); + if (componentOptions?.tag === 't-option-group') { + return options.concat(parseOptions(componentOptions.children)); } return options; }, []); From 162a9d7dd143b9160bec4d792329295ab7c3c65c Mon Sep 17 00:00:00 2001 From: ikeq Date: Wed, 23 Feb 2022 13:28:06 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix(popup):=20=E4=BF=AE=E5=A4=8D=20popup=20?= =?UTF-8?q?=E8=A7=A6=E5=8F=91=E5=85=83=E7=B4=A0=E5=B0=BA=E5=AF=B8=E5=8F=98?= =?UTF-8?q?=E5=8C=96=E5=90=8E=E4=BD=8D=E7=BD=AE=E4=B8=8D=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/popup/container.tsx | 37 ++++++++++++++++++++++++++++++++++++- src/popup/popup.tsx | 5 +++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/popup/container.tsx b/src/popup/container.tsx index 80f2bb6d7..e2c01677d 100644 --- a/src/popup/container.tsx +++ b/src/popup/container.tsx @@ -2,7 +2,42 @@ import Vue from 'vue'; import { getAttach } from '../utils/dom'; import props from './props'; +function isContentRectChanged(rect1: DOMRectReadOnly, rect2: DOMRectReadOnly) { + if (!rect1 || !rect2) return; + if (['width', 'height', 'x', 'y'].some((k) => rect1[k] !== rect2[k])) { + return true; + } + return false; +} + const Ref = Vue.extend({ + data() { + return { + contentRect: null as DOMRectReadOnly, + }; + }, + mounted() { + if (window?.ResizeObserver && this.$el) { + const el = this.$el; + const vm = this as any; + const ro = new ResizeObserver((entries = []) => { + const { contentRect } = entries[0] || {}; + if (isContentRectChanged(contentRect, vm.contentRect)) { + vm.contentRect = contentRect; + vm.$emit('resize', { ...contentRect }); + return; + } + // omit initial change + if (!vm.contentRect) { + vm.contentRect = contentRect; + } + }); + ro.observe(el); + this.$on('hook:destroyed', () => { + ro.unobserve(el); + }); + } + }, render() { const children = this.$slots.default || []; if (children.length > 1 || !children[0]?.tag) { @@ -68,6 +103,6 @@ export default Vue.extend({ }, }, render() { - return {this.$slots.default}; + return this.$emit('refResize', ev)}>{this.$slots.default}; }, }); diff --git a/src/popup/popup.tsx b/src/popup/popup.tsx index daf53b697..fcb46e067 100644 --- a/src/popup/popup.tsx +++ b/src/popup/popup.tsx @@ -385,6 +385,11 @@ export default Vue.extend({ this.updateOverlayStyle(); } }} + onRefResize={() => { + if (visible) { + this.updatePopper(); + } + }} parent={this} visible={visible} attach={this.attach}