diff --git a/docs/src/demo-common.js b/docs/src/demo-common.js index 12dc16038..653e9ed84 100644 --- a/docs/src/demo-common.js +++ b/docs/src/demo-common.js @@ -7,7 +7,7 @@ import VueRouter from 'vue-router'; import VantDoc, { DemoBlock, DemoSection } from '@vant/doc'; import i18n from './utils/i18n'; import Vant, { Lazyload, Locale } from '../../packages'; -import { camelize } from '../../packages/utils'; +import { camelize } from '../../packages/utils/format/string'; Vue .use(Vant) diff --git a/docs/src/utils/i18n.js b/docs/src/utils/i18n.js index cd867fba3..e2882cf22 100644 --- a/docs/src/utils/i18n.js +++ b/docs/src/utils/i18n.js @@ -1,5 +1,6 @@ // component mixin -import { get, camelize } from '../../../packages/utils'; +import { get } from '../../../packages/utils'; +import { camelize } from '../../../packages/utils/format/string'; export default { computed: { diff --git a/packages/address-edit/Detail.js b/packages/address-edit/Detail.js index b9f16ba52..1a816b788 100644 --- a/packages/address-edit/Detail.js +++ b/packages/address-edit/Detail.js @@ -1,4 +1,5 @@ -import { use, isAndroid } from '../utils'; +import { use } from '../utils'; +import { isAndroid } from '../utils/validate/system'; import Cell from '../cell'; import Field from '../field'; diff --git a/packages/circle/index.js b/packages/circle/index.js index 3e33e1448..beccb1cde 100644 --- a/packages/circle/index.js +++ b/packages/circle/index.js @@ -1,5 +1,5 @@ import { use } from '../utils'; -import { raf, cancel } from '../utils/raf'; +import { raf, cancelRaf } from '../utils/dom/raf'; import { BLUE, WHITE } from '../utils/color'; const [sfc, bem] = use('circle'); @@ -81,7 +81,7 @@ export default sfc({ this.increase = this.endRate > this.startRate; this.duration = Math.abs(((this.startRate - this.endRate) * 1000) / this.speed); if (this.speed) { - cancel(this.rafId); + cancelRaf(this.rafId); this.rafId = raf(this.animate); } else { this.$emit('input', this.endRate); diff --git a/packages/collapse-item/index.js b/packages/collapse-item/index.js index c499cfcba..ed261db4e 100644 --- a/packages/collapse-item/index.js +++ b/packages/collapse-item/index.js @@ -1,5 +1,5 @@ import { use, isDef } from '../utils'; -import { raf } from '../utils/raf'; +import { raf } from '../utils/dom/raf'; import Cell from '../cell'; import { cellProps } from '../cell/shared'; import { ChildrenMixin } from '../mixins/relation'; diff --git a/packages/coupon/index.js b/packages/coupon/index.js index a99e04016..bd040337f 100644 --- a/packages/coupon/index.js +++ b/packages/coupon/index.js @@ -1,5 +1,6 @@ -import { use, padZero } from '../utils'; +import { use } from '../utils'; import { RED } from '../utils/color'; +import { padZero } from '../utils/format/string'; import Checkbox from '../checkbox'; const [sfc, bem, t] = use('coupon'); diff --git a/packages/datetime-picker/index.js b/packages/datetime-picker/index.js index 8cdd1c7c7..dd9fcb246 100644 --- a/packages/datetime-picker/index.js +++ b/packages/datetime-picker/index.js @@ -1,4 +1,6 @@ -import { use, range, padZero } from '../utils'; +import { use } from '../utils'; +import { range } from '../utils/format/number'; +import { padZero } from '../utils/format/string'; import Picker from '../picker'; import { pickerProps } from '../picker/shared'; import { diff --git a/packages/dialog/index.js b/packages/dialog/index.js index 77b7cbb6d..2ae98e5f5 100644 --- a/packages/dialog/index.js +++ b/packages/dialog/index.js @@ -1,9 +1,13 @@ import Vue from 'vue'; import VanDialog from './Dialog'; -import { isServer, isInDocument } from '../utils'; +import { isServer } from '../utils'; let instance; +function isInDocument(element) { + return document.body.contains(element); +} + function initInstance() { if (instance) { instance.$destroy(); diff --git a/packages/field/index.js b/packages/field/index.js index 98258c253..c352c96a7 100644 --- a/packages/field/index.js +++ b/packages/field/index.js @@ -1,9 +1,10 @@ import Icon from '../icon'; import Cell from '../cell'; import { cellProps } from '../cell/shared'; -import { preventDefault } from '../utils/event'; -import { getRootScrollTop } from '../utils/scroll'; -import { use, isObj, isDef, isIOS, suffixPx } from '../utils'; +import { preventDefault } from '../utils/dom/event'; +import { getRootScrollTop } from '../utils/dom/scroll'; +import { use, isObj, isDef, suffixPx } from '../utils'; +import { isIOS } from '../utils/validate/system'; const [sfc, bem] = use('field'); diff --git a/packages/image-preview/ImagePreview.js b/packages/image-preview/ImagePreview.js index 2e32bf7dd..a30b5fa7d 100644 --- a/packages/image-preview/ImagePreview.js +++ b/packages/image-preview/ImagePreview.js @@ -1,5 +1,6 @@ -import { use, range, isServer } from '../utils'; -import { preventDefault } from '../utils/event'; +import { use, isServer } from '../utils'; +import { range } from '../utils/format/number'; +import { preventDefault } from '../utils/dom/event'; import { PopupMixin } from '../mixins/popup'; import { TouchMixin } from '../mixins/touch'; import Swipe from '../swipe'; diff --git a/packages/index-bar/index.js b/packages/index-bar/index.js index dc086df34..e7cdb46e9 100644 --- a/packages/index-bar/index.js +++ b/packages/index-bar/index.js @@ -3,7 +3,7 @@ import { TouchMixin } from '../mixins/touch'; import { ParentMixin } from '../mixins/relation'; import { BindEventMixin } from '../mixins/bind-event'; import { GREEN } from '../utils/color'; -import { getScrollTop, getElementTop, getScrollEventTarget } from '../utils/scroll'; +import { getScrollTop, getElementTop, getScrollEventTarget } from '../utils/dom/scroll'; const [sfc, bem] = use('index-bar'); diff --git a/packages/list/index.js b/packages/list/index.js index b470c7581..b4cc67d31 100644 --- a/packages/list/index.js +++ b/packages/list/index.js @@ -6,7 +6,7 @@ import { getElementTop, getVisibleHeight, getScrollEventTarget -} from '../utils/scroll'; +} from '../utils/dom/scroll'; const [sfc, bem, t] = use('list'); diff --git a/packages/mixins/bind-event.js b/packages/mixins/bind-event.js index e213807c3..a25897d1d 100644 --- a/packages/mixins/bind-event.js +++ b/packages/mixins/bind-event.js @@ -1,4 +1,4 @@ -import { on, off } from '../utils/event'; +import { on, off } from '../utils/dom/event'; export function BindEventMixin(handler) { function bind() { diff --git a/packages/mixins/click-outside.js b/packages/mixins/click-outside.js index 7ac96b2f3..97fbf67aa 100644 --- a/packages/mixins/click-outside.js +++ b/packages/mixins/click-outside.js @@ -1,4 +1,4 @@ -import { on, off } from '../utils/event'; +import { on, off } from '../utils/dom/event'; export const ClickOutsideMixin = config => ({ mounted() { diff --git a/packages/mixins/popup/index.js b/packages/mixins/popup/index.js index 076b1cf6c..dd3a2dc28 100644 --- a/packages/mixins/popup/index.js +++ b/packages/mixins/popup/index.js @@ -1,8 +1,8 @@ import { context } from './context'; import { TouchMixin } from '../touch'; -import { on, off, preventDefault } from '../../utils/event'; +import { on, off, preventDefault } from '../../utils/dom/event'; import { openOverlay, closeOverlay, updateOverlay } from './overlay'; -import { getScrollEventTarget } from '../../utils/scroll'; +import { getScrollEventTarget } from '../../utils/dom/scroll'; export const PopupMixin = { mixins: [TouchMixin], diff --git a/packages/number-keyboard/index.js b/packages/number-keyboard/index.js index 2c5a09354..2c0b71cba 100644 --- a/packages/number-keyboard/index.js +++ b/packages/number-keyboard/index.js @@ -1,5 +1,5 @@ import { use } from '../utils'; -import { stopPropagation } from '../utils/event'; +import { stopPropagation } from '../utils/dom/event'; import { BindEventMixin } from '../mixins/bind-event'; import Key from './Key'; diff --git a/packages/overlay/index.tsx b/packages/overlay/index.tsx index 029a050fc..73c835492 100644 --- a/packages/overlay/index.tsx +++ b/packages/overlay/index.tsx @@ -1,6 +1,6 @@ import { use } from '../utils'; import { inherit } from '../utils/functional'; -import { preventDefault } from '../utils/event'; +import { preventDefault } from '../utils/dom/event'; // Types import { CreateElement, RenderContext } from 'vue/types'; diff --git a/packages/picker/PickerColumn.js b/packages/picker/PickerColumn.js index 1adf1c153..63d580317 100644 --- a/packages/picker/PickerColumn.js +++ b/packages/picker/PickerColumn.js @@ -1,6 +1,7 @@ import { deepClone } from '../utils/deep-clone'; -import { use, isObj, range } from '../utils'; -import { preventDefault } from '../utils/event'; +import { use, isObj } from '../utils'; +import { range } from '../utils/format/number'; +import { preventDefault } from '../utils/dom/event'; import { TouchMixin } from '../mixins/touch'; const DEFAULT_DURATION = 200; diff --git a/packages/picker/index.js b/packages/picker/index.js index 59d5a9314..27083d5f9 100644 --- a/packages/picker/index.js +++ b/packages/picker/index.js @@ -1,5 +1,5 @@ import { use } from '../utils'; -import { preventDefault } from '../utils/event'; +import { preventDefault } from '../utils/dom/event'; import { deepClone } from '../utils/deep-clone'; import { pickerProps } from './shared'; import { BLUE } from '../utils/color'; diff --git a/packages/pull-refresh/index.js b/packages/pull-refresh/index.js index 6d7c8affb..8882f669a 100644 --- a/packages/pull-refresh/index.js +++ b/packages/pull-refresh/index.js @@ -1,7 +1,7 @@ import { use } from '../utils'; -import { preventDefault } from '../utils/event'; +import { preventDefault } from '../utils/dom/event'; import { TouchMixin } from '../mixins/touch'; -import { getScrollTop, getScrollEventTarget } from '../utils/scroll'; +import { getScrollTop, getScrollEventTarget } from '../utils/dom/scroll'; import Loading from '../loading'; const [sfc, bem, t] = use('pull-refresh'); diff --git a/packages/rate/index.tsx b/packages/rate/index.tsx index 1fda2b62a..cb14e4f7a 100644 --- a/packages/rate/index.tsx +++ b/packages/rate/index.tsx @@ -1,7 +1,7 @@ /* eslint-disable prefer-spread */ import { use, suffixPx } from '../utils'; import { emit, inherit } from '../utils/functional'; -import { preventDefault } from '../utils/event'; +import { preventDefault } from '../utils/dom/event'; import Icon from '../icon'; // Types diff --git a/packages/search/index.tsx b/packages/search/index.tsx index 6b05a3d73..48d0d9291 100644 --- a/packages/search/index.tsx +++ b/packages/search/index.tsx @@ -1,6 +1,6 @@ import { use } from '../utils'; import { inherit, emit } from '../utils/functional'; -import { preventDefault } from '../utils/event'; +import { preventDefault } from '../utils/dom/event'; import Field from '../field'; // Types diff --git a/packages/slider/index.js b/packages/slider/index.js index 72938f160..a583f9b20 100644 --- a/packages/slider/index.js +++ b/packages/slider/index.js @@ -1,6 +1,6 @@ import { use, isDef } from '../utils'; import { TouchMixin } from '../mixins/touch'; -import { preventDefault } from '../utils/event'; +import { preventDefault } from '../utils/dom/event'; const [sfc, bem] = use('slider'); diff --git a/packages/swipe-cell/index.js b/packages/swipe-cell/index.js index fbe0abda6..1d169aa30 100644 --- a/packages/swipe-cell/index.js +++ b/packages/swipe-cell/index.js @@ -1,5 +1,6 @@ -import { use, range } from '../utils'; -import { preventDefault } from '../utils/event'; +import { use } from '../utils'; +import { range } from '../utils/format/number'; +import { preventDefault } from '../utils/dom/event'; import { TouchMixin } from '../mixins/touch'; import { ClickOutsideMixin } from '../mixins/click-outside'; diff --git a/packages/swipe/index.js b/packages/swipe/index.js index 6b6cc63ff..b847807a8 100644 --- a/packages/swipe/index.js +++ b/packages/swipe/index.js @@ -1,5 +1,5 @@ import { use } from '../utils'; -import { on, off, preventDefault } from '../utils/event'; +import { on, off, preventDefault } from '../utils/dom/event'; import { TouchMixin } from '../mixins/touch'; const [sfc, bem] = use('swipe'); diff --git a/packages/tabs/index.js b/packages/tabs/index.js index ef58e7af8..9e39d9bc8 100644 --- a/packages/tabs/index.js +++ b/packages/tabs/index.js @@ -1,6 +1,6 @@ import { use, isDef } from '../utils'; -import { raf } from '../utils/raf'; -import { on, off } from '../utils/event'; +import { raf } from '../utils/dom/raf'; +import { on, off } from '../utils/dom/event'; import { TouchMixin } from '../mixins/touch'; import { ParentMixin } from '../mixins/relation'; import { @@ -8,7 +8,7 @@ import { getScrollTop, getElementTop, getScrollEventTarget -} from '../utils/scroll'; +} from '../utils/dom/scroll'; const [sfc, bem] = use('tabs'); const tabBem = use('tab')[1]; diff --git a/packages/utils/event.ts b/packages/utils/dom/event.ts similarity index 94% rename from packages/utils/event.ts rename to packages/utils/dom/event.ts index 49c023bcc..1ea868c9a 100644 --- a/packages/utils/event.ts +++ b/packages/utils/dom/event.ts @@ -1,8 +1,8 @@ /* eslint-disable no-empty */ /* eslint-disable getter-return */ /* eslint-disable import/no-mutable-exports */ -import { isServer } from '.'; -import { EventHanlder } from './types'; +import { isServer } from '..'; +import { EventHanlder } from '../types'; export let supportsPassive = false; diff --git a/packages/utils/raf.ts b/packages/utils/dom/raf.ts similarity index 90% rename from packages/utils/raf.ts rename to packages/utils/dom/raf.ts index 80558d91f..772bea86b 100644 --- a/packages/utils/raf.ts +++ b/packages/utils/dom/raf.ts @@ -2,7 +2,7 @@ * requestAnimationFrame polyfill */ -import { isServer } from './index'; +import { isServer } from '..'; let prev = Date.now(); @@ -28,6 +28,6 @@ export function raf(fn: FrameRequestCallback): number { return iRaf.call(root, fn); } -export function cancel(id: number) { +export function cancelRaf(id: number) { iCancel.call(root, id); } diff --git a/packages/utils/scroll.ts b/packages/utils/dom/scroll.ts similarity index 100% rename from packages/utils/scroll.ts rename to packages/utils/dom/scroll.ts diff --git a/packages/utils/format/number.ts b/packages/utils/format/number.ts new file mode 100644 index 000000000..5401d691b --- /dev/null +++ b/packages/utils/format/number.ts @@ -0,0 +1,3 @@ +export function range(num: number, min: number, max: number): number { + return Math.min(Math.max(num, min), max); +} diff --git a/packages/utils/format/string.ts b/packages/utils/format/string.ts new file mode 100644 index 000000000..9f39001f9 --- /dev/null +++ b/packages/utils/format/string.ts @@ -0,0 +1,9 @@ +const camelizeRE = /-(\w)/g; + +export function camelize(str: string): string { + return str.replace(camelizeRE, (_, c) => c.toUpperCase()); +} + +export function padZero(num: number | string): string { + return (num < 10 ? '0' : '') + num; +} diff --git a/packages/utils/format/unit.ts b/packages/utils/format/unit.ts new file mode 100644 index 000000000..80ea0b597 --- /dev/null +++ b/packages/utils/format/unit.ts @@ -0,0 +1,11 @@ +import { isDef } from '..'; +import { isNumber } from '../validate/number'; + +export function suffixPx(value?: string | number): string | undefined { + if (!isDef(value)) { + return undefined; + } + + value = String(value); + return isNumber(value) ? `${value}px` : value; +} diff --git a/packages/utils/index.ts b/packages/utils/index.ts index 7102ae037..e881a3827 100644 --- a/packages/utils/index.ts +++ b/packages/utils/index.ts @@ -1,7 +1,7 @@ import Vue from 'vue'; -import { isNumber } from './validate/number'; export { use } from './use'; +export { suffixPx } from './format/unit'; export const isServer: boolean = Vue.prototype.$isServer; @@ -26,39 +26,3 @@ export function get(object: any, path: string): any { return result; } - -const camelizeRE = /-(\w)/g; -export function camelize(str: string): string { - return str.replace(camelizeRE, (_, c) => c.toUpperCase()); -} - -export function isAndroid(): boolean { - /* istanbul ignore next */ - return isServer ? false : /android/.test(navigator.userAgent.toLowerCase()); -} - -export function isIOS(): boolean { - /* istanbul ignore next */ - return isServer ? false : /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase()); -} - -export function range(num: number, min: number, max: number): number { - return Math.min(Math.max(num, min), max); -} - -export function isInDocument(element: HTMLElement): boolean { - return document.body.contains(element); -} - -export function suffixPx(value?: string | number): string | undefined { - if (!isDef(value)) { - return undefined; - } - - value = String(value); - return isNumber(value) ? `${value}px` : value; -} - -export function padZero(num: number | string): string { - return (num < 10 ? '0' : '') + num; -} diff --git a/packages/utils/test/index.spec.js b/packages/utils/test/index.spec.js index 66153a462..d2bebae65 100644 --- a/packages/utils/test/index.spec.js +++ b/packages/utils/test/index.spec.js @@ -1,10 +1,12 @@ import { deepClone } from '../deep-clone'; -import { isAndroid, isDef, camelize, get } from '..'; -import { raf, cancel } from '../raf'; +import { isDef, get } from '..'; +import { raf, cancelRaf } from '../dom/raf'; import { later } from '../../../test/utils'; import { isEmail } from '../validate/email'; import { isMobile } from '../validate/mobile'; import { isNumber } from '../validate/number'; +import { isAndroid } from '../validate/system'; +import { camelize } from '../format/string'; test('deepClone', () => { const a = { foo: 0 }; @@ -53,7 +55,7 @@ test('raf', async () => { await later(50); expect(spy).toHaveBeenCalledTimes(1); - cancel(1); + cancelRaf(1); }); test('is-email', () => { diff --git a/packages/utils/use/i18n.ts b/packages/utils/use/i18n.ts index 4291619c8..fec8eabc1 100644 --- a/packages/utils/use/i18n.ts +++ b/packages/utils/use/i18n.ts @@ -1,4 +1,5 @@ -import { get, camelize } from '..'; +import { get } from '..'; +import { camelize } from '../format/string'; import locale from '../../locale'; export function useI18N(name: string) { diff --git a/packages/utils/use/sfc.ts b/packages/utils/use/sfc.ts index fe0710370..945f49287 100644 --- a/packages/utils/use/sfc.ts +++ b/packages/utils/use/sfc.ts @@ -2,7 +2,7 @@ * Create a basic component with common options */ import '../../locale'; -import { camelize } from '..'; +import { camelize } from '../format/string'; import { SlotsMixin } from '../../mixins/slots'; import Vue, { VNode, VueConstructor, ComponentOptions, RenderContext } from 'vue'; import { DefaultProps, FunctionComponent } from '../types'; diff --git a/packages/utils/validate/system.ts b/packages/utils/validate/system.ts new file mode 100644 index 000000000..3c13bb612 --- /dev/null +++ b/packages/utils/validate/system.ts @@ -0,0 +1,11 @@ +import { isServer } from '..'; + +export function isAndroid(): boolean { + /* istanbul ignore next */ + return isServer ? false : /android/.test(navigator.userAgent.toLowerCase()); +} + +export function isIOS(): boolean { + /* istanbul ignore next */ + return isServer ? false : /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase()); +}