refactor: anchor
							parent
							
								
									fbe3a48ac2
								
							
						
					
					
						commit
						a6e30c2ded
					
				|  | @ -4,10 +4,8 @@ import { | |||
|   onBeforeUnmount, | ||||
|   onMounted, | ||||
|   onUpdated, | ||||
|   provide, | ||||
|   reactive, | ||||
|   ref, | ||||
|   getCurrentInstance, | ||||
|   ExtractPropTypes, | ||||
|   computed, | ||||
| } from 'vue'; | ||||
|  | @ -18,6 +16,7 @@ import Affix from '../affix'; | |||
| import scrollTo from '../_util/scrollTo'; | ||||
| import getScroll from '../_util/getScroll'; | ||||
| import useConfigInject from '../_util/hooks/useConfigInject'; | ||||
| import useProvideAnchor from './context'; | ||||
| 
 | ||||
| function getDefaultContainer() { | ||||
|   return window; | ||||
|  | @ -67,15 +66,7 @@ const anchorProps = { | |||
| 
 | ||||
| export type AnchorProps = Partial<ExtractPropTypes<typeof anchorProps>>; | ||||
| 
 | ||||
| export interface AntAnchor { | ||||
|   registerLink: (link: string) => void; | ||||
|   unregisterLink: (link: string) => void; | ||||
|   $data: AnchorState; | ||||
|   scrollTo: (link: string) => void; | ||||
|   $emit?: Function; | ||||
| } | ||||
| export interface AnchorState { | ||||
|   activeLink: null | string; | ||||
|   scrollContainer: HTMLElement | Window; | ||||
|   links: string[]; | ||||
|   scrollEvent: any; | ||||
|  | @ -89,25 +80,21 @@ export default defineComponent({ | |||
|   emits: ['change', 'click'], | ||||
|   setup(props, { emit, attrs, slots }) { | ||||
|     const { prefixCls, getTargetContainer, direction } = useConfigInject('anchor', props); | ||||
|     const instance = getCurrentInstance(); | ||||
|     const inkNodeRef = ref(); | ||||
|     const anchorRef = ref(); | ||||
|     const state = reactive<AnchorState>({ | ||||
|       activeLink: null, | ||||
|       links: [], | ||||
|       scrollContainer: null, | ||||
|       scrollEvent: null, | ||||
|       animating: false, | ||||
|     }); | ||||
|     const activeLink = ref(); | ||||
|     const getContainer = computed(() => { | ||||
|       const { getContainer } = props; | ||||
| 
 | ||||
|       const getFunc = getContainer || getTargetContainer.value || getDefaultContainer; | ||||
| 
 | ||||
|       return getFunc(); | ||||
|       return getContainer || getTargetContainer.value || getDefaultContainer; | ||||
|     }); | ||||
|     // func... | ||||
|     const getCurrentActiveLink = (offsetTop = 0, bounds = 5) => { | ||||
|     const getCurrentAnchor = (offsetTop = 0, bounds = 5) => { | ||||
|       const { getCurrentAnchor } = props; | ||||
| 
 | ||||
|       if (typeof getCurrentAnchor === 'function') { | ||||
|  | @ -140,9 +127,8 @@ export default defineComponent({ | |||
|       return ''; | ||||
|     }; | ||||
|     const setCurrentActiveLink = (link: string) => { | ||||
|       const { activeLink } = state; | ||||
|       if (activeLink !== link) { | ||||
|         state.activeLink = link; | ||||
|       if (activeLink.value !== link) { | ||||
|         activeLink.value = link; | ||||
|         emit('change', link); | ||||
|       } | ||||
|     }; | ||||
|  | @ -178,7 +164,7 @@ export default defineComponent({ | |||
|         return; | ||||
|       } | ||||
|       const { offsetTop, bounds, targetOffset } = props; | ||||
|       const currentActiveLink = getCurrentActiveLink( | ||||
|       const currentActiveLink = getCurrentAnchor( | ||||
|         targetOffset !== undefined ? targetOffset : offsetTop || 0, | ||||
|         bounds, | ||||
|       ); | ||||
|  | @ -196,8 +182,7 @@ export default defineComponent({ | |||
|       } | ||||
|     }; | ||||
| 
 | ||||
|     // provide data | ||||
|     provide('antAnchor', { | ||||
|     useProvideAnchor({ | ||||
|       registerLink: (link: string) => { | ||||
|         if (!state.links.includes(link)) { | ||||
|           state.links.push(link); | ||||
|  | @ -209,10 +194,12 @@ export default defineComponent({ | |||
|           state.links.splice(index, 1); | ||||
|         } | ||||
|       }, | ||||
|       $data: state, | ||||
|       activeLink, | ||||
|       scrollTo: handleScrollTo, | ||||
|     } as AntAnchor); | ||||
|     provide('antAnchorContext', instance); | ||||
|       handleClick: (e, info) => { | ||||
|         emit('click', e, info); | ||||
|       }, | ||||
|     }); | ||||
| 
 | ||||
|     onMounted(() => { | ||||
|       nextTick(() => { | ||||
|  | @ -244,7 +231,7 @@ export default defineComponent({ | |||
|       const { offsetTop, affix, showInkInFixed } = props; | ||||
|       const pre = prefixCls.value; | ||||
|       const inkClass = classNames(`${pre}-ink-ball`, { | ||||
|         visible: state.activeLink, | ||||
|         visible: activeLink.value, | ||||
|       }); | ||||
| 
 | ||||
|       const wrapperClass = classNames(props.wrapperClass, `${pre}-wrapper`, { | ||||
|  |  | |||
|  | @ -1,8 +1,6 @@ | |||
| import { | ||||
|   ComponentInternalInstance, | ||||
|   defineComponent, | ||||
|   ExtractPropTypes, | ||||
|   inject, | ||||
|   nextTick, | ||||
|   onBeforeUnmount, | ||||
|   onMounted, | ||||
|  | @ -11,8 +9,8 @@ import { | |||
| import PropTypes from '../_util/vue-types'; | ||||
| import { getPropsSlot } from '../_util/props-util'; | ||||
| import classNames from '../_util/classNames'; | ||||
| import { AntAnchor } from './Anchor'; | ||||
| import useConfigInject from '../_util/hooks/useConfigInject'; | ||||
| import { useInjectAnchor } from './context'; | ||||
| 
 | ||||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
| function noop(..._any: any[]): any {} | ||||
|  | @ -30,22 +28,19 @@ export default defineComponent({ | |||
|   name: 'AAnchorLink', | ||||
|   props: anchorLinkProps, | ||||
|   setup(props, { slots }) { | ||||
|     const antAnchor = inject('antAnchor', { | ||||
|       registerLink: noop, | ||||
|       unregisterLink: noop, | ||||
|       scrollTo: noop, | ||||
|       $data: {}, | ||||
|     } as AntAnchor); | ||||
|     const antAnchorContext = inject('antAnchorContext', {}) as ComponentInternalInstance; | ||||
|     const { | ||||
|       handleClick: contextHandleClick, | ||||
|       scrollTo, | ||||
|       unregisterLink, | ||||
|       registerLink, | ||||
|       activeLink, | ||||
|     } = useInjectAnchor(); | ||||
|     const { prefixCls } = useConfigInject('anchor', props); | ||||
| 
 | ||||
|     const handleClick = (e: Event) => { | ||||
|       // antAnchor.scrollTo(props.href); | ||||
|       const { scrollTo } = antAnchor; | ||||
|       const { href, title } = props; | ||||
|       if (antAnchorContext.emit) { | ||||
|         antAnchorContext.emit('click', e, { title, href }); | ||||
|       } | ||||
|       contextHandleClick(e, { title, href }); | ||||
|       scrollTo(href); | ||||
|     }; | ||||
| 
 | ||||
|  | @ -53,25 +48,25 @@ export default defineComponent({ | |||
|       () => props.href, | ||||
|       (val, oldVal) => { | ||||
|         nextTick(() => { | ||||
|           antAnchor.unregisterLink(oldVal); | ||||
|           antAnchor.registerLink(val); | ||||
|           unregisterLink(oldVal); | ||||
|           registerLink(val); | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     onMounted(() => { | ||||
|       antAnchor.registerLink(props.href); | ||||
|       registerLink(props.href); | ||||
|     }); | ||||
| 
 | ||||
|     onBeforeUnmount(() => { | ||||
|       antAnchor.unregisterLink(props.href); | ||||
|       unregisterLink(props.href); | ||||
|     }); | ||||
| 
 | ||||
|     return () => { | ||||
|       const { href, target } = props; | ||||
|       const pre = prefixCls.value; | ||||
|       const title = getPropsSlot(slots, props, 'title'); | ||||
|       const active = antAnchor.$data.activeLink === href; | ||||
|       const active = activeLink.value === href; | ||||
|       const wrapperClassName = classNames(`${pre}-link`, { | ||||
|         [`${pre}-link-active`]: active, | ||||
|       }); | ||||
|  |  | |||
|  | @ -0,0 +1,31 @@ | |||
| import { computed, Ref, inject, InjectionKey, provide } from 'vue'; | ||||
| 
 | ||||
| export interface AnchorContext { | ||||
|   registerLink: (link: string) => void; | ||||
|   unregisterLink: (link: string) => void; | ||||
|   activeLink: Ref<string>; | ||||
|   scrollTo: (link: string) => void; | ||||
|   handleClick: (e: Event, info: { title: any; href: string }) => void; | ||||
| } | ||||
| 
 | ||||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | ||||
| function noop(..._any: any[]): any {} | ||||
| 
 | ||||
| export const AnchorContextKey: InjectionKey<AnchorContext> = Symbol('anchorContextKey'); | ||||
| 
 | ||||
| const useProvideAnchor = (state: AnchorContext) => { | ||||
|   provide(AnchorContextKey, state); | ||||
| }; | ||||
| 
 | ||||
| const useInjectAnchor = () => { | ||||
|   return inject(AnchorContextKey, { | ||||
|     registerLink: noop, | ||||
|     unregisterLink: noop, | ||||
|     scrollTo: noop, | ||||
|     activeLink: computed(() => ''), | ||||
|     handleClick: noop, | ||||
|   } as AnchorContext); | ||||
| }; | ||||
| 
 | ||||
| export { useInjectAnchor, useProvideAnchor }; | ||||
| export default useProvideAnchor; | ||||
|  | @ -433,7 +433,11 @@ | |||
| 
 | ||||
| // Anchor | ||||
| // --- | ||||
| @anchor-bg: transparent; | ||||
| @anchor-border-color: @border-color-split; | ||||
| @anchor-link-top: 7px; | ||||
| @anchor-link-left: 16px; | ||||
| @anchor-link-padding: @anchor-link-top 0 @anchor-link-top @anchor-link-left; | ||||
| 
 | ||||
| // Tooltip | ||||
| // --- | ||||
|  |  | |||
							
								
								
									
										2
									
								
								v2-doc
								
								
								
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								v2-doc
								
								
								
								
							|  | @ -1 +1 @@ | |||
| Subproject commit a7013ae87f69dcbcf547f4b023255b8a7a775557 | ||||
| Subproject commit d197053285b81e77718621c0b5b94cb3b21831a2 | ||||
		Loading…
	
		Reference in New Issue
	
	 tangjinzhou
						tangjinzhou