UNPKG

ui-template-muc

Version:

A fantastic mobile ui lib implement by Vue

233 lines (210 loc) 6.76 kB
//浏览器相关 let inBrowser = typeof window !== 'undefined' let UA = inBrowser && window.navigator.userAgent.toLowerCase() let isIE = UA && /msie|trident/.test(UA) let isIE9 = UA && UA.indexOf('msie 9.0') > 0 let isEdge = UA && UA.indexOf('edge/') > 0 let isAndroid = (UA && UA.indexOf('android') > 0) let isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) let isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge export let ua = {isIE, isIE9, isEdge, isAndroid, isIOS, isChrome} //工具函数 export function findIndex (ary, fn) { if (ary.findIndex) { return ary.findIndex(fn) } /* istanbul ignore next */ let index = -1 /* istanbul ignore next */ ary.some(function (item, i, ary) { const ret = fn.call(this, item, i, ary) if (ret) { index = i return ret } }) /* istanbul ignore next */ return index } export function deepAssign (to, from) { for (let key in from) { if (!to[key] || typeof to[key] !== 'object') { to[key] = from[key] } else { deepAssign(to[key], from[key]) } } } export function isArray (args) { if (Array.isArray) { return Array.isArray(args) } return Object.prototype.toString.call(args) === '[object Array]' } export function isString (args) { return Object.prototype.toString.call(args) === '[object String]' } export function isNumber (args) { return Object.prototype.toString.call(args) === '[object Number]' } export function isObject (args) { return Object.prototype.toString.call(args) === '[object Object]' } /* @param {Function} func The function to debounce. * @param {number} [wait=0] * The number of milliseconds to delay; if omitted, `requestAnimationFrame` is * used (if available). * @param {Object} [options={}] The options object. * @param {boolean} [options.leading=false] * Specify invoking on the leading edge of the timeout. * @param {number} [options.maxWait] * The maximum time `func` is allowed to be delayed before it's invoked. * @param {boolean} [options.trailing=true] * Specify invoking on the trailing edge of the timeout. * @returns {Function} Returns the new debounced function. */ export function debounce (func, wait, options) { let lastArgs, lastThis, maxWait, result, timerId, lastCallTime let lastInvokeTime = 0 let leading = false let maxing = false let trailing = true // Bypass `requestAnimationFrame` by explicitly setting `wait=0`. const useRAF = (!wait && wait !== 0 && typeof window.requestAnimationFrame === 'function') if (typeof func !== 'function') { throw new TypeError('Expected a function') } wait = +wait || 0 if (isObject(options)) { leading = !!options.leading maxing = 'maxWait' in options maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait trailing = 'trailing' in options ? !!options.trailing : trailing } function invokeFunc (time) { const args = lastArgs const thisArg = lastThis lastArgs = lastThis = undefined lastInvokeTime = time result = func.apply(thisArg, args) return result } function startTimer (pendingFunc, wait) { if (useRAF) { window.cancelAnimationFrame(timerId) return window.requestAnimationFrame(pendingFunc) } return setTimeout(pendingFunc, wait) } function cancelTimer (id) { if (useRAF) { return window.cancelAnimationFrame(id) } clearTimeout(id) } function leadingEdge (time) { // Reset any `maxWait` timer. lastInvokeTime = time // Start the timer for the trailing edge. timerId = startTimer(timerExpired, wait) // Invoke the leading edge. return leading ? invokeFunc(time) : result } function remainingWait (time) { const timeSinceLastCall = time - lastCallTime const timeSinceLastInvoke = time - lastInvokeTime const timeWaiting = wait - timeSinceLastCall return maxing ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting } function shouldInvoke (time) { const timeSinceLastCall = time - lastCallTime const timeSinceLastInvoke = time - lastInvokeTime // Either this is the first call, activity has stopped and we're at the // trailing edge, the system time has gone backwards and we're treating // it as the trailing edge, or we've hit the `maxWait` limit. return (lastCallTime === undefined || (timeSinceLastCall >= wait) || (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)) } function timerExpired () { const time = Date.now() if (shouldInvoke(time)) { return trailingEdge(time) } // Restart the timer. timerId = startTimer(timerExpired, remainingWait(time)) } function trailingEdge (time) { timerId = undefined // Only invoke if we have `lastArgs` which means `func` has been // debounced at least once. if (trailing && lastArgs) { return invokeFunc(time) } lastArgs = lastThis = undefined return result } function cancel () { if (timerId !== undefined) { cancelTimer(timerId) } lastInvokeTime = 0 lastArgs = lastCallTime = lastThis = timerId = undefined } function flush () { return timerId === undefined ? result : trailingEdge(Date.now()) } function pending () { return timerId !== undefined } function debounced (...args) { const time = Date.now() const isInvoking = shouldInvoke(time) lastArgs = args lastThis = this lastCallTime = time if (isInvoking) { if (timerId === undefined) { return leadingEdge(lastCallTime) } if (maxing) { // Handle invocations in a tight loop. timerId = startTimer(timerExpired, wait) return invokeFunc(lastCallTime) } } if (timerId === undefined) { timerId = startTimer(timerExpired, wait) } return result } debounced.cancel = cancel debounced.flush = flush debounced.pending = pending return debounced } export function throttle (func, wait, options) { let leading = true let trailing = true if (typeof func !== 'function') { throw new TypeError('Expected a function') } if (isObject(options)) { leading = 'leading' in options ? !!options.leading : leading trailing = 'trailing' in options ? !!options.trailing : trailing } return debounce(func, wait, { leading, trailing, 'maxWait': wait }) } export function isNative (Ctor) { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) }