Skip to content

Commit 0c91121

Browse files
authored
Revert "feat(anchor): support --level vars and custom highlighted anchor points (#3430)" (#3494)
This reverts commit 67edf99.
1 parent 2bfc161 commit 0c91121

File tree

13 files changed

+155
-417
lines changed

13 files changed

+155
-417
lines changed

src/anchor/_example/base.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
<t-anchor-item href="#指定容器锚点" title="指定容器锚点" />
88
<t-anchor-item href="#特定交互锚点" title="特定交互锚点" />
99
<t-anchor-item href="#不同尺寸的锚点" title="不同尺寸的锚点" />
10-
<t-anchor-item href="#自定义锚点高亮" title="自定义锚点高亮" />
1110
</t-anchor>
1211
</div>
1312
</template>

src/anchor/_example/customize-highlight.vue

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/anchor/anchor-item-props.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
/**
44
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
5+
* updated at 2021-12-12 19:17:30
56
* */
67

78
import { TdAnchorItemProps } from '../anchor/type';
@@ -19,13 +20,12 @@ export default {
1920
type: String as PropType<TdAnchorItemProps['target']>,
2021
default: '_self' as TdAnchorItemProps['target'],
2122
validator(val: TdAnchorItemProps['target']): boolean {
22-
if (!val) return true;
2323
return ['_self', '_blank', '_parent', '_top'].includes(val);
2424
},
2525
},
2626
/** 锚点文本 */
2727
title: {
2828
type: [String, Function] as PropType<TdAnchorItemProps['title']>,
29-
default: '' as TdAnchorItemProps['title'],
29+
default: '',
3030
},
3131
};

src/anchor/anchor-item.tsx

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { defineComponent, h, VNodeChild, onMounted, onUnmounted, inject, watch, cloneVNode, ref, nextTick } from 'vue';
1+
import { defineComponent, h, VNodeChild, onMounted, onUnmounted, inject, watch } from 'vue';
22
import { ANCHOR_SHARP_REGEXP } from './utils';
33
import props from './anchor-item-props';
44
import { usePrefixClass, useCommonClassName } from '../hooks/useConfig';
@@ -15,18 +15,16 @@ const localProps = {
1515
return ANCHOR_SHARP_REGEXP.test(v);
1616
},
1717
},
18-
_level: {
19-
type: Number,
20-
default: 1,
21-
},
2218
};
2319

