From 64fef377c09167253f900058a8a2f4684ce36c1a Mon Sep 17 00:00:00 2001 From: tanjinzhou <415800467@qq.com> Date: Mon, 12 Oct 2020 17:54:43 +0800 Subject: [PATCH] refactor: anchor by ts --- components/anchor/{Anchor.jsx => Anchor.tsx} | 119 ++++++++---------- .../anchor/{AnchorLink.jsx => AnchorLink.tsx} | 25 ++-- components/anchor/{index.jsx => index.tsx} | 5 +- 3 files changed, 66 insertions(+), 83 deletions(-) rename components/anchor/{Anchor.jsx => Anchor.tsx} (74%) rename components/anchor/{AnchorLink.jsx => AnchorLink.tsx} (81%) rename components/anchor/{index.jsx => index.tsx} (66%) diff --git a/components/anchor/Anchor.jsx b/components/anchor/Anchor.tsx similarity index 74% rename from components/anchor/Anchor.jsx rename to components/anchor/Anchor.tsx index 01fbe79d4..d0a3f50e4 100644 --- a/components/anchor/Anchor.jsx +++ b/components/anchor/Anchor.tsx @@ -1,11 +1,11 @@ -import { inject, provide } from 'vue'; +import { defineComponent, inject, provide } from 'vue'; import PropTypes from '../_util/vue-types'; import classNames from '../_util/classNames'; import addEventListener from '../vc-util/Dom/addEventListener'; import Affix from '../affix'; import scrollTo from '../_util/scrollTo'; import getScroll from '../_util/getScroll'; -import { initDefaultProps, findDOMNode } from '../_util/props-util'; +import { findDOMNode } from '../_util/props-util'; import BaseMixin from '../_util/BaseMixin'; import { defaultConfigProvider } from '../config-provider'; @@ -13,7 +13,7 @@ function getDefaultContainer() { return window; } -function getOffsetTop(element, container) { +function getOffsetTop(element: HTMLElement, container: AnchorContainer): number { if (!element) { return 0; } @@ -29,61 +29,28 @@ function getOffsetTop(element, container) { container = element.ownerDocument.documentElement; return rect.top - container.clientTop; } - return rect.top - container.getBoundingClientRect().top; + return rect.top - (container as HTMLElement).getBoundingClientRect().top; } return rect.top; } -// function easeInOutCubic(t, b, c, d) { -// const cc = c - b; -// t /= d / 2; -// if (t < 1) { -// return (cc / 2) * t * t * t + b; -// } -// return (cc / 2) * ((t -= 2) * t * t + 2) + b; -// } - const sharpMatcherRegx = /#([^#]+)$/; -// function scrollTo(href, offsetTop = 0, getContainer, callback = () => {}) { -// const container = getContainer(); -// const scrollTop = getScroll(container, true); -// const sharpLinkMatch = sharpMatcherRegx.exec(href); -// if (!sharpLinkMatch) { -// return; -// } -// const targetElement = document.getElementById(sharpLinkMatch[1]); -// if (!targetElement) { -// return; -// } -// const eleOffsetTop = getOffsetTop(targetElement, container); -// const targetScrollTop = scrollTop + eleOffsetTop - offsetTop; -// const startTime = Date.now(); -// const frameFunc = () => { -// const timestamp = Date.now(); -// const time = timestamp - startTime; -// const nextScrollTop = easeInOutCubic(time, scrollTop, targetScrollTop, 450); -// if (container === window) { -// window.scrollTo(window.pageXOffset, nextScrollTop); -// } else { -// container.scrollTop = nextScrollTop; -// } -// if (time < 450) { -// raf(frameFunc); -// } else { -// callback(); -// } -// }; -// raf(frameFunc); -// } -export const AnchorProps = { +type Section = { + link: string; + top: number; +}; + +export type AnchorContainer = HTMLElement | Window; + +const AnchorProps = { prefixCls: PropTypes.string, offsetTop: PropTypes.number, bounds: PropTypes.number, - affix: PropTypes.looseBool, - showInkInFixed: PropTypes.looseBool, - getContainer: PropTypes.func, + affix: PropTypes.looseBool.def(true), + showInkInFixed: PropTypes.looseBool.def(false), + getContainer: PropTypes.func.def(getDefaultContainer), wrapperClass: PropTypes.string, wrapperStyle: PropTypes.object, getCurrentAnchor: PropTypes.func, @@ -92,30 +59,48 @@ export const AnchorProps = { onClick: PropTypes.func, }; -export default { +export interface AntAnchor { + registerLink: (link: string) => void; + unregisterLink: (link: string) => void; + $data: AnchorState; + scrollTo: (link: string) => void; + $emit?: Function +} +interface AnchorState { + activeLink: null | string; + scrollContainer: HTMLElement | Window; + links: string[]; + scrollEvent: any; + animating: boolean; + sPrefixCls?: string; +} + +export default defineComponent({ name: 'AAnchor', mixins: [BaseMixin], inheritAttrs: false, - props: initDefaultProps(AnchorProps, { - affix: true, - showInkInFixed: false, - getContainer: getDefaultContainer, - }), + props: AnchorProps, + emits: ['change', 'click'], data() { - this.links = []; - this._sPrefixCls = ''; + // this.links = []; + // this.sPrefixCls = ''; return { activeLink: null, - }; + links: [], + sPrefixCls: '', + scrollContainer: null, + scrollEvent: null, + animating: false, + } as AnchorState; }, created() { provide('antAnchor', { - registerLink: link => { + registerLink: (link: string) => { if (!this.links.includes(link)) { this.links.push(link); } }, - unregisterLink: link => { + unregisterLink: (link: string) => { const index = this.links.indexOf(link); if (index !== -1) { this.links.splice(index, 1); @@ -123,7 +108,7 @@ export default { }, $data: this.$data, scrollTo: this.handleScrollTo, - }); + } as AntAnchor); provide('antAnchorContext', this); }, setup() { @@ -171,7 +156,7 @@ export default { return activeLink; } - const linkSections = []; + const linkSections: Array
= []; const { getContainer } = this; const container = getContainer(); this.links.forEach(link => { @@ -225,7 +210,7 @@ export default { getContainer, }); }, - setCurrentActiveLink(link) { + setCurrentActiveLink(link: string) { const { activeLink } = this; if (activeLink !== link) { @@ -252,12 +237,12 @@ export default { if (typeof document === 'undefined') { return; } - const { _sPrefixCls } = this; + const { sPrefixCls } = this; const linkNode = findDOMNode(this).getElementsByClassName( - `${_sPrefixCls}-link-title-active`, + `${sPrefixCls}-link-title-active`, )[0]; if (linkNode) { - this.$refs.inkNode.style.top = `${linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5}px`; + (this.$refs.inkNode as HTMLElement).style.top = `${linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5}px`; } }, }, @@ -274,7 +259,7 @@ export default { } = this; const getPrefixCls = this.configProvider.getPrefixCls; const prefixCls = getPrefixCls('anchor', customizePrefixCls); - this._sPrefixCls = prefixCls; + this.sPrefixCls = prefixCls; const inkClass = classNames(`${prefixCls}-ink-ball`, { visible: activeLink, @@ -309,4 +294,4 @@ export default { ); }, -}; +}); diff --git a/components/anchor/AnchorLink.jsx b/components/anchor/AnchorLink.tsx similarity index 81% rename from components/anchor/AnchorLink.jsx rename to components/anchor/AnchorLink.tsx index 7fcc7c504..256cc38dc 100644 --- a/components/anchor/AnchorLink.jsx +++ b/components/anchor/AnchorLink.tsx @@ -1,22 +1,21 @@ -import { inject } from 'vue'; +import { ComponentPublicInstance, defineComponent, inject } from 'vue'; import PropTypes from '../_util/vue-types'; -import { initDefaultProps, getComponent } from '../_util/props-util'; +import { getComponent } from '../_util/props-util'; import classNames from '../_util/classNames'; import { defaultConfigProvider } from '../config-provider'; -function noop() {} +import { AntAnchor } from './Anchor'; +function noop(..._any: any[]): any {} -export const AnchorLinkProps = { +const AnchorLinkProps = { prefixCls: PropTypes.string, - href: PropTypes.string, + href: PropTypes.string.def('#'), title: PropTypes.any, target: PropTypes.string, }; -export default { +export default defineComponent({ name: 'AAnchorLink', - props: initDefaultProps(AnchorLinkProps, { - href: '#', - }), + props: AnchorLinkProps, setup() { return { antAnchor: inject('antAnchor', { @@ -24,8 +23,8 @@ export default { unregisterLink: noop, scrollTo: noop, $data: {}, - }), - antAnchorContext: inject('antAnchorContext', {}), + } as AntAnchor), + antAnchorContext: inject('antAnchorContext', {}) as ComponentPublicInstance, configProvider: inject('configProvider', defaultConfigProvider), }; }, @@ -46,7 +45,7 @@ export default { this.antAnchor.unregisterLink(this.href); }, methods: { - handleClick(e) { + handleClick(e: Event) { this.antAnchor.scrollTo(this.href); const { scrollTo } = this.antAnchor; const { href, title } = this.$props; @@ -85,4 +84,4 @@ export default { ); }, -}; +}); diff --git a/components/anchor/index.jsx b/components/anchor/index.tsx similarity index 66% rename from components/anchor/index.jsx rename to components/anchor/index.tsx index f031c9c63..1c54bb6c8 100644 --- a/components/anchor/index.jsx +++ b/components/anchor/index.tsx @@ -1,13 +1,12 @@ +import { App } from 'vue'; import Anchor from './Anchor'; import AnchorLink from './AnchorLink'; Anchor.Link = AnchorLink; /* istanbul ignore next */ -Anchor.install = function(app) { +Anchor.install = function(app: App) { app.component(Anchor.name, Anchor); app.component(Anchor.Link.name, Anchor.Link); }; -export { AnchorProps } from './Anchor'; -export { AnchorLinkProps } from './AnchorLink'; export default Anchor;