From f0056297c683f02c421e69622975d030804e2edd Mon Sep 17 00:00:00 2001 From: neverland Date: Sat, 2 Feb 2019 10:41:01 +0800 Subject: [PATCH] [improvement] sort out utils (#2672) --- packages/list/index.js | 27 +++++++------- packages/mixins/popup/index.js | 6 ++-- packages/pull-refresh/index.js | 6 ++-- packages/tabs/index.js | 12 +++---- packages/utils/index.js | 30 +++++----------- packages/utils/scroll.js | 63 ++++++++++++++++++--------------- packages/utils/slots.js | 8 ----- packages/utils/use/index.js | 11 +++++- packages/waterfall/directive.js | 20 +++++++---- 9 files changed, 93 insertions(+), 90 deletions(-) delete mode 100644 packages/utils/slots.js diff --git a/packages/list/index.js b/packages/list/index.js index e05bfdd0d..cac5cfe82 100644 --- a/packages/list/index.js +++ b/packages/list/index.js @@ -1,7 +1,13 @@ import { use } from '../utils'; -import utils from '../utils/scroll'; import Loading from '../loading'; import { on, off } from '../utils/event'; +import { + getScrollTop, + getElementTop, + getVisibleHeight, + getComputedStyle, + getScrollEventTarget +} from '../utils/scroll'; const [sfc, bem, t] = use('list'); @@ -28,7 +34,7 @@ export default sfc({ }, mounted() { - this.scroller = utils.getScrollEventTarget(this.$el); + this.scroller = getScrollEventTarget(this.$el); this.handler(true); if (this.immediateCheck) { @@ -66,18 +72,14 @@ export default sfc({ const el = this.$el; const { scroller } = this; - const scrollerHeight = utils.getVisibleHeight(scroller); + const scrollerHeight = getVisibleHeight(scroller); /* istanbul ignore next */ - if ( - !scrollerHeight || - utils.getComputedStyle(el).display === 'none' || - el.offsetParent === null - ) { + if (!scrollerHeight || getComputedStyle(el).display === 'none' || el.offsetParent === null) { return; } - const scrollTop = utils.getScrollTop(scroller); + const scrollTop = getScrollTop(scroller); const targetBottom = scrollTop + scrollerHeight; let reachBottom = false; @@ -86,8 +88,7 @@ export default sfc({ if (el === scroller) { reachBottom = scroller.scrollHeight - targetBottom < this.offset; } else { - const elBottom = - utils.getElementTop(el) - utils.getElementTop(scroller) + utils.getVisibleHeight(el); + const elBottom = getElementTop(el) - getElementTop(scroller) + getVisibleHeight(el); reachBottom = elBottom - scrollerHeight < this.offset; } @@ -128,7 +129,9 @@ export default sfc({
{this.finishedText}
)} {this.error && this.errorText && ( -
{this.errorText}
+
+ {this.errorText} +
)} ); diff --git a/packages/mixins/popup/index.js b/packages/mixins/popup/index.js index 525f0d40c..4e96fd710 100644 --- a/packages/mixins/popup/index.js +++ b/packages/mixins/popup/index.js @@ -1,8 +1,8 @@ import manager from './manager'; import context from './context'; -import scrollUtils from '../../utils/scroll'; -import { on, off } from '../../utils/event'; import Touch from '../touch'; +import { on, off } from '../../utils/event'; +import { getScrollEventTarget } from '../../utils/scroll'; export default { mixins: [Touch], @@ -159,7 +159,7 @@ export default { onTouchMove(e) { this.touchMove(e); const direction = this.deltaY > 0 ? '10' : '01'; - const el = scrollUtils.getScrollEventTarget(e.target, this.$el); + const el = getScrollEventTarget(e.target, this.$el); const { scrollHeight, offsetHeight, scrollTop } = el; let status = '11'; diff --git a/packages/pull-refresh/index.js b/packages/pull-refresh/index.js index c9f91658e..ce1c38be0 100644 --- a/packages/pull-refresh/index.js +++ b/packages/pull-refresh/index.js @@ -1,7 +1,7 @@ import { use } from '../utils'; import Loading from '../loading'; -import scrollUtils from '../utils/scroll'; import Touch from '../mixins/touch'; +import { getScrollTop, getScrollEventTarget } from '../utils/scroll'; const [sfc, bem, t] = use('pull-refresh'); @@ -49,7 +49,7 @@ export default sfc({ }, mounted() { - this.scrollEl = scrollUtils.getScrollEventTarget(this.$el); + this.scrollEl = getScrollEventTarget(this.$el); }, methods: { @@ -95,7 +95,7 @@ export default sfc({ }, getCeiling() { - this.ceiling = scrollUtils.getScrollTop(this.scrollEl) === 0; + this.ceiling = getScrollTop(this.scrollEl) === 0; return this.ceiling; }, diff --git a/packages/tabs/index.js b/packages/tabs/index.js index e9c14f1cb..7afd0326b 100644 --- a/packages/tabs/index.js +++ b/packages/tabs/index.js @@ -1,8 +1,8 @@ import { use, isDef } from '../utils'; +import Touch from '../mixins/touch'; import { raf } from '../utils/raf'; import { on, off } from '../utils/event'; -import scrollUtils from '../utils/scroll'; -import Touch from '../mixins/touch'; +import { setScrollTop, getScrollTop, getElementTop, getScrollEventTarget } from '../utils/scroll'; const [sfc, bem] = use('tabs'); const tabBem = use('tab')[1]; @@ -128,7 +128,7 @@ export default sfc({ // scroll to correct position if (this.position === 'top' || this.position === 'bottom') { - scrollUtils.setScrollTop(window, scrollUtils.getElementTop(this.$el)); + setScrollTop(window, getElementTop(this.$el)); } }, @@ -179,7 +179,7 @@ export default sfc({ // listen to scroll event if (events.sticky !== sticky) { events.sticky = sticky; - this.scrollEl = this.scrollEl || scrollUtils.getScrollEventTarget(this.$el); + this.scrollEl = this.scrollEl || getScrollEventTarget(this.$el); (sticky ? on : off)(this.scrollEl, 'scroll', this.onScroll, true); this.onScroll(); } @@ -215,8 +215,8 @@ export default sfc({ // adjust tab position onScroll() { - const scrollTop = scrollUtils.getScrollTop(window) + this.offsetTop; - const elTopToPageTop = scrollUtils.getElementTop(this.$el); + const scrollTop = getScrollTop(window) + this.offsetTop; + const elTopToPageTop = getElementTop(this.$el); const elBottomToPageTop = elTopToPageTop + this.$el.offsetHeight - this.$refs.wrap.offsetHeight; if (scrollTop > elBottomToPageTop) { diff --git a/packages/utils/index.js b/packages/utils/index.js index 2c710e80f..21a5d2ca1 100644 --- a/packages/utils/index.js +++ b/packages/utils/index.js @@ -1,19 +1,19 @@ import Vue from 'vue'; -import use from './use'; -import { useSlots } from './slots'; -const isServer = Vue.prototype.$isServer; +export { use, useSlots } from './use'; -function isDef(value) { +export const isServer = Vue.prototype.$isServer; + +export function isDef(value) { return value !== undefined && value !== null; } -function isObj(x) { +export function isObj(x) { const type = typeof x; return x !== null && (type === 'object' || type === 'function'); } -function get(object, path) { +export function get(object, path) { const keys = path.split('.'); let result = object; @@ -25,27 +25,15 @@ function get(object, path) { } const camelizeRE = /-(\w)/g; -function camelize(str) { +export function camelize(str) { return str.replace(camelizeRE, (_, c) => c.toUpperCase()); } -function isAndroid() { +export function isAndroid() { /* istanbul ignore next */ return isServer ? false : /android/.test(navigator.userAgent.toLowerCase()); } -function range(num, min, max) { +export function range(num, min, max) { return Math.min(Math.max(num, min), max); } - -export { - use, - get, - range, - isObj, - isDef, - isServer, - useSlots, - camelize, - isAndroid -}; diff --git a/packages/utils/scroll.js b/packages/utils/scroll.js index 414d3c13a..bc6ff9e77 100644 --- a/packages/utils/scroll.js +++ b/packages/utils/scroll.js @@ -1,36 +1,41 @@ import { isServer } from '.'; -export default { - // get nearest scroll element - getScrollEventTarget(element, rootParent = window) { - let node = element; - // bugfix, see http://w3help.org/zh-cn/causes/SD9013 and http://stackoverflow.com/questions/17016740/onscroll-function-is-not-working-for-chrome - while (node && node.tagName !== 'HTML' && node.tagName !== 'BODY' && node.nodeType === 1 && node !== rootParent) { - const { overflowY } = this.getComputedStyle(node); - if (overflowY === 'scroll' || overflowY === 'auto') { - return node; - } - node = node.parentNode; +export const getComputedStyle = !isServer && document.defaultView.getComputedStyle.bind(document.defaultView); + +// get nearest scroll element +// http://w3help.org/zh-cn/causes/SD9013 +// http://stackoverflow.com/questions/17016740/onscroll-function-is-not-working-for-chrome +export function getScrollEventTarget(element, rootParent = window) { + let node = element; + while ( + node && + node.tagName !== 'HTML' && + node.tagName !== 'BODY' && + node.nodeType === 1 && + node !== rootParent + ) { + const { overflowY } = getComputedStyle(node); + if (overflowY === 'scroll' || overflowY === 'auto') { + return node; } - return rootParent; - }, + node = node.parentNode; + } + return rootParent; +} - getScrollTop(element) { - return 'scrollTop' in element ? element.scrollTop : element.pageYOffset; - }, +export function getScrollTop(element) { + return 'scrollTop' in element ? element.scrollTop : element.pageYOffset; +} - setScrollTop(element, value) { - 'scrollTop' in element ? element.scrollTop = value : element.scrollTo(element.scrollX, value); - }, +export function setScrollTop(element, value) { + 'scrollTop' in element ? (element.scrollTop = value) : element.scrollTo(element.scrollX, value); +} - // get distance from element top to page top - getElementTop(element) { - return (element === window ? 0 : element.getBoundingClientRect().top) + this.getScrollTop(window); - }, +// get distance from element top to page top +export function getElementTop(element) { + return (element === window ? 0 : element.getBoundingClientRect().top) + getScrollTop(window); +} - getVisibleHeight(element) { - return element === window ? element.innerHeight : element.getBoundingClientRect().height; - }, - - getComputedStyle: !isServer && document.defaultView.getComputedStyle.bind(document.defaultView) -}; +export function getVisibleHeight(element) { + return element === window ? element.innerHeight : element.getBoundingClientRect().height; +} diff --git a/packages/utils/slots.js b/packages/utils/slots.js deleted file mode 100644 index b324e9b35..000000000 --- a/packages/utils/slots.js +++ /dev/null @@ -1,8 +0,0 @@ -export function useSlots({ $slots, $scopedSlots }) { - return (name, props) => { - if ($scopedSlots[name]) { - return $scopedSlots[name](props); - } - return $slots[name]; - }; -} diff --git a/packages/utils/use/index.js b/packages/utils/use/index.js index da1e785e2..e0647c86b 100644 --- a/packages/utils/use/index.js +++ b/packages/utils/use/index.js @@ -2,7 +2,16 @@ import useBem from './bem'; import useSfc from './sfc'; import useI18n from './i18n'; -export default function (name) { +export function use(name) { name = 'van-' + name; return [useSfc(name), useBem(name), useI18n(name)]; } + +export function useSlots({ $slots, $scopedSlots }) { + return (name, props) => { + if ($scopedSlots[name]) { + return $scopedSlots[name](props); + } + return $slots[name]; + }; +} diff --git a/packages/waterfall/directive.js b/packages/waterfall/directive.js index 7d7edebc0..0e3716e46 100644 --- a/packages/waterfall/directive.js +++ b/packages/waterfall/directive.js @@ -1,6 +1,11 @@ /* eslint-disable no-underscore-dangle */ -import Utils from '../utils/scroll'; import { on, off } from '../utils/event'; +import { + getScrollTop, + getElementTop, + getVisibleHeight, + getScrollEventTarget +} from '../utils/scroll'; const CONTEXT = '@@Waterfall'; const OFFSET = 300; @@ -12,8 +17,8 @@ function handleScrollEvent() { // 已被禁止的滚动处理 if (this.disabled) return; - const targetScrollTop = Utils.getScrollTop(scrollEventTarget); - const targetVisibleHeight = Utils.getVisibleHeight(scrollEventTarget); + const targetScrollTop = getScrollTop(scrollEventTarget); + const targetVisibleHeight = getVisibleHeight(scrollEventTarget); // 滚动元素可视区域下边沿到滚动元素元素最顶上 距离 const targetBottom = targetScrollTop + targetVisibleHeight; @@ -25,7 +30,8 @@ function handleScrollEvent() { if (element === scrollEventTarget) { needLoadMoreToLower = scrollEventTarget.scrollHeight - targetBottom < this.offset; } else { - const elementBottom = Utils.getElementTop(element) - Utils.getElementTop(scrollEventTarget) + Utils.getVisibleHeight(element); + const elementBottom = + getElementTop(element) - getElementTop(scrollEventTarget) + getVisibleHeight(element); needLoadMoreToLower = elementBottom - targetVisibleHeight < this.offset; } if (needLoadMoreToLower) { @@ -37,7 +43,7 @@ function handleScrollEvent() { if (element === scrollEventTarget) { needLoadMoreToUpper = targetScrollTop < this.offset; } else { - const elementTop = Utils.getElementTop(element) - Utils.getElementTop(scrollEventTarget); + const elementTop = getElementTop(element) - getElementTop(scrollEventTarget); needLoadMoreToUpper = elementTop + this.offset > 0; } if (needLoadMoreToUpper) { @@ -54,12 +60,12 @@ function doBindEvent() { this.el[CONTEXT].binded = true; this.scrollEventListener = handleScrollEvent.bind(this); - this.scrollEventTarget = Utils.getScrollEventTarget(this.el); + this.scrollEventTarget = getScrollEventTarget(this.el); const disabledExpr = this.el.getAttribute('waterfall-disabled'); let disabled = false; if (disabledExpr) { - this.vm.$watch(disabledExpr, (value) => { + this.vm.$watch(disabledExpr, value => { this.disabled = value; this.scrollEventListener(); });