diff --git a/packages/components/affix/__tests__/affix.test.tsx b/packages/components/affix/__tests__/affix.test.tsx index 6f4933b7e3..b2a08b7093 100644 --- a/packages/components/affix/__tests__/affix.test.tsx +++ b/packages/components/affix/__tests__/affix.test.tsx @@ -1,134 +1,923 @@ import { nextTick } from 'vue'; import { mount } from '@vue/test-utils'; -import { beforeEach, expect, it, vi } from 'vitest'; -import { Affix } from '@tdesign/components/affix'; +import { beforeEach, expect, it, vi, describe } from 'vitest'; +import { Affix } from '@tdesign/components'; describe('Affix', () => { - test('_______', () => { - expect(true).toEqual(true); - }); - vi.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => { cb(performance.now()); return 1; }); - describe('Test the state of the container under the window', () => { - const offsetTop = 10; - const slotWidth = 100; - const slotHeight = 20; + describe('props', () => { + it(':offsetTop[number]', async () => { + const offsetTop = 10; + const wrapper = mount(Content); + await nextTick(); + expect(wrapper.exists()).toBeTruthy(); + }); - const wrapper = mount({ - render() { - return ( - -
hello world
-
- ); - }, + it(':offsetBottom[number]', async () => { + const offsetBottom = 50; + const wrapper = mount(Content); + await nextTick(); + expect(wrapper.exists()).toBeTruthy(); }); - // TODO PAOPAO need refactor - const { affixRef } = wrapper.vm.$refs as { affixRef: { affixWrapRef: any; scrollContainer: HTMLElement } }; - // 模拟 affixWrap 的位置 - vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ - top: 5, - width: slotWidth, - height: slotHeight, - })); - it('Test get container', async () => { + it(':zIndex[number]', async () => { + const zIndex = 1000; + const wrapper = mount(Content); await nextTick(); - expect(affixRef.scrollContainer).toBe(window); + expect(wrapper.exists()).toBeTruthy(); }); - it('Test the scrolling state', async () => { - // 模拟滚动触发 - window.dispatchEvent(new CustomEvent('scroll')); - expect(wrapper.find('.t-affix').classes()).toContain('t-affix'); + it(':container[string]', async () => { + const wrapper = mount(Content); + await nextTick(); + expect(wrapper.exists()).toBeTruthy(); }); - it('Test the position in the scroll state', () => { - // 模拟滚动触发 - window.dispatchEvent(new CustomEvent('scroll')); - const style = wrapper.find('.t-affix').attributes('style'); - expect(style).toBe(`top: ${offsetTop}px; width: ${slotWidth}px; height: ${slotHeight}px;`); + it(':container[function]', async () => { + const wrapper = mount({ + methods: { + container(): any { + return (this as any).$refs?.container; + }, + }, + render() { + return ( +
+ Content +
+ ); + }, + }); + await nextTick(); + expect(wrapper.exists()).toBeTruthy(); }); - it('Test the generation of placeholder nodes', () => { - // 模拟滚动触发 - window.dispatchEvent(new CustomEvent('scroll')); - expect(wrapper.html()).toContain(`
`); + it(':content[string]', async () => { + const wrapper = mount(); + await nextTick(); + expect(wrapper.text()).toBe('Affix Content'); + }); + + it(':content[function]', async () => { + const contentFn = () => 'Custom Content'; + const wrapper = mount(); + await nextTick(); + expect(wrapper.text()).toBe('Custom Content'); + }); + + it(':onFixedChange[function]', async () => { + const onFixedChange = vi.fn(); + const wrapper = mount(Content); + await nextTick(); + expect(wrapper.exists()).toBeTruthy(); }); }); - describe('Test the specified container', () => { - const offsetTop = 10; - const slotWidth = 100; - const slotHeight = 20; - const containerTop = 100; - - const wrapper = mount({ - methods: { - // TODO PAOPAO need refactor - // @ts-ignore - container() { - // TODO PAOPAO need refactor - // @ts-ignore - return (this.$refs as any)?.container; - }, - }, - render() { - return ( -
- {/* // TODO PAOPAO need refactor */} - {/* @ts-ignore */} - -
hello world
-
-
- ); - }, + describe('events', () => { + it('@fixedChange', async () => { + const onFixedChange = vi.fn(); + const wrapper = mount( + + Content + , + ); + + // Mock getBoundingClientRect to trigger fixed state + const affixRef = (wrapper.vm.$refs as any).affixRef; + if (affixRef) { + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 5, + width: 100, + height: 20, + })); + + // Trigger scroll to activate fixed state + window.dispatchEvent(new CustomEvent('scroll')); + await nextTick(); + + expect(onFixedChange).toHaveBeenCalled(); + } }); + }); - // TODO PAOPAO need refactor - const { affixRef } = wrapper.vm.$refs as { - affixRef: { affixWrapRef: any; scrollContainer: any; handleScroll: () => void }; - }; + describe('slots', () => { + it('default slot', async () => { + const wrapper = mount(Affix, { + slots: { + default: '
Custom Slot Content
', + }, + }); - it('Test get container', async () => { await nextTick(); - expect(affixRef.scrollContainer).toBe(wrapper.vm.container()); + expect(wrapper.find('.custom-content').exists()).toBe(true); + expect(wrapper.find('.custom-content').text()).toBe('Custom Slot Content'); }); - // 模拟 affixWrap 的位置 - beforeEach(() => { + + it('content slot', async () => { + const wrapper = mount(Affix, { + slots: { + content: 'Slot Content', + }, + }); + + await nextTick(); + expect(wrapper.find('.custom-span').exists()).toBe(true); + expect(wrapper.find('.custom-span').text()).toBe('Slot Content'); + }); + }); + + describe('functionality', () => { + describe('window container', () => { + const offsetTop = 10; + const slotWidth = 100; + const slotHeight = 20; + + const wrapper = mount({ + render() { + return ( + +
hello world
+
+ ); + }, + }); + + const { affixRef } = wrapper.vm.$refs as { affixRef: { affixWrapRef: any; scrollContainer: HTMLElement } }; + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ top: 5, width: slotWidth, height: slotHeight, })); + + it('should get window as default container', async () => { + await nextTick(); + expect(affixRef.scrollContainer).toBe(window); + }); + + it('should apply fixed class when scrolling', async () => { + window.dispatchEvent(new CustomEvent('scroll')); + expect(wrapper.find('.t-affix').classes()).toContain('t-affix'); + }); + + it('should calculate correct position when fixed', () => { + window.dispatchEvent(new CustomEvent('scroll')); + const style = wrapper.find('.t-affix').attributes('style'); + expect(style).toBe(`top: ${offsetTop}px; width: ${slotWidth}px; height: ${slotHeight}px;`); + }); + + it('should generate placeholder element when fixed', () => { + window.dispatchEvent(new CustomEvent('scroll')); + expect(wrapper.html()).toContain(`
`); + }); }); - it('Test the scrolling state', async () => { - // 模拟容器滚动 - wrapper.vm.container().dispatchEvent(new CustomEvent('scroll')); - expect(wrapper.find('.t-affix').classes()).toContain('t-affix'); + describe('custom container', () => { + const offsetTop = 10; + const slotWidth = 100; + const slotHeight = 20; + const containerTop = 100; + + const wrapper = mount({ + methods: { + container(): any { + return (this as any).$refs?.container; + }, + }, + render() { + return ( +
+ +
hello world
+
+
+ ); + }, + }); + + const { affixRef } = wrapper.vm.$refs as { + affixRef: { affixWrapRef: any; scrollContainer: any; handleScroll: () => void }; + }; + + it('should get custom container', async () => { + await nextTick(); + expect(affixRef.scrollContainer).toBe((wrapper.vm as any).container()); + }); + + beforeEach(() => { + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 5, + width: slotWidth, + height: slotHeight, + })); + }); + + it('should apply fixed class when container scrolling', async () => { + (wrapper.vm as any).container().dispatchEvent(new CustomEvent('scroll')); + expect(wrapper.find('.t-affix').classes()).toContain('t-affix'); + }); + + beforeEach(() => { + window.addEventListener('scroll', affixRef.handleScroll); + vi.spyOn(affixRef.scrollContainer, 'getBoundingClientRect').mockImplementation(() => ({ + top: containerTop, + })); + }); + + it('should calculate correct position relative to container', () => { + window.dispatchEvent(new CustomEvent('scroll')); + const style = wrapper.find('.t-affix').attributes('style'); + expect(style).toBe(`top: ${offsetTop + containerTop}px; width: ${slotWidth}px; height: ${slotHeight}px;`); + }); }); - beforeEach(() => { - // 模拟绑定 - window.addEventListener('scroll', affixRef.handleScroll); - // 模拟容器的位置 - vi.spyOn(affixRef.scrollContainer, 'getBoundingClientRect').mockImplementation(() => ({ - top: containerTop, + describe('offsetBottom', () => { + const offsetBottom = 50; + const slotWidth = 100; + const slotHeight = 20; + const containerHeight = 400; + const containerTop = 0; + + const wrapper = mount({ + methods: { + container(): any { + return (this as any).$refs?.container; + }, + }, + render() { + return ( +
+ +
hello world
+
+
+ ); + }, + }); + + const { affixRef } = wrapper.vm.$refs as { + affixRef: { affixWrapRef: any; scrollContainer: any; handleScroll: () => void }; + }; + + beforeEach(() => { + vi.spyOn(affixRef.scrollContainer, 'getBoundingClientRect').mockImplementation(() => ({ + top: containerTop, + })); + + Object.defineProperty(affixRef.scrollContainer, 'clientHeight', { + value: containerHeight, + writable: true, + }); + }); + + it('should trigger when element reaches bottom boundary', async () => { + await nextTick(); + + const wrapToTop = containerHeight - offsetBottom + 10; + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: wrapToTop, + width: slotWidth, + height: slotHeight, + })); + + affixRef.handleScroll(); + await nextTick(); + + expect(wrapper.find('.t-affix').classes()).toContain('t-affix'); + }); + + it('should calculate correct bottom position', async () => { + await nextTick(); + + const wrapToTop = containerHeight - offsetBottom + 10; + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: wrapToTop, + width: slotWidth, + height: slotHeight, + })); + + affixRef.handleScroll(); + await nextTick(); + + const expectedTop = containerTop + containerHeight - slotHeight - offsetBottom; + const style = wrapper.find('.t-affix').attributes('style'); + expect(style).toBe(`top: ${expectedTop}px; width: ${slotWidth}px; height: ${slotHeight}px;`); + }); + + it('should not trigger when element is above bottom boundary', async () => { + const testWrapper = mount({ + methods: { + container(): any { + return (this as any).$refs?.container; + }, + }, + render() { + return ( +
+ +
hello world
+
+
+ ); + }, + }); + + const { testAffixRef } = testWrapper.vm.$refs as { + testAffixRef: { affixWrapRef: any; scrollContainer: any; handleScroll: () => void }; + }; + + await nextTick(); + + vi.spyOn(testAffixRef.scrollContainer, 'getBoundingClientRect').mockImplementation(() => ({ + top: containerTop, + })); + + Object.defineProperty(testAffixRef.scrollContainer, 'clientHeight', { + value: containerHeight, + writable: true, + }); + + const normalPosition = 50; + vi.spyOn(testAffixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: normalPosition, + width: slotWidth, + height: slotHeight, + })); + + testAffixRef.handleScroll(); + await nextTick(); + + const affixElements = testWrapper.findAll('.t-affix'); + expect(affixElements.length).toBe(0); + }); + + it('should create placeholder element for offsetBottom', async () => { + await nextTick(); + + const wrapToTop = containerHeight - offsetBottom + 10; + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: wrapToTop, + width: slotWidth, + height: slotHeight, + })); + + affixRef.handleScroll(); + await nextTick(); + + expect(wrapper.html()).toContain(`
`); + }); + }); + + describe('event binding/unbinding', () => { + const offsetTop = 10; + const slotWidth = 100; + const slotHeight = 20; + + it('should remove event listeners when component unmounts', async () => { + const testWrapper = mount({ + methods: { + container(): any { + return (this as any).$refs?.container; + }, + }, + render() { + return ( +
+ +
test content
+
+
+ ); + }, + }); + + const testAffixRef = (testWrapper.vm as any).$refs.testAffixRef; + await nextTick(); + + expect(testAffixRef.scrollContainer).toBeDefined(); + + const offSpy = vi.fn(); + vi.doMock('@tdesign/shared-utils', () => ({ + off: offSpy, + on: vi.fn(), + getScrollContainer: vi.fn(() => testAffixRef.scrollContainer), + })); + + const mockRAFId = 123; + const cancelAnimationFrameSpy = vi.spyOn(window, 'cancelAnimationFrame'); + vi.spyOn(window, 'requestAnimationFrame').mockReturnValue(mockRAFId); + vi.spyOn(testAffixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 5, + width: slotWidth, + height: slotHeight, + })); + + testAffixRef.handleScroll(); + testWrapper.unmount(); + await nextTick(); + + expect(cancelAnimationFrameSpy).toHaveBeenCalledWith(mockRAFId); + vi.restoreAllMocks(); + }); + + it('should handle null scrollContainer gracefully', async () => { + const testWrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + + const testAffixRef = (testWrapper.vm.$refs as any).affixRef; + if (testAffixRef) { + testAffixRef.scrollContainer = { value: null }; + } + + expect(() => { + testWrapper.unmount(); + }).not.toThrow(); + }); + + it('should handle missing rAFId gracefully', async () => { + const testWrapper = mount({ + methods: { + container(): any { + return (this as any).$refs?.container; + }, + }, + render() { + return ( +
+ +
test content
+
+
+ ); + }, + }); + + const testAffixRef = (testWrapper.vm.$refs as any).testAffixRef; + await nextTick(); + + expect(testAffixRef.scrollContainer).toBeDefined(); + + const cancelAnimationFrameSpy = vi.spyOn(window, 'cancelAnimationFrame'); + + testWrapper.unmount(); + await nextTick(); + + expect(cancelAnimationFrameSpy).not.toHaveBeenCalled(); + vi.restoreAllMocks(); + }); + + it('should manage isBind state correctly', async () => { + const testWrapper = mount({ + methods: { + container(): any { + return (this as any).$refs?.container; + }, + }, + render() { + return ( +
+ +
test content
+
+
+ ); + }, + }); + + const testAffixRef = (testWrapper.vm.$refs as any).testAffixRef; + await nextTick(); + + expect(testAffixRef.scrollContainer).toBeDefined(); + + expect(() => { + testWrapper.unmount(); + }).not.toThrow(); + + expect(() => { + testWrapper.unmount(); + }).not.toThrow(); + }); + + it('should handle bindScroll early return when already bound', async () => { + const testWrapper = mount({ + methods: { + container(): any { + return (this as any).$refs?.container; + }, + }, + render() { + return ( +
+ +
test content
+
+
+ ); + }, + }); + + await nextTick(); + + const testAffixRef = (testWrapper.vm.$refs as any).testAffixRef; + expect(testAffixRef).toBeDefined(); + expect(testAffixRef.scrollContainer).toBeDefined(); + + expect(() => { + testAffixRef.handleScroll(); + }).not.toThrow(); + + testWrapper.unmount(); + }); + }); + + describe('props watchers', () => { + it('should trigger component update when props change', async () => { + const testWrapper = mount(Affix, { + props: { + offsetTop: 10, + offsetBottom: 10, + zIndex: 100, + }, + slots: { + default: '
test content
', + }, + }); + + await nextTick(); + expect(testWrapper.exists()).toBe(true); + + await testWrapper.setProps({ offsetTop: 20 }); + await nextTick(); + expect(testWrapper.exists()).toBe(true); + + await testWrapper.setProps({ offsetBottom: 20 }); + await nextTick(); + expect(testWrapper.exists()).toBe(true); + + await testWrapper.setProps({ zIndex: 200 }); + await nextTick(); + expect(testWrapper.exists()).toBe(true); + + await testWrapper.setProps({ + offsetTop: 30, + offsetBottom: 30, + zIndex: 300, + }); + await nextTick(); + expect(testWrapper.exists()).toBe(true); + + testWrapper.unmount(); + }); + + it('should handle undefined values correctly', async () => { + const testWrapper = mount(Affix, { + props: { + offsetTop: undefined, + offsetBottom: undefined, + zIndex: undefined, + }, + slots: { + default: '
test content
', + }, + }); + + await nextTick(); + expect(testWrapper.exists()).toBe(true); + + await testWrapper.setProps({ offsetTop: 10, offsetBottom: 10, zIndex: 100 }); + await nextTick(); + expect(testWrapper.exists()).toBe(true); + + await testWrapper.setProps({ offsetTop: undefined, offsetBottom: undefined, zIndex: undefined }); + await nextTick(); + expect(testWrapper.exists()).toBe(true); + + testWrapper.unmount(); + }); + + it('should handle rapid prop changes', async () => { + const testWrapper = mount(Affix, { + props: { offsetTop: 10 }, + slots: { default: '
test content
' }, + }); + + await nextTick(); + + for (let i = 0; i < 3; i++) { + await testWrapper.setProps({ offsetTop: 10 + i * 5, zIndex: 100 + i * 10 }); + } + + await nextTick(); + expect(testWrapper.exists()).toBe(true); + expect(testWrapper.find('div').exists()).toBe(true); + + testWrapper.unmount(); + }); + }); + }); + + describe('internal logic', () => { + it('should expose scrollContainer, affixWrapRef, and handleScroll', async () => { + const wrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + const affixRef = (wrapper.vm.$refs as any).affixRef; + + expect(affixRef.scrollContainer).toBeDefined(); + expect(affixRef.affixWrapRef).toBeDefined(); + expect(typeof affixRef.handleScroll).toBe('function'); + }); + + it('should handle ticking state correctly', async () => { + const wrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + const affixRef = (wrapper.vm.$refs as any).affixRef; + + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 5, + width: 100, + height: 20, + })); + + // 第一次调用 handleScroll + affixRef.handleScroll(); + // 立即再次调用,应该被 ticking 状态阻止 + affixRef.handleScroll(); + + await nextTick(); + expect(wrapper.exists()).toBe(true); + }); + + it('should calculate fixedTop correctly for offsetTop', async () => { + const offsetTop = 20; + const wrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + const affixRef = (wrapper.vm.$refs as any).affixRef; + + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 10, // 小于 offsetTop,应该触发固定 + width: 100, + height: 20, + })); + + window.dispatchEvent(new CustomEvent('scroll')); + await nextTick(); + + const affixElement = wrapper.find('.t-affix'); + if (affixElement.exists()) { + const style = affixElement.attributes('style'); + expect(style).toContain(`top: ${offsetTop}px`); + } + }); + + it('should not apply fixed when element is in normal position', async () => { + const offsetTop = 20; + const wrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + const affixRef = (wrapper.vm.$refs as any).affixRef; + + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 100, // 大于 offsetTop,不应该固定 + width: 100, + height: 20, + })); + + affixRef.handleScroll(); + await nextTick(); + + const affixElements = wrapper.findAll('.t-affix'); + expect(affixElements.length).toBe(0); + }); + + it('should apply zIndex when fixed', async () => { + const zIndex = 999; + const wrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + const affixRef = (wrapper.vm.$refs as any).affixRef; + + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 5, + width: 100, + height: 20, + })); + + window.dispatchEvent(new CustomEvent('scroll')); + await nextTick(); + + const affixElement = wrapper.find('.t-affix'); + if (affixElement.exists()) { + const style = affixElement.attributes('style'); + expect(style).toContain(`z-index: ${zIndex}`); + } + }); + + it('should remove placeholder when not fixed', async () => { + const wrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + const affixRef = (wrapper.vm.$refs as any).affixRef; + + // 先触发固定状态 + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 5, + width: 100, + height: 20, + })); + + window.dispatchEvent(new CustomEvent('scroll')); + await nextTick(); + + // 改变位置,取消固定 + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 100, + width: 100, + height: 20, })); + + window.dispatchEvent(new CustomEvent('scroll')); + await nextTick(); + + // 验证 class 被移除 + const affixElements = wrapper.findAll('.t-affix'); + expect(affixElements.length).toBe(0); }); - it('Test the positioning after opening the binding window sliding event', () => { - // 模拟滚动触发 + it('should emit fixedChange with correct parameters', async () => { + const onFixedChange = vi.fn(); + const wrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + const affixRef = (wrapper.vm.$refs as any).affixRef; + + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 5, + width: 100, + height: 20, + })); + window.dispatchEvent(new CustomEvent('scroll')); + await nextTick(); + + if (onFixedChange.mock.calls.length > 0) { + const [affixed, context] = onFixedChange.mock.calls[0]; + expect(affixed).toBe(true); + expect(context).toHaveProperty('top'); + expect(typeof context.top).toBe('number'); + } + }); + + it('should handle getBoundingClientRect returning undefined', async () => { + const wrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + const affixRef = (wrapper.vm.$refs as any).affixRef; + + // Mock getBoundingClientRect 返回 undefined + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => undefined); + + expect(() => { + affixRef.handleScroll(); + }).not.toThrow(); + }); + + it('should handle window resize event', async () => { + const onFixedChange = vi.fn(); + const wrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + const affixRef = (wrapper.vm.$refs as any).affixRef; + + vi.spyOn(affixRef.affixWrapRef, 'getBoundingClientRect').mockImplementation(() => ({ + top: 5, + width: 100, + height: 20, + })); + + window.dispatchEvent(new Event('resize')); + await nextTick(); + + // resize 事件会触发 handleScroll,进而可能触发 fixedChange + expect(wrapper.exists()).toBe(true); + }); + + it('should handle keep-alive activation/deactivation', async () => { + const wrapper = mount({ + render() { + return ( + +
test content
+
+ ); + }, + }); + + await nextTick(); + const affixRef = (wrapper.vm.$refs as any).affixRef; + + expect(affixRef.scrollContainer).toBeDefined(); - const style = wrapper.find('.t-affix').attributes('style'); - expect(style).toBe(`top: ${offsetTop + containerTop}px; width: ${slotWidth}px; height: ${slotHeight}px;`); + expect(() => { + affixRef.handleScroll(); + }).not.toThrow(); }); }); }); diff --git a/packages/components/affix/affix.en-US.md b/packages/components/affix/affix.en-US.md index ea64503f04..861b0efe25 100644 --- a/packages/components/affix/affix.en-US.md +++ b/packages/components/affix/affix.en-US.md @@ -6,7 +6,7 @@ name | type | default | description | required -- | -- | -- | -- | -- container | String / Function | () => (() => window) | Typescript:`ScrollContainer`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/common.ts) | N -content(暂未实现) | String / Slot / Function | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/common.ts) | N +content | String / Slot / Function | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/common.ts) | N default | String / Slot / Function | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/common.ts) | N offsetBottom | Number | 0 | When the distance from the bottom of the container reaches the specified distance, the trigger is fixed | N offsetTop | Number | 0 | When the distance from the top of the container reaches the specified distance, the trigger is fixed | N diff --git a/packages/components/affix/affix.md b/packages/components/affix/affix.md index 11efbd02ab..6d1b2fb5ab 100644 --- a/packages/components/affix/affix.md +++ b/packages/components/affix/affix.md @@ -6,7 +6,7 @@ 名称 | 类型 | 默认值 | 说明 | 必传 -- | -- | -- | -- | -- container | String / Function | () => (() => window) | 指定滚动的容器。数据类型为 String 时,会被当作选择器处理,进行节点查询。示例:'body' 或 () => document.body。TS 类型:`ScrollContainer`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/common.ts) | N -content(暂未实现) | String / Slot / Function | - | 内容。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/common.ts) | N +content | String / Slot / Function | - | 内容。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/common.ts) | N default | String / Slot / Function | - | 内容,同 content。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/common.ts) | N offsetBottom | Number | 0 | 距离容器底部达到指定距离后触发固定 | N offsetTop | Number | 0 | 距离容器顶部达到指定距离后触发固定 | N diff --git a/packages/components/affix/affix.tsx b/packages/components/affix/affix.tsx index 6ae03d1cc6..1cd9d12e08 100644 --- a/packages/components/affix/affix.tsx +++ b/packages/components/affix/affix.tsx @@ -4,7 +4,7 @@ import { isFunction, isUndefined } from 'lodash-es'; import { on, off, getScrollContainer } from '@tdesign/shared-utils'; import props from './props'; import { ScrollContainerElement } from '../common'; -import { useTNodeJSX, usePrefixClass } from '@tdesign/shared-hooks'; +import { useContent, usePrefixClass } from '@tdesign/shared-hooks'; export default defineComponent({ name: 'TAffix', @@ -12,7 +12,7 @@ export default defineComponent({ emits: ['fixedChange'], setup(props, context) { const COMPONENT_NAME = usePrefixClass('affix'); - const renderTNodeJSX = useTNodeJSX(); + const renderContent = useContent(); const affixWrapRef = ref(null); const affixRef = ref(null); @@ -149,7 +149,7 @@ export default defineComponent({ return () => (
- {renderTNodeJSX('default')} + {renderContent('default', 'content')}
); diff --git a/packages/tdesign-vue-next/.changelog/pr-5981.md b/packages/tdesign-vue-next/.changelog/pr-5981.md new file mode 100644 index 0000000000..dd8a85504e --- /dev/null +++ b/packages/tdesign-vue-next/.changelog/pr-5981.md @@ -0,0 +1,6 @@ +--- +pr_number: 5981 +contributor: ImaginingMaker +--- + +- feat(Affix): 新增支持`content`API,与其他组件保持一致 @ImaginingMaker ([#5981](https://github.com/Tencent/tdesign-vue-next/pull/5981))