diff --git a/packages/vant/src/text-ellipsis/TextEllipsis.tsx b/packages/vant/src/text-ellipsis/TextEllipsis.tsx index 3ebe1be27..4d4ea69ed 100644 --- a/packages/vant/src/text-ellipsis/TextEllipsis.tsx +++ b/packages/vant/src/text-ellipsis/TextEllipsis.tsx @@ -2,6 +2,7 @@ import { ref, watch, computed, + onActivated, onMounted, defineComponent, type ExtractPropTypes, @@ -42,6 +43,7 @@ export default defineComponent({ const expanded = ref(false); const hasAction = ref(false); const root = ref(); + let needRecalculate = false; const actionText = computed(() => expanded.value ? props.collapseText : props.expandText, @@ -53,29 +55,31 @@ export default defineComponent({ return match ? Number(match[0]) : 0; }; + const cloneContainer = () => { + if (!root.value || !root.value.isConnected) return; + + const originStyle = window.getComputedStyle(root.value); + const container = document.createElement('div'); + const styleNames: string[] = Array.prototype.slice.apply(originStyle); + + styleNames.forEach((name) => { + container.style.setProperty(name, originStyle.getPropertyValue(name)); + }); + + container.style.position = 'fixed'; + container.style.zIndex = '-9999'; + container.style.top = '-9999px'; + container.style.height = 'auto'; + container.style.minHeight = 'auto'; + container.style.maxHeight = 'auto'; + + container.innerText = props.content; + document.body.appendChild(container); + + return container; + }; + const calcEllipsised = () => { - const cloneContainer = () => { - if (!root.value) return; - - const originStyle = window.getComputedStyle(root.value); - const container = document.createElement('div'); - const styleNames: string[] = Array.prototype.slice.apply(originStyle); - styleNames.forEach((name) => { - container.style.setProperty(name, originStyle.getPropertyValue(name)); - }); - - container.style.position = 'fixed'; - container.style.zIndex = '-9999'; - container.style.top = '-9999px'; - container.style.height = 'auto'; - container.style.minHeight = 'auto'; - container.style.maxHeight = 'auto'; - - container.innerText = props.content; - document.body.appendChild(container); - return container; - }; - const calcEllipsisText = ( container: HTMLDivElement, maxHeight: number, @@ -168,7 +172,12 @@ export default defineComponent({ // Calculate the interceptional text const container = cloneContainer(); - if (!container) return; + + if (!container) { + needRecalculate = true; + return; + } + const { paddingBottom, paddingTop, lineHeight } = container.style; const maxHeight = Math.ceil( (Number(props.rows) + 0.5) * pxToNum(lineHeight) + @@ -209,6 +218,13 @@ export default defineComponent({ onMounted(calcEllipsised); + onActivated(() => { + if (needRecalculate) { + needRecalculate = false; + calcEllipsised(); + } + }); + watch( [windowWidth, () => [props.content, props.rows, props.position]], calcEllipsised, diff --git a/packages/vant/src/text-ellipsis/test/__snapshots__/index.spec.ts.snap b/packages/vant/src/text-ellipsis/test/__snapshots__/index.spec.tsx.snap similarity index 100% rename from packages/vant/src/text-ellipsis/test/__snapshots__/index.spec.ts.snap rename to packages/vant/src/text-ellipsis/test/__snapshots__/index.spec.tsx.snap diff --git a/packages/vant/src/text-ellipsis/test/index.spec.ts b/packages/vant/src/text-ellipsis/test/index.spec.tsx similarity index 72% rename from packages/vant/src/text-ellipsis/test/index.spec.ts rename to packages/vant/src/text-ellipsis/test/index.spec.tsx index f5f142079..4f2b049b0 100644 --- a/packages/vant/src/text-ellipsis/test/index.spec.ts +++ b/packages/vant/src/text-ellipsis/test/index.spec.tsx @@ -1,5 +1,5 @@ import { mount } from '../../../test'; -import { nextTick } from 'vue'; +import { defineComponent, KeepAlive, nextTick } from 'vue'; import TextEllipsis, { type TextEllipsisInstance } from '..'; const originGetComputedStyle = window.getComputedStyle; @@ -34,6 +34,7 @@ afterAll(() => { test('should render action slot correctly', async () => { const wrapper = mount(TextEllipsis, { + attachTo: document.body, props: { content, }, @@ -57,6 +58,7 @@ test('should render action slot correctly', async () => { test('should render content correctly', async () => { const wrapper = mount(TextEllipsis, { + attachTo: document.body, props: { content, }, @@ -68,6 +70,7 @@ test('should render content correctly', async () => { test('Expand and Collapse should be work', async () => { const wrapper = mount(TextEllipsis, { + attachTo: document.body, props: { content, expandText: 'expand', @@ -83,6 +86,7 @@ test('Expand and Collapse should be work', async () => { test('should emit click event after Expand/Collapse is clicked', async () => { const wrapper = mount(TextEllipsis, { + attachTo: document.body, props: { content, expandText: 'expand', @@ -102,6 +106,7 @@ test('text not exceeded', async () => { const shortContent = 'Vant is a component library'; const wrapper = mount(TextEllipsis, { + attachTo: document.body, props: { content: shortContent, expandText: 'expand', @@ -112,3 +117,45 @@ test('text not exceeded', async () => { await nextTick(); expect(wrapper.text()).not.toMatch('...'); }); + +// https://github.com/vant-ui/vant/issues/12445 +test('should recalculate the ellipsis state when the component is activated', async () => { + vi.useFakeTimers(); + + const Comp = defineComponent({ + data() { + return { + show: false, + }; + }, + beforeMount() { + setTimeout(() => { + this.show = true; + }, 1000); + }, + render() { + return this.show ? : null; + }, + }); + + const wrapper = mount( + { + data() { + return { + render: true, + }; + }, + render() { + return {this.render ? : null}; + }, + }, + { attachTo: document.body }, + ); + + wrapper.setData({ render: false }); + await vi.advanceTimersByTimeAsync(1000); + await wrapper.setData({ render: true }); + expect(wrapper.text()).toMatch(content); + + vi.useRealTimers(); +});