Merge branch '2.x' into dev

This commit is contained in:
chenjiahan 2020-11-15 11:16:02 +08:00
commit 6c6ea01599
7 changed files with 46 additions and 48 deletions

View File

@ -165,10 +165,10 @@ export default {
### DropdownItem Slots ### DropdownItem Slots
| 名称 | 说明 | | 名称 | 说明 |
| ------- | -------------------------- | | ------- | ---------------- |
| default | 菜单内容 | | default | 菜单内容 |
| title | 自定义标题,不支持动态渲染 | | title | 自定义菜单项标题 |
### DropdownItem 方法 ### DropdownItem 方法

View File

@ -1,12 +1,13 @@
import { reactive, ref, computed } from 'vue'; import { ref, reactive, computed, onMounted } from 'vue';
// Utils // Utils
import { createNamespace } from '../utils'; import { createNamespace } from '../utils';
import { BORDER_BOTTOM } from '../utils/constant'; import { BORDER_BOTTOM } from '../utils/constant';
import { INDEX_BAR_KEY } from '../index-bar'; import { INDEX_BAR_KEY } from '../index-bar';
import { getScrollTop, getRootScrollTop } from '../utils/dom/scroll';
// Composition // Composition
import { useParent } from '@vant/use'; import { useRect, useParent } from '@vant/use';
import { useHeight } from '../composition/use-height'; import { useHeight } from '../composition/use-height';
import { useExpose } from '../composition/use-expose'; import { useExpose } from '../composition/use-expose';
@ -21,12 +22,12 @@ export default createComponent({
const state = reactive({ const state = reactive({
top: 0, top: 0,
left: null, left: null,
rect: { top: 0, height: 0 },
width: null, width: null,
active: false, active: false,
}); });
const root = ref(); const root = ref();
const height = useHeight(root);
const { parent } = useParent(INDEX_BAR_KEY); const { parent } = useParent(INDEX_BAR_KEY);
const isSticky = () => state.active && parent.props.sticky; 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({ useExpose({
state, state,
height, getRect,
}); });
return () => { return () => {
const sticky = isSticky(); const sticky = isSticky();
return ( return (
<div ref={root} style={{ height: sticky ? `${height.value}px` : null }}> <div
ref={root}
style={{ height: sticky ? `${state.rect.height}px` : null }}
>
<div <div
style={anchorStyle.value} style={anchorStyle.value}
class={[bem({ sticky }), { [BORDER_BOTTOM]: sticky }]} class={[bem({ sticky }), { [BORDER_BOTTOM]: sticky }]}

View File

@ -5,7 +5,6 @@ import {
isDef, isDef,
isHidden, isHidden,
getScrollTop, getScrollTop,
getElementTop,
preventDefault, preventDefault,
createNamespace, createNamespace,
getRootScrollTop, getRootScrollTop,
@ -92,18 +91,6 @@ export default createComponent({
}; };
}; };
const getAnchorTop = (element, scrollParentRect) => {
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) => { const getActiveAnchor = (scrollTop, rects) => {
for (let i = children.length - 1; i >= 0; i--) { for (let i = children.length - 1; i >= 0; i--) {
const prevHeight = i > 0 ? rects[i - 1].height : 0; const prevHeight = i > 0 ? rects[i - 1].height : 0;
@ -126,10 +113,9 @@ export default createComponent({
const scrollTop = getScrollTop(scrollParent.value); const scrollTop = getScrollTop(scrollParent.value);
const scrollParentRect = getScrollerRect(); const scrollParentRect = getScrollerRect();
const rects = children.map((item) => ({ const rects = children.map((item) =>
height: item.height.value, item.getRect(scrollParent.value, scrollParentRect)
top: getAnchorTop(item.$el, scrollParentRect), );
}));
const active = getActiveAnchor(scrollTop, rects); const active = getActiveAnchor(scrollTop, rects);
@ -137,7 +123,7 @@ export default createComponent({
if (sticky) { if (sticky) {
children.forEach((item, index) => { children.forEach((item, index) => {
const { state, height, $el } = item; const { state, $el } = item;
if (index === active || index === active - 1) { if (index === active || index === active - 1) {
const rect = $el.getBoundingClientRect(); const rect = $el.getBoundingClientRect();
state.left = rect.left; state.left = rect.left;
@ -155,7 +141,8 @@ export default createComponent({
} else if (index === active - 1) { } else if (index === active - 1) {
const activeItemTop = rects[active].top - scrollTop; const activeItemTop = rects[active].top - scrollTop;
state.active = activeItemTop > 0; state.active = activeItemTop > 0;
state.top = activeItemTop + scrollParentRect.top - height.value; state.top =
activeItemTop + scrollParentRect.top - rects[index].height;
} else { } else {
state.active = false; state.active = false;
} }

View File

@ -1,13 +1,5 @@
import { mount, trigger, triggerDrag, mockScrollIntoView } from '../../../test'; 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', () => { test('should allow to custom anchor text', () => {
const wrapper = mount({ const wrapper = mount({
template: ` template: `
@ -97,11 +89,10 @@ test('should update active anchor after page scroll', () => {
const { index } = this.dataset; const { index } = this.dataset;
return { return {
top: index ? index * 10 : 0, top: index ? index * 10 : 0,
height: 10,
}; };
}; };
mockOffsetHeight(10);
const wrapper = mount({ const wrapper = mount({
template: ` template: `
<van-index-bar :sticky="sticky"> <van-index-bar :sticky="sticky">
@ -138,11 +129,10 @@ test('should emit change event when active index changed', () => {
const { index } = this.dataset; const { index } = this.dataset;
return { return {
top: index ? index * 10 : 0, top: index ? index * 10 : 0,
height: 10,
}; };
}; };
mockOffsetHeight(10);
const onChange = jest.fn(); const onChange = jest.fn();
mount({ mount({

View File

@ -6,6 +6,8 @@
&__avatar { &__avatar {
flex-shrink: 0; flex-shrink: 0;
width: @skeleton-avatar-size;
height: @skeleton-avatar-size;
margin-right: @padding-md; margin-right: @padding-md;
background-color: @skeleton-avatar-background-color; background-color: @skeleton-avatar-background-color;
@ -29,6 +31,7 @@
} }
&__title { &__title {
width: @skeleton-title-width;
margin: 0; margin: 0;
} }

View File

@ -10,6 +10,8 @@ export default createComponent({
title: Boolean, title: Boolean,
round: Boolean, round: Boolean,
avatar: Boolean, avatar: Boolean,
avatarSize: [Number, String],
titleWidth: [Number, String],
row: { row: {
type: [Number, String], type: [Number, String],
default: 0, default: 0,
@ -22,18 +24,10 @@ export default createComponent({
type: Boolean, type: Boolean,
default: true, default: true,
}, },
avatarSize: {
type: String,
default: '32px',
},
avatarShape: { avatarShape: {
type: String as PropType<'square' | 'round'>, type: String as PropType<'square' | 'round'>,
default: 'round', default: 'round',
}, },
titleWidth: {
type: [Number, String],
default: '40%',
},
rowWidth: { rowWidth: {
type: [Number, String, Array] as PropType< type: [Number, String, Array] as PropType<
number | string | (number | string)[] number | string | (number | string)[]

View File

@ -648,6 +648,8 @@
@skeleton-row-height: 16px; @skeleton-row-height: 16px;
@skeleton-row-background-color: @active-color; @skeleton-row-background-color: @active-color;
@skeleton-row-margin-top: @padding-sm; @skeleton-row-margin-top: @padding-sm;
@skeleton-title-width: 40%;
@skeleton-avatar-size: 32px;
@skeleton-avatar-background-color: @active-color; @skeleton-avatar-background-color: @active-color;
@skeleton-animation-duration: 1.2s; @skeleton-animation-duration: 1.2s;