feat: Anchor supports getCurrentAnchor(activeLink) (#34799)

close #34784
This commit is contained in:
afc163 2022-03-31 11:17:17 +08:00 committed by GitHub
parent 83b979e2d5
commit 0edd112d5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 44 deletions

View File

@ -51,7 +51,7 @@ export interface AnchorProps {
showInkInFixed?: boolean; showInkInFixed?: boolean;
getContainer?: () => AnchorContainer; getContainer?: () => AnchorContainer;
/** Return customize highlight anchor */ /** Return customize highlight anchor */
getCurrentAnchor?: () => string; getCurrentAnchor?: (activeLink: string) => string;
onClick?: ( onClick?: (
e: React.MouseEvent<HTMLElement>, e: React.MouseEvent<HTMLElement>,
link: { title: React.ReactNode; href: string }, link: { title: React.ReactNode; href: string },
@ -230,7 +230,7 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState, Co
} }
// https://github.com/ant-design/ant-design/issues/30584 // https://github.com/ant-design/ant-design/issues/30584
this.setState({ this.setState({
activeLink: typeof getCurrentAnchor === 'function' ? getCurrentAnchor() : link, activeLink: typeof getCurrentAnchor === 'function' ? getCurrentAnchor(link) : link,
}); });
onChange?.(link); onChange?.(link);
}; };

View File

@ -286,19 +286,6 @@ describe('Anchor Render', () => {
expect(removeListenerSpy).toHaveBeenCalled(); expect(removeListenerSpy).toHaveBeenCalled();
}); });
it('Anchor getCurrentAnchor prop', () => {
const hash1 = getHashUrl();
const hash2 = getHashUrl();
const getCurrentAnchor = () => `#${hash2}`;
const wrapper = mount<Anchor>(
<Anchor getCurrentAnchor={getCurrentAnchor}>
<Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} />
</Anchor>,
);
expect(wrapper.instance().state.activeLink).toBe(`#${hash2}`);
});
it('Anchor targetOffset prop', async () => { it('Anchor targetOffset prop', async () => {
const hash = getHashUrl(); const hash = getHashUrl();
let dateNowMock; let dateNowMock;
@ -404,23 +391,6 @@ describe('Anchor Render', () => {
expect(onChange).toHaveBeenCalledWith(hash2); expect(onChange).toHaveBeenCalledWith(hash2);
}); });
// https://github.com/ant-design/ant-design/issues/30584
it('should trigger onChange when have getCurrentAnchor', async () => {
const hash1 = getHashUrl();
const hash2 = getHashUrl();
const onChange = jest.fn();
const wrapper = mount<Anchor>(
<Anchor onChange={onChange} getCurrentAnchor={() => hash1}>
<Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} />
</Anchor>,
);
expect(onChange).toHaveBeenCalledTimes(1);
wrapper.instance().handleScrollTo(hash2);
expect(onChange).toHaveBeenCalledTimes(2);
expect(onChange).toHaveBeenCalledWith(hash2);
});
it('invalid hash', async () => { it('invalid hash', async () => {
const wrapper = mount<Anchor>( const wrapper = mount<Anchor>(
<Anchor> <Anchor>
@ -531,4 +501,54 @@ describe('Anchor Render', () => {
dateNowMock.mockRestore(); dateNowMock.mockRestore();
}); });
describe('getCurrentAnchor', () => {
it('Anchor getCurrentAnchor prop', () => {
const hash1 = getHashUrl();
const hash2 = getHashUrl();
const getCurrentAnchor = () => `#${hash2}`;
const wrapper = mount<Anchor>(
<Anchor getCurrentAnchor={getCurrentAnchor}>
<Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} />
</Anchor>,
);
expect(wrapper.instance().state.activeLink).toBe(`#${hash2}`);
});
// https://github.com/ant-design/ant-design/issues/30584
it('should trigger onChange when have getCurrentAnchor', async () => {
const hash1 = getHashUrl();
const hash2 = getHashUrl();
const onChange = jest.fn();
const wrapper = mount<Anchor>(
<Anchor onChange={onChange} getCurrentAnchor={() => hash1}>
<Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} />
</Anchor>,
);
expect(onChange).toHaveBeenCalledTimes(1);
wrapper.instance().handleScrollTo(hash2);
expect(onChange).toHaveBeenCalledTimes(2);
expect(onChange).toHaveBeenCalledWith(hash2);
});
// https://github.com/ant-design/ant-design/issues/34784
it('getCurrentAnchor have default link as argument', async () => {
const hash1 = getHashUrl();
const hash2 = getHashUrl();
const getCurrentAnchor = jest.fn();
const wrapper = mount<Anchor>(
<Anchor getCurrentAnchor={getCurrentAnchor}>
<Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} />
</Anchor>,
);
wrapper.find(`a[href="#${hash1}"]`).simulate('click');
expect(getCurrentAnchor).toHaveBeenCalledWith(`#${hash1}`);
wrapper.find(`a[href="#${hash2}"]`).simulate('click');
expect(getCurrentAnchor).toHaveBeenCalledWith(`#${hash2}`);
});
});
}); });

