mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
Merge branch '2.x' into dev
This commit is contained in:
commit
6c6ea01599
@ -165,10 +165,10 @@ export default {
|
|||||||
|
|
||||||
### DropdownItem Slots
|
### DropdownItem Slots
|
||||||
|
|
||||||
| 名称 | 说明 |
|
| 名称 | 说明 |
|
||||||
| ------- | -------------------------- |
|
| ------- | ---------------- |
|
||||||
| default | 菜单内容 |
|
| default | 菜单内容 |
|
||||||
| title | 自定义标题,不支持动态渲染 |
|
| title | 自定义菜单项标题 |
|
||||||
|
|
||||||
### DropdownItem 方法
|
### DropdownItem 方法
|
||||||
|
|
||||||
|
@ -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 }]}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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({
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)[]
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user