mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-05 05:29:01 +08:00
refactor: anchor
This commit is contained in:
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,
|
||||
});
|
||||
|
31
components/anchor/context.ts
Normal file
31
components/anchor/context.ts
Normal 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;
|
@ -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
Block a user