View File

@ -21,7 +21,7 @@ For displaying anchor hyperlinks on page and jumping between them.
| affix | Fixed mode of Anchor | boolean | true | | | affix | Fixed mode of Anchor | boolean | true | |
| bounds | Bounding distance of anchor area | number | 5 | | | bounds | Bounding distance of anchor area | number | 5 | |
| getContainer | Scrolling container | () => HTMLElement | () => window | | | getContainer | Scrolling container | () => HTMLElement | () => window | |
| getCurrentAnchor | Customize the anchor highlight | () => string | - | | | getCurrentAnchor | Customize the anchor highlight | (activeLink: string) => string | - | |
| offsetTop | Pixels to offset from top when calculating position of scroll | number | 0 | | | offsetTop | Pixels to offset from top when calculating position of scroll | number | 0 | |
| showInkInFixed | Whether show ink-balls when `affix={false}` | boolean | false | | | showInkInFixed | Whether show ink-balls when `affix={false}` | boolean | false | |
| targetOffset | Anchor scroll offset, default as `offsetTop`, [example](#components-anchor-demo-targetOffset) | number | - | | | targetOffset | Anchor scroll offset, default as `offsetTop`, [example](#components-anchor-demo-targetOffset) | number | - | |
@ -30,8 +30,8 @@ For displaying anchor hyperlinks on page and jumping between them.
### Link Props ### Link Props
| Property | Description | Type | Default | Version | | Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- | | -------- | ----------------------------------------- | --------- | ------- | ------- |
| href | The target of hyperlink | string | | | | href | The target of hyperlink | string | | |
| target | Specifies where to display the linked URL | string | | | | target | Specifies where to display the linked URL | string | | |
| title | The content of hyperlink | ReactNode | | | | title | The content of hyperlink | ReactNode | | |

View File

@ -22,7 +22,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_1-C1JwsC/Anchor.svg
| affix | 固定模式 | boolean | true | | | affix | 固定模式 | boolean | true | |
| bounds | 锚点区域边界 | number | 5 | | | bounds | 锚点区域边界 | number | 5 | |
| getContainer | 指定滚动的容器 | () => HTMLElement | () => window | | | getContainer | 指定滚动的容器 | () => HTMLElement | () => window | |
| getCurrentAnchor | 自定义高亮的锚点 | () => string | - | | | getCurrentAnchor | 自定义高亮的锚点 | (activeLink: string) => string | - | |
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | | | | offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | | |
| showInkInFixed | `affix={false}` 时是否显示小圆点 | boolean | false | | | showInkInFixed | `affix={false}` 时是否显示小圆点 | boolean | false | |
| targetOffset | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#components-anchor-demo-targetOffset) | number | - | | | targetOffset | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#components-anchor-demo-targetOffset) | number | - | |
@ -31,8 +31,8 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_1-C1JwsC/Anchor.svg
### Link Props ### Link Props
| 成员 | 说明 | 类型 | 默认值 | 版本 | | 成员 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- | | ------ | -------------------------------- | --------- | ------ | ---- |
| href | 锚点链接 | string | - | | | href | 锚点链接 | string | - | |
| target | 该属性指定在何处显示链接的资源。 | string | - | | | target | 该属性指定在何处显示链接的资源。 | string | - | |
| title | 文字内容 | ReactNode | - | | | title | 文字内容 | ReactNode | - | |