fix(IndexBar): incorrect behavior inside popup (#7559)

This commit is contained in:
neverland 2020-11-15 10:43:12 +08:00 committed by GitHub
parent 97f2028e4e
commit d78438a899
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 32 deletions

View File

@ -1,6 +1,7 @@
import { createNamespace } from '../utils'; import { createNamespace } from '../utils';
import { ChildrenMixin } from '../mixins/relation'; import { ChildrenMixin } from '../mixins/relation';
import { BORDER_BOTTOM } from '../utils/constant'; import { BORDER_BOTTOM } from '../utils/constant';
import { getScrollTop, getRootScrollTop } from '../utils/dom/scroll';
const [createComponent, bem] = createNamespace('index-anchor'); const [createComponent, bem] = createNamespace('index-anchor');
@ -15,6 +16,7 @@ export default createComponent({
return { return {
top: 0, top: 0,
left: null, left: null,
rect: { top: 0, height: 0 },
width: null, width: null,
active: false, active: false,
}; };
@ -39,20 +41,35 @@ export default createComponent({
}, },
mounted() { mounted() {
this.height = this.$el.offsetHeight; const rect = this.$el.getBoundingClientRect();
this.rect.height = rect.height;
}, },
methods: { methods: {
scrollIntoView() { scrollIntoView() {
this.$el.scrollIntoView(); this.$el.scrollIntoView();
}, },
getRect(scroller, scrollerRect) {
const el = this.$el;
const elRect = el.getBoundingClientRect();
this.rect.height = elRect.height;
if (scroller === window || scroller === document.body) {
this.rect.top = elRect.top + getRootScrollTop();
} else {
this.rect.top = elRect.top + getScrollTop(scroller) - scrollerRect.top;
}
return this.rect;
},
}, },
render() { render() {
const { sticky } = this; const { sticky } = this;
return ( return (
<div style={{ height: sticky ? `${this.height}px` : null }}> <div style={{ height: sticky ? `${this.rect.height}px` : null }}>
<div <div
style={this.anchorStyle} style={this.anchorStyle}
class={[bem({ sticky }), { [BORDER_BOTTOM]: sticky }]} class={[bem({ sticky }), { [BORDER_BOTTOM]: sticky }]}

View File

@ -5,7 +5,6 @@ import { preventDefault } from '../utils/dom/event';
import { import {
getScroller, getScroller,
getScrollTop, getScrollTop,
getElementTop,
getRootScrollTop, getRootScrollTop,
setRootScrollTop, setRootScrollTop,
} from '../utils/dom/scroll'; } from '../utils/dom/scroll';
@ -103,10 +102,9 @@ export default createComponent({
const scrollTop = getScrollTop(this.scroller); const scrollTop = getScrollTop(this.scroller);
const scrollerRect = this.getScrollerRect(); const scrollerRect = this.getScrollerRect();
const rects = this.children.map((item) => ({ const rects = this.children.map((item) =>
height: item.height, item.getRect(this.scroller, scrollerRect)
top: this.getElementTop(item.$el, scrollerRect), );
}));
const active = this.getActiveAnchorIndex(scrollTop, rects); const active = this.getActiveAnchorIndex(scrollTop, rects);
@ -131,7 +129,7 @@ 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;
item.active = activeItemTop > 0; item.active = activeItemTop > 0;
item.top = activeItemTop + scrollerRect.top - item.height; item.top = activeItemTop + scrollerRect.top - rects[index].height;
} else { } else {
item.active = false; item.active = false;
} }
@ -150,18 +148,6 @@ export default createComponent({
}; };
}, },
getElementTop(ele, scrollerRect) {
const { scroller } = this;
if (scroller === window || scroller === document.body) {
return getElementTop(ele);
}
const eleRect = ele.getBoundingClientRect();
return eleRect.top - scrollerRect.top + getScrollTop(scroller);
},
getActiveAnchorIndex(scrollTop, rects) { getActiveAnchorIndex(scrollTop, rects) {
for (let i = this.children.length - 1; i >= 0; i--) { for (let i = this.children.length - 1; i >= 0; i--) {
const prevHeight = i > 0 ? rects[i - 1].height : 0; const prevHeight = i > 0 ? rects[i - 1].height : 0;

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({