diff --git a/src/dropdown-menu/README.zh-CN.md b/src/dropdown-menu/README.zh-CN.md index c346cdd57..c1dcbc259 100644 --- a/src/dropdown-menu/README.zh-CN.md +++ b/src/dropdown-menu/README.zh-CN.md @@ -165,10 +165,10 @@ export default { ### DropdownItem Slots -| 名称 | 说明 | -| ------- | -------------------------- | -| default | 菜单内容 | -| title | 自定义标题,不支持动态渲染 | +| 名称 | 说明 | +| ------- | ---------------- | +| default | 菜单内容 | +| title | 自定义菜单项标题 | ### DropdownItem 方法 diff --git a/src/index-anchor/index.js b/src/index-anchor/index.js index df74a9200..f55295412 100644 --- a/src/index-anchor/index.js +++ b/src/index-anchor/index.js @@ -1,12 +1,13 @@ -import { reactive, ref, computed } from 'vue'; +import { ref, reactive, computed, onMounted } from 'vue'; // Utils import { createNamespace } from '../utils'; import { BORDER_BOTTOM } from '../utils/constant'; import { INDEX_BAR_KEY } from '../index-bar'; +import { getScrollTop, getRootScrollTop } from '../utils/dom/scroll'; // Composition -import { useParent } from '@vant/use'; +import { useRect, useParent } from '@vant/use'; import { useHeight } from '../composition/use-height'; import { useExpose } from '../composition/use-expose'; @@ -21,12 +22,12 @@ export default createComponent({ const state = reactive({ top: 0, left: null, + rect: { top: 0, height: 0 }, width: null, active: false, }); const root = ref(); - const height = useHeight(root); const { parent } = useParent(INDEX_BAR_KEY); const isSticky = () => state.active && parent.props.sticky; @@ -45,16 +46,37 @@ export default createComponent({ } }); + const getRect = (scrollParent, scrollParentRect) => { + const rootRect = useRect(root); + state.rect.height = rootRect.height; + + if (scrollParent === window || scrollParent === document.body) { + state.rect.top = rootRect.top + getRootScrollTop(); + } else { + state.rect.top = + rootRect.top + getScrollTop(scrollParent) - scrollParentRect.top; + } + + return state.rect; + }; + + onMounted(() => { + state.rect.height = useHeight(root); + }); + useExpose({ state, - height, + getRect, }); return () => { const sticky = isSticky(); return ( -
+
{ - if ( - scrollParent.value === window || - scrollParent.value === document.body - ) { - return getElementTop(element); - } - - const rect = useRect(element); - return rect.top - scrollParentRect.top + getScrollTop(scrollParent); - }; - const getActiveAnchor = (scrollTop, rects) => { for (let i = children.length - 1; i >= 0; i--) { const prevHeight = i > 0 ? rects[i - 1].height : 0; @@ -126,10 +113,9 @@ export default createComponent({ const scrollTop = getScrollTop(scrollParent.value); const scrollParentRect = getScrollerRect(); - const rects = children.map((item) => ({ - height: item.height.value, - top: getAnchorTop(item.$el, scrollParentRect), - })); + const rects = children.map((item) => + item.getRect(scrollParent.value, scrollParentRect) + ); const active = getActiveAnchor(scrollTop, rects); @@ -137,7 +123,7 @@ export default createComponent({ if (sticky) { children.forEach((item, index) => { - const { state, height, $el } = item; + const { state, $el } = item; if (index === active || index === active - 1) { const rect = $el.getBoundingClientRect(); state.left = rect.left; @@ -155,7 +141,8 @@ export default createComponent({ } else if (index === active - 1) { const activeItemTop = rects[active].top - scrollTop; state.active = activeItemTop > 0; - state.top = activeItemTop + scrollParentRect.top - height.value; + state.top = + activeItemTop + scrollParentRect.top - rects[index].height; } else { state.active = false; } diff --git a/src/index-bar/test/index.legacy.js b/src/index-bar/test/index.legacy.js index 37a3a6c62..ac083cacd 100644 --- a/src/index-bar/test/index.legacy.js +++ b/src/index-bar/test/index.legacy.js @@ -1,13 +1,5 @@ import { mount, trigger, triggerDrag, mockScrollIntoView } from '../../../test'; -function mockOffsetHeight(offsetHeight) { - Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { - get() { - return offsetHeight; - }, - }); -} - test('should allow to custom anchor text', () => { const wrapper = mount({ template: ` @@ -97,11 +89,10 @@ test('should update active anchor after page scroll', () => { const { index } = this.dataset; return { top: index ? index * 10 : 0, + height: 10, }; }; - mockOffsetHeight(10); - const wrapper = mount({ template: ` @@ -138,11 +129,10 @@ test('should emit change event when active index changed', () => { const { index } = this.dataset; return { top: index ? index * 10 : 0, + height: 10, }; }; - mockOffsetHeight(10); - const onChange = jest.fn(); mount({ diff --git a/src/skeleton/index.less b/src/skeleton/index.less index 95ab87c47..38e56ff68 100644 --- a/src/skeleton/index.less +++ b/src/skeleton/index.less @@ -6,6 +6,8 @@ &__avatar { flex-shrink: 0; + width: @skeleton-avatar-size; + height: @skeleton-avatar-size; margin-right: @padding-md; background-color: @skeleton-avatar-background-color; @@ -29,6 +31,7 @@ } &__title { + width: @skeleton-title-width; margin: 0; } diff --git a/src/skeleton/index.tsx b/src/skeleton/index.tsx index a17e256ea..3b003445d 100644 --- a/src/skeleton/index.tsx +++ b/src/skeleton/index.tsx @@ -10,6 +10,8 @@ export default createComponent({ title: Boolean, round: Boolean, avatar: Boolean, + avatarSize: [Number, String], + titleWidth: [Number, String], row: { type: [Number, String], default: 0, @@ -22,18 +24,10 @@ export default createComponent({ type: Boolean, default: true, }, - avatarSize: { - type: String, - default: '32px', - }, avatarShape: { type: String as PropType<'square' | 'round'>, default: 'round', }, - titleWidth: { - type: [Number, String], - default: '40%', - }, rowWidth: { type: [Number, String, Array] as PropType< number | string | (number | string)[] diff --git a/src/style/var.less b/src/style/var.less index f65987954..78a34196e 100644 --- a/src/style/var.less +++ b/src/style/var.less @@ -648,6 +648,8 @@ @skeleton-row-height: 16px; @skeleton-row-background-color: @active-color; @skeleton-row-margin-top: @padding-sm; +@skeleton-title-width: 40%; +@skeleton-avatar-size: 32px; @skeleton-avatar-background-color: @active-color; @skeleton-animation-duration: 1.2s;