[bugfix] compatible <body /> is the scene of the scrolling container (#3844)

This commit is contained in:
流采 2019-07-15 19:36:21 +08:00 committed by neverland
parent dbe56fd362
commit 511087bc74
6 changed files with 40 additions and 18 deletions

View File

@ -2,7 +2,7 @@ import Icon from '../icon';
import Cell from '../cell'; import Cell from '../cell';
import { cellProps } from '../cell/shared'; import { cellProps } from '../cell/shared';
import { preventDefault } from '../utils/dom/event'; import { preventDefault } from '../utils/dom/event';
import { getRootScrollTop } from '../utils/dom/scroll'; import { getRootScrollTop, setRootScrollTop } from '../utils/dom/scroll';
import { createNamespace, isObj, isDef, addUnit } from '../utils'; import { createNamespace, isObj, isDef, addUnit } from '../utils';
import { isIOS } from '../utils/validate/system'; import { isIOS } from '../utils/validate/system';
@ -139,7 +139,7 @@ export default createComponent({
// https://developers.weixin.qq.com/community/develop/doc/00044ae90742f8c82fb78fcae56800 // https://developers.weixin.qq.com/community/develop/doc/00044ae90742f8c82fb78fcae56800
/* istanbul ignore next */ /* istanbul ignore next */
if (isIOS()) { if (isIOS()) {
window.scrollTo(0, getRootScrollTop()); setRootScrollTop(getRootScrollTop());
} }
}, },

View File

@ -7,6 +7,7 @@ import {
getScrollTop, getScrollTop,
getElementTop, getElementTop,
getRootScrollTop, getRootScrollTop,
setRootScrollTop,
getScrollEventTarget getScrollEventTarget
} from '../utils/dom/scroll'; } from '../utils/dom/scroll';
@ -77,9 +78,13 @@ export default createComponent({
methods: { methods: {
onScroll() { onScroll() {
const scrollTop = this.scroller === window let scrollTop;
? getScrollTop(this.scroller) if (this.scroller === window || this.scroller === document.body) {
: 0; scrollTop = getScrollTop(this.scroller);
} else {
// see: https://github.com/youzan/vant/issues/3774
scrollTop = 0;
}
const rects = this.children.map(item => ({ const rects = this.children.map(item => ({
height: item.height, height: item.height,
top: getElementTop(item.$el) top: getElementTop(item.$el)
@ -154,7 +159,7 @@ export default createComponent({
match[0].scrollIntoView(); match[0].scrollIntoView();
if (this.stickyOffsetTop) { if (this.stickyOffsetTop) {
window.scrollTo(0, getRootScrollTop() - this.stickyOffsetTop); setRootScrollTop(getRootScrollTop() - this.stickyOffsetTop);
} }
this.$emit('select', match[0].index); this.$emit('select', match[0].index);

View File

@ -79,9 +79,14 @@ export default {
}, },
methods: { methods: {
onLoad(index) { onLoad(index, isRefresh) {
const list = this.list[index]; const list = this.list[index];
list.loading = true;
setTimeout(() => { setTimeout(() => {
if (isRefresh) {
list.items = [];
}
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
const text = list.items.length + 1; const text = list.items.length + 1;
list.items.push(text < 10 ? '0' + text : text); list.items.push(text < 10 ? '0' + text : text);
@ -104,11 +109,10 @@ export default {
onRefresh(index) { onRefresh(index) {
const list = this.list[index]; const list = this.list[index];
setTimeout(() => { setTimeout(() => {
list.items = [];
list.error = false; list.error = false;
list.finished = false; list.finished = false;
list.refreshing = false; list.refreshing = false;
window.scrollTo(0, 10); this.onLoad(index, true);
}, 1000); }, 1000);
} }
} }

View File

@ -1,5 +1,5 @@
import { createNamespace, isDef, addUnit } from '../utils'; import { createNamespace, isDef, addUnit } from '../utils';
import { getRootScrollTop } from '../utils/dom/scroll'; import { getRootScrollTop, setRootScrollTop } from '../utils/dom/scroll';
import { isIOS } from '../utils/validate/system'; import { isIOS } from '../utils/validate/system';
const [createComponent, bem] = createNamespace('stepper'); const [createComponent, bem] = createNamespace('stepper');
@ -160,7 +160,7 @@ export default createComponent({
// https://developers.weixin.qq.com/community/develop/doc/00044ae90742f8c82fb78fcae56800 // https://developers.weixin.qq.com/community/develop/doc/00044ae90742f8c82fb78fcae56800
/* istanbul ignore next */ /* istanbul ignore next */
if (isIOS()) { if (isIOS()) {
window.scrollTo(0, getRootScrollTop()); setRootScrollTop(getRootScrollTop());
} }
}, },

View File

@ -4,7 +4,7 @@ import { on, off } from '../utils/dom/event';
import { ParentMixin } from '../mixins/relation'; import { ParentMixin } from '../mixins/relation';
import { BindEventMixin } from '../mixins/bind-event'; import { BindEventMixin } from '../mixins/bind-event';
import { import {
setScrollTop, setRootScrollTop,
getScrollTop, getScrollTop,
getElementTop, getElementTop,
getScrollEventTarget getScrollEventTarget
@ -145,7 +145,7 @@ export default createComponent({
// scroll to correct position // scroll to correct position
if (this.position === 'top' || this.position === 'bottom') { if (this.position === 'top' || this.position === 'bottom') {
setScrollTop(window, getElementTop(this.$el) - this.offsetTop); setRootScrollTop(getElementTop(this.$el) - this.offsetTop);
} }
}, },
@ -184,7 +184,7 @@ export default createComponent({
// adjust tab position // adjust tab position
onScroll() { onScroll() {
const scrollTop = getScrollTop(window) + this.offsetTop; const scrollTop = getScrollTop(this.scrollEl) + this.offsetTop;
const elTopToPageTop = getElementTop(this.$el); const elTopToPageTop = getElementTop(this.$el);
const elBottomToPageTop = const elBottomToPageTop =
elTopToPageTop + this.$el.offsetHeight - this.$refs.wrap.offsetHeight; elTopToPageTop + this.$el.offsetHeight - this.$refs.wrap.offsetHeight;

View File

@ -3,19 +3,27 @@ type ScrollElement = HTMLElement | Window;
// get nearest scroll element // get nearest scroll element
// http://w3help.org/zh-cn/causes/SD9013 // http://w3help.org/zh-cn/causes/SD9013
// http://stackoverflow.com/questions/17016740/onscroll-function-is-not-working-for-chrome // http://stackoverflow.com/questions/17016740/onscroll-function-is-not-working-for-chrome
const overflowScrollReg = /scroll|auto/i;
export function getScrollEventTarget(element: HTMLElement, rootParent: ScrollElement = window) { export function getScrollEventTarget(element: HTMLElement, rootParent: ScrollElement = window) {
let node = element; let node = element;
while ( while (
node && node &&
node.tagName !== 'HTML' && node.tagName !== 'HTML' &&
node.tagName !== 'BODY' &&
node.nodeType === 1 && node.nodeType === 1 &&
node !== rootParent node !== rootParent
) { ) {
const { overflowY } = window.getComputedStyle(node); const { overflowY } = window.getComputedStyle(node);
if (overflowY === 'scroll' || overflowY === 'auto') { if (overflowScrollReg.test(<string>overflowY)) {
if (node.tagName !== 'BODY') {
return node; return node;
} }
// see: https://github.com/youzan/vant/issues/3823
const { overflowY: htmlOverflowY } = window.getComputedStyle(<Element>node.parentNode);
if (overflowScrollReg.test(<string>htmlOverflowY)) {
return node;
}
}
node = <HTMLElement>node.parentNode; node = <HTMLElement>node.parentNode;
} }
return rootParent; return rootParent;
@ -33,11 +41,16 @@ export function getRootScrollTop(): number {
return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
} }
export function setRootScrollTop(value: number) {
setScrollTop(window, value);
setScrollTop(document.body, value);
}
// get distance from element top to page top // get distance from element top to page top
export function getElementTop(element: ScrollElement) { export function getElementTop(element: ScrollElement) {
return ( return (
(element === window ? 0 : (<HTMLElement>element).getBoundingClientRect().top) + (element === window ? 0 : (<HTMLElement>element).getBoundingClientRect().top) +
getScrollTop(window) getRootScrollTop()
); );
} }