diff --git a/src/field/index.js b/src/field/index.js index 418677aeb5d..d5ac2d1a063 100644 --- a/src/field/index.js +++ b/src/field/index.js @@ -2,7 +2,7 @@ import Icon from '../icon'; import Cell from '../cell'; import { cellProps } from '../cell/shared'; 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 { isIOS } from '../utils/validate/system'; @@ -139,7 +139,7 @@ export default createComponent({ // https://developers.weixin.qq.com/community/develop/doc/00044ae90742f8c82fb78fcae56800 /* istanbul ignore next */ if (isIOS()) { - window.scrollTo(0, getRootScrollTop()); + setRootScrollTop(getRootScrollTop()); } }, diff --git a/src/index-bar/index.js b/src/index-bar/index.js index a6be6c7a662..891f2c30b73 100644 --- a/src/index-bar/index.js +++ b/src/index-bar/index.js @@ -7,6 +7,7 @@ import { getScrollTop, getElementTop, getRootScrollTop, + setRootScrollTop, getScrollEventTarget } from '../utils/dom/scroll'; @@ -77,9 +78,13 @@ export default createComponent({ methods: { onScroll() { - const scrollTop = this.scroller === window - ? getScrollTop(this.scroller) - : 0; + let scrollTop; + if (this.scroller === window || this.scroller === document.body) { + scrollTop = getScrollTop(this.scroller); + } else { + // see: https://github.com/youzan/vant/issues/3774 + scrollTop = 0; + } const rects = this.children.map(item => ({ height: item.height, top: getElementTop(item.$el) @@ -154,7 +159,7 @@ export default createComponent({ match[0].scrollIntoView(); if (this.stickyOffsetTop) { - window.scrollTo(0, getRootScrollTop() - this.stickyOffsetTop); + setRootScrollTop(getRootScrollTop() - this.stickyOffsetTop); } this.$emit('select', match[0].index); diff --git a/src/list/demo/index.vue b/src/list/demo/index.vue index b89ba7b54da..a7fd5482f32 100644 --- a/src/list/demo/index.vue +++ b/src/list/demo/index.vue @@ -79,9 +79,14 @@ export default { }, methods: { - onLoad(index) { + onLoad(index, isRefresh) { const list = this.list[index]; + list.loading = true; setTimeout(() => { + if (isRefresh) { + list.items = []; + } + for (let i = 0; i < 10; i++) { const text = list.items.length + 1; list.items.push(text < 10 ? '0' + text : text); @@ -104,11 +109,10 @@ export default { onRefresh(index) { const list = this.list[index]; setTimeout(() => { - list.items = []; list.error = false; list.finished = false; list.refreshing = false; - window.scrollTo(0, 10); + this.onLoad(index, true); }, 1000); } } diff --git a/src/stepper/index.js b/src/stepper/index.js index 883e161e32d..5c6224d9d06 100644 --- a/src/stepper/index.js +++ b/src/stepper/index.js @@ -1,5 +1,5 @@ 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'; const [createComponent, bem] = createNamespace('stepper'); @@ -160,7 +160,7 @@ export default createComponent({ // https://developers.weixin.qq.com/community/develop/doc/00044ae90742f8c82fb78fcae56800 /* istanbul ignore next */ if (isIOS()) { - window.scrollTo(0, getRootScrollTop()); + setRootScrollTop(getRootScrollTop()); } }, diff --git a/src/tabs/index.js b/src/tabs/index.js index c920520f09e..9f66ad43355 100644 --- a/src/tabs/index.js +++ b/src/tabs/index.js @@ -4,7 +4,7 @@ import { on, off } from '../utils/dom/event'; import { ParentMixin } from '../mixins/relation'; import { BindEventMixin } from '../mixins/bind-event'; import { - setScrollTop, + setRootScrollTop, getScrollTop, getElementTop, getScrollEventTarget @@ -145,7 +145,7 @@ export default createComponent({ // scroll to correct position 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 onScroll() { - const scrollTop = getScrollTop(window) + this.offsetTop; + const scrollTop = getScrollTop(this.scrollEl) + this.offsetTop; const elTopToPageTop = getElementTop(this.$el); const elBottomToPageTop = elTopToPageTop + this.$el.offsetHeight - this.$refs.wrap.offsetHeight; diff --git a/src/utils/dom/scroll.ts b/src/utils/dom/scroll.ts index 57914006961..ea47358e843 100644 --- a/src/utils/dom/scroll.ts +++ b/src/utils/dom/scroll.ts @@ -3,18 +3,26 @@ type ScrollElement = HTMLElement | Window; // get nearest scroll element // http://w3help.org/zh-cn/causes/SD9013 // 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) { let node = element; while ( node && node.tagName !== 'HTML' && - node.tagName !== 'BODY' && node.nodeType === 1 && node !== rootParent ) { const { overflowY } = window.getComputedStyle(node); - if (overflowY === 'scroll' || overflowY === 'auto') { - return node; + if (overflowScrollReg.test(overflowY)) { + if (node.tagName !== 'BODY') { + return node; + } + + // see: https://github.com/youzan/vant/issues/3823 + const { overflowY: htmlOverflowY } = window.getComputedStyle(node.parentNode); + if (overflowScrollReg.test(htmlOverflowY)) { + return node; + } } node = node.parentNode; } @@ -33,11 +41,16 @@ export function getRootScrollTop(): number { 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 export function getElementTop(element: ScrollElement) { return ( (element === window ? 0 : (element).getBoundingClientRect().top) + - getScrollTop(window) + getRootScrollTop() ); }