From 511087bc74220a6f4711bddb6dacbedba40eebc7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=B5=81=E9=87=87?=
Date: Mon, 15 Jul 2019 19:36:21 +0800
Subject: [PATCH] [bugfix] compatible `` is the scene of the scrolling
container (#3844)
---
src/field/index.js | 4 ++--
src/index-bar/index.js | 13 +++++++++----
src/list/demo/index.vue | 10 +++++++---
src/stepper/index.js | 4 ++--
src/tabs/index.js | 6 +++---
src/utils/dom/scroll.ts | 21 +++++++++++++++++----
6 files changed, 40 insertions(+), 18 deletions(-)
diff --git a/src/field/index.js b/src/field/index.js
index 418677aeb..d5ac2d1a0 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 a6be6c7a6..891f2c30b 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 b89ba7b54..a7fd5482f 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 883e161e3..5c6224d9d 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 c920520f0..9f66ad433 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 579140069..ea47358e8 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()
);
}