2420
export default defineComponent({
2521
name: 'TAnchorItem',
22+
inject: {
23+
tAnchor: { default: undefined },
24+
},
2625
props: localProps,
2726
setup(props, { slots }) {
28-
const elRef = ref<HTMLElement>(null);
29-
const anchor = inject(AnchorInjectionKey);
27+
const anchor = inject(AnchorInjectionKey, undefined);
3028
const CLASSNAME_PREFIX = usePrefixClass('anchor__item');
3129
const { STATUS } = useCommonClassName();
3230
const register = () => {
@@ -39,6 +37,7 @@ export default defineComponent({
3937
};
4038
const handleClick = (e: MouseEvent) => {
4139
const { href, title } = props;
40+
anchor.handleScrollTo(href);
4241
anchor.handleLinkClick({ href, title: isString(title) ? title : undefined, e });
4342
};
4443
const renderTitle = () => {
@@ -62,10 +61,8 @@ export default defineComponent({
6261
},
6362
{ immediate: true },
6463
);
65-
onMounted(async () => {
64+
onMounted(() => {
6665
register();
67-
await nextTick();
68-
elRef.value.style.setProperty('--level', `${props._level}`);
6966
});
7067
onUnmounted(() => {
7168
unregister();
@@ -84,19 +81,12 @@ export default defineComponent({
8481
[`${CLASSNAME_PREFIX.value}-link`]: true,
8582
};
8683
return (
87-
<>
88-
<div class={wrapperClass} ref={elRef}>
89-
<a href={href} title={titleAttr} class={titleClass} target={target} onClick={handleClick}>
90-
{titleSlot ? titleSlot(null) : title}
91-
</a>
92-
</div>
93-
{children &&
94-
children(null).map((child) =>
95-
cloneVNode(child, {
96-
_level: props._level + 1,
97-
}),
98-
)}
99-
</>
84+
<div class={wrapperClass}>
85+
<a href={href} title={titleAttr} class={titleClass} target={target} onClick={handleClick}>
86+
{titleSlot ? titleSlot(null) : title}
87+
</a>
88+
{children && children(null)}
89+
</div>
10090
);
10191
};
10292
},

src/anchor/anchor-target-props.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
/**
44
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
5+
* updated at 2021-12-12 19:17:30
56
* */
67

78
export default {

src/anchor/anchor.en-US.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
:: BASE_DOC ::
22

33
## API
4+
45
### Anchor Props
56

67
name | type | default | description | required
78
-- | -- | -- | -- | --
89
affixProps | Object | - | Typescript:`AffixProps`[Affix API Documents](./affix?tab=api)[see more ts definition](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/anchor/type.ts) | N
910
bounds | Number | 5 | \- | N
10-
container | String / Function | () => (() => window) | Typescript:`ScrollContainer`[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
11+
container | String / Function | () => (() => window) | Typescript:`ScrollContainer` | N
1112
cursor | Slot / Function | - | Typescript:`TNode`[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
12-
getCurrentAnchor | Function | - | Custom Highlighted Anchor Points。Typescript:`(activeLink: string) => string` | N
13-
size | String | medium | options: small/medium/large。Typescript:`SizeEnum`[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
13+
size | String | medium | options:small/medium/large。Typescript:`SizeEnum`[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
1414
targetOffset | Number | 0 | \- | N
1515
onChange | Function | | Typescript:`(currentLink: string, prevLink: string) => void`<br/> | N
1616
onClick | Function | | Typescript:`(link: { href: string; title: string; e: MouseEvent }) => void`<br/> | N
@@ -27,7 +27,7 @@ click | `(link: { href: string; title: string; e: MouseEvent })` | \-
2727
name | type | default | description | required
2828
-- | -- | -- | -- | --
2929
href | String | - | required | Y
30-
target | String | _self | options: _self/_blank/_parent/_top | N
30+
target | String | _self | options_self/_blank/_parent/_top | N
3131
title | String / Slot / Function | '' | Typescript:`string \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
3232

3333
### AnchorTarget Props

src/anchor/anchor.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
-- | -- | -- | -- | --
88
affixProps | Object | - | 透传 Affix 组件属性,即让 Anchor 组件支持所有 Affix 组件特性。TS 类型:`AffixProps`[Affix API Documents](./affix?tab=api)[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/anchor/type.ts) | N
99
bounds | Number | 5 | 锚点区域边界 | N
10-
container | String / Function | () => (() => window) | 指定滚动的容器。数据类型为 String 时,会被当作选择器处理,进行节点查询。示例:'body' 或 () => document.body。TS 类型:`ScrollContainer`[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
10+
container | String / Function | () => (() => window) | 指定滚动的容器。数据类型为 String 时,会被当作选择器处理,进行节点查询。示例:'body' 或 () => document.body。TS 类型:`ScrollContainer` | N
1111
cursor | Slot / Function | - | 用于自定义选中项左侧游标。TS 类型:`TNode`[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
12-
getCurrentAnchor | Function | - | 自定义高亮的锚点 。TS 类型:`(activeLink: string) => string` | N
1312
size | String | medium | 组件尺寸,small(120px),medium(200px),large(320px)。可选项:small/medium/large。TS 类型:`SizeEnum`[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
1413
targetOffset | Number | 0 | 锚点滚动偏移量 | N
1514
onChange | Function | | TS 类型:`(currentLink: string, prevLink: string) => void`<br/>锚点改变时触发 | N

src/anchor/anchor.tsx

Lines changed: 35 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import {
66
reactive,
77
onMounted,
88
onUnmounted,
9+
watchEffect,
910
provide,
10-
watch,
1111
} from 'vue';
1212
import { ANCHOR_SHARP_REGEXP, ANCHOR_CONTAINER, getOffsetTop } from './utils';
1313
import { isServer, on, off, getScroll, scrollTo, getScrollContainer as utilsGetScrollContainer } from '../utils/dom';
@@ -18,7 +18,6 @@ import Affix from '../affix';
1818
import { TdAnchorProps } from './type';
1919
import { usePrefixClass, useCommonClassName } from '../hooks/useConfig';
2020
import { AnchorInjectionKey } from './constants';
21-
import { isFunction } from 'lodash';
2221

2322
export interface Anchor extends ComponentPublicInstance {
2423
scrollContainer: ANCHOR_CONTAINER;
@@ -34,7 +33,7 @@ export default defineComponent({
3433
const anchorRef = ref<HTMLElement | null>(null);
3534
const links = ref<string[]>([]);
3635
const active = ref('');
37-
const scrollContainer = ref<ANCHOR_CONTAINER>(window);
36+
const scrollContainer = ref<ANCHOR_CONTAINER>(null);
3837
const handleScrollLock = ref<boolean>(false);
3938
const activeLineStyle = reactive({});
4039
const COMPONENT_NAME = usePrefixClass('anchor');
@@ -63,7 +62,7 @@ export default defineComponent({
6362
if (handleScrollLock.value) return;
6463
const { bounds, targetOffset } = props;
6564
const filters: { top: number; link: string }[] = [];
66-
let newActive = '';
65+
let active = '';
6766
// 找出所有当前top小于预设值
6867
links.value.forEach((link) => {
6968
const anchor = getAnchorTarget(link);
@@ -81,14 +80,9 @@ export default defineComponent({
8180
// 找出小于预设值集合中top最大的
8281
if (filters.length) {
8382
const latest = filters.reduce((prev, cur) => (prev.top > cur.top ? prev : cur));
84-
newActive = latest.link;
85-
}
86-
87-
if (active.value !== newActive) {
88-
const newHref = isFunction(props?.getCurrentAnchor) ? props?.getCurrentAnchor(newActive) : newActive;
89-
props?.onChange?.(newHref, active.value);
90-
active.value = newHref;
83+
active = latest.link;
9184
}
85+
setCurrentActiveLink(active);
9286
};
9387
/**
9488
* 获取锚点对应的target元素
@@ -125,7 +119,20 @@ export default defineComponent({
125119
const unregisterLink = (link: string) => {
126120
links.value = links.value.filter((each) => each !== link);
127121
};
128-
122+
/**
123+
* 设置当前激活状态锚点
124+
*
125+
* @param {string} link
126+
*/
127+
const setCurrentActiveLink = async (link: string): Promise<void> => {
128+
if (active.value === link) {
129+
return;
130+
}
131+
active.value = link;
132+
props.onChange?.(link, active.value);
133+
await nextTick();
134+
updateActiveLine();
135+
};
129136
/**
130137
* 计算active-line所在的位置
131138
* 当前active-item的top + height, 以及ANCHOR_ITEM_PADDING修正
@@ -148,19 +155,16 @@ export default defineComponent({
148155
* @param {{ href: string; title: string }} link
149156
*/
150157
const handleLinkClick = (link: { href: string; title: string; e: MouseEvent }) => {
151-
props?.onClick?.(link);
152-
const newHref = isFunction(props?.getCurrentAnchor) ? props?.getCurrentAnchor(link.href) : link.href;
153-
handleScrollTo(newHref);
158+
props.onClick?.(link);
154159
};
155160
/**
156161
* 滚动到指定锚点
157162
*
158-
* @param {string} href
163+
* @param {string} link
159164
*/
160-
const handleScrollTo = async (href: string): Promise<void> => {
161-
const anchor = getAnchorTarget(href);
162-
props?.onChange?.(href, active.value);
163-
active.value = href;
165+
const handleScrollTo = async (link: string): Promise<void> => {
166+
const anchor = getAnchorTarget(link);
167+
setCurrentActiveLink(link);
164168
if (!anchor) return;
165169
handleScrollLock.value = true;
166170
const { targetOffset } = props;
@@ -176,62 +180,34 @@ export default defineComponent({
176180
const titleContent: SlotReturnValue = renderTNodeJSX('cursor');
177181
return titleContent || <div class={ANCHOR_LINE_CURSOR_CLASSNAME.value}></div>;
178182
};
179-
180-
const getNewHref = (newHref: string = active.value) => {
181-
if (props.getCurrentAnchor) {
182-
newHref = props.getCurrentAnchor(newHref);
183-
} else {
184-
newHref = decodeURIComponent(window?.location.hash);
185-
}
186-
return newHref;
187-
};
188-
189183
onMounted(async () => {
190184
getScrollContainer();
191-
// 初始化
192-
const newHref = getNewHref();
193-
await nextTick();
194-
handleScrollTo(newHref);
185+
if (active.value) {
186+
await nextTick();
187+
handleScrollTo(active.value);
188+
}
195189
});
196-
197190
onUnmounted(() => {
198191
if (!scrollContainer.value) return;
199192
off(scrollContainer.value, 'scroll', handleScroll);
200193
});
201-
202-
watch(active, async () => {
203-
await nextTick();
204-
updateActiveLine();
194+
watchEffect(() => {
195+
// 清空上一个container的事件监听
196+
if (scrollContainer.value) {
197+
off(scrollContainer.value, 'scroll', handleScroll);
198+
}
199+
getScrollContainer();
205200
});
206-
207-
watch(
208-
() => props.container,
209-
() => {
210-
if (scrollContainer.value) {
211-
off(scrollContainer.value, 'scroll', handleScroll);
212-
}
213-
getScrollContainer();
214-
},
215-
);
216-
217-
watch(
218-
() => props.getCurrentAnchor,
219-
() => {
220-
const newHref = getNewHref();
221-
handleScrollTo(newHref);
222-
},
223-
);
224-
225201
provide(
226202
AnchorInjectionKey,
227203
reactive({
228204
registerLink,
229205
unregisterLink,
206+
handleScrollTo,
230207
handleLinkClick,
231208
active,
232209
}),
233210
);
234-
235211
return () => {
236212
const { size, affixProps } = props;
237213
const className = [COMPONENT_NAME.value, SIZE.value[size]];

src/anchor/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { InjectionKey } from 'vue';
33
export const AnchorInjectionKey: InjectionKey<{
44
registerLink: (link: string) => void;
55
unregisterLink: (link: string) => void;
6+
handleScrollTo: (link: string) => void;
67
handleLinkClick: (link: { href: string; title: string; e: MouseEvent }) => void;
78
active: string;
89
}> = Symbol('AnchorInjectionProvide');

src/anchor/props.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
/**
44
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
5+
* updated at 2021-12-12 19:17:30
56
* */
67

78
import { TdAnchorProps } from './type';
@@ -20,22 +21,17 @@ export default {
2021
/** 指定滚动的容器。数据类型为 String 时,会被当作选择器处理,进行节点查询。示例:'body' 或 () => document.body */
2122
container: {
2223
type: [String, Function] as PropType<TdAnchorProps['container']>,
23-
default: () => (() => window) as TdAnchorProps['container'],
24+
default: () => () => window,
2425
},
2526
/** 用于自定义选中项左侧游标 */
2627
cursor: {
2728
type: Function as PropType<TdAnchorProps['cursor']>,
2829
},
29-
/** 自定义高亮的锚点 */
30-
getCurrentAnchor: {
31-
type: Function as PropType<TdAnchorProps['getCurrentAnchor']>,
32-
},
3330
/** 组件尺寸,small(120px),medium(200px),large(320px) */
3431
size: {
3532
type: String as PropType<TdAnchorProps['size']>,
3633
default: 'medium' as TdAnchorProps['size'],
3734
validator(val: TdAnchorProps['size']): boolean {
38-
if (!val) return true;
3935
return ['small', 'medium', 'large'].includes(val);
4036
},
4137
},

0 commit comments

Comments
 (0)