refactor: anchor

This commit is contained in:
tangjinzhou 2021-05-24 22:54:07 +08:00
parent fbe3a48ac2
commit a6e30c2ded
5 changed files with 64 additions and 47 deletions

View File

@ -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`, {

View File

@ -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,
});

View File

@ -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;

View File

@ -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

@ -1 +1 @@
Subproject commit a7013ae87f69dcbcf547f4b023255b8a7a775557
Subproject commit d197053285b81e77718621c0b5b94cb3b21831a2