UNPKG

@sdc-monitor/demo

Version:

<div align="center"> <a href="#" target="_blank"> <img src="https://i.loli.net/2021/07/28/EvPwd4NjVH3tBfO.jpg" alt="mito-logo" height="90"> </a> <p>A Lightweight SDK For Monitor Web</p>

316 lines (289 loc) 8.91 kB
import { IAnyObject } from '@sdc-monitor/types' import { globalVar, ToStringTypes } from '@sdc-monitor/shared' import { logger } from './logger' import { nativeToString, variableTypeDetection } from './is' import { isWxMiniEnv, isBrowserEnv } from './global' export function getLocationHref(): string { if (typeof document === 'undefined' || document.location == null) return '' return document.location.href } export function getUrlWithEnv(): string { if (isWxMiniEnv) return getCurrentRoute() if (isBrowserEnv) return getLocationHref() return '' } // 用到所有事件的名称 type TotalEventName = keyof GlobalEventHandlersEventMap | keyof XMLHttpRequestEventTargetEventMap | keyof WindowEventMap /** * 添加事件监听器 * * @export * @param {{ addEventListener: Function }} target 目标对象 * @param {TotalEventName} eventName 目标对象上的事件名 * @param {Function} handler 回调函数 * @param {(boolean | unknown)} [opitons=false] useCapture默认为false */ export function on( target: { addEventListener: Function }, eventName: TotalEventName, handler: Function, opitons: boolean | unknown = false ): void { target.addEventListener(eventName, handler, opitons) } /** * 重写对象上面的某个属性 * * @export * @param {IAnyObject} source 需要被重写的对象 * @param {string} name 需要被重写对象的key * @param {(...args: any[]) => any} replacement 以原有的函数作为参数,执行并重写原有函数 * @param {boolean} [isForced=false] 是否强制重写(可能原先没有该属性) */ export function replaceOld(source: IAnyObject, name: string, replacement: (...args: any[]) => any, isForced = false): void { if (source === undefined) return if (name in source || isForced) { const original = source[name] const wrapped = replacement(original) if (typeof wrapped === 'function') { source[name] = wrapped } } } /** * 用&分割对象,返回a=1&b=2 * ../param obj 需要拼接的对象 */ // export function splitObjToQuery(obj: Record<string, unknown>): string { // return Object.entries(obj).reduce((result, [key, value], index) => { // if (index !== 0) { // result += '&' // } // const valueStr = variableTypeDetection.isObject(value) || variableTypeDetection.isArray(value) ? JSON.stringify(value) : value // result += `${key}=${valueStr}` // return result // }, '') // } export const defaultFunctionName = '<anonymous>' /** * 需要获取函数名,匿名则返回<anonymous> * ../param {unknown} fn 需要获取函数名的函数本体 * ../returns 返回传入的函数的函数名 */ export function getFunctionName(fn: unknown): string { if (!fn || typeof fn !== 'function') { return defaultFunctionName } return fn.name || defaultFunctionName } // 函数防抖 /** * * ../param fn 需要防抖的函数 * ../param delay 防抖的时间间隔 * ../param isImmediate 是否需要立即执行,默认为false,第一次是不执行的 * ../returns 返回一个包含防抖功能的函数 */ // export const debounce = (fn: voidFun, delay: number, isImmediate = false): voidFun => { // let timer = null // return function (...args: any) { // if (isImmediate) { // fn.apply(this, args) // isImmediate = false // return // } // clearTimeout(timer) // timer = setTimeout(() => { // fn.apply(this, args) // }, delay) // } // } /** * 函数节流 * * @export * @param {Function} fn 需要节流的函数 * @param {number} delay 节流的时间间隔 * @return {*} {Function} 返回一个包含节流功能的函数 */ export function throttle(fn: Function, delay: number): Function { let canRun = true return function (...args: any) { if (!canRun) return fn.apply(this, args) canRun = false setTimeout(() => { canRun = true }, delay) } } /** * 原子字符中是否包含目标字符 * * @export * @param {string} origin 原字符 * @param {string} target 目标字符 * @return {*} {boolean} */ export function isInclude(origin: string, target: string): boolean { return !!~origin.indexOf(target) } /** * 获取当前的时间戳 * * @export * @return {*} {number} */ export function getTimestamp(): number { return Date.now() } export function toStringAny(target: any, type: ToStringTypes): boolean { return nativeToString.call(target) === `[object ${type}]` } export function toStringValidateOption(target: any, targetName: string, expectType: ToStringTypes): boolean { if (toStringAny(target, expectType)) return true typeof target !== 'undefined' && logger.error(`${targetName}期望传入:${expectType}类型,当前是:${nativeToString.call(target)}类型`) return false } /** * 如果用户输入console,并且logger是打开的会造成无限递归,执行callback前,会把监听console的行为关掉 * * @export * @param {Function} callback */ export function silentConsoleScope(callback: Function) { globalVar.isLogAddBreadcrumb = false callback() globalVar.isLogAddBreadcrumb = true } export function generateUUID(): string { let d = new Date().getTime() const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { const r = (d + Math.random() * 16) % 16 | 0 d = Math.floor(d / 16) return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16) }) return uuid } export function unknownToString(target: unknown): string { if (variableTypeDetection.isString(target)) { return target as string } if (variableTypeDetection.isUndefined(target)) { return 'undefined' } return JSON.stringify(target) } export function getBigVersion(version: string) { return Number(version.split('.')[0]) } /** * 给url添加query * @param url * @param query */ export function setUrlQuery(url: string, query: object) { const queryArr = [] Object.keys(query).forEach((k) => { queryArr.push(`${k}=${query[k]}`) }) if (url.indexOf('?') !== -1) { url = `${url}&${queryArr.join('&')}` } else { url = `${url}?${queryArr.join('&')}` } return url } export function interceptStr(str: string, interceptLength: number): string { if (variableTypeDetection.isString(str)) { return str.slice(0, interceptLength) + (str.length > interceptLength ? `;slice the first ${interceptLength} characters` : '') } return '' } /** * 获取wx当前route的方法 * 必须是在进入Page或Component构造函数内部才能够获取到currentPages * 否则都是在注册Page和Component时执行的代码,此时url默认返回'App' */ export function getCurrentRoute() { if (!variableTypeDetection.isFunction(getCurrentPages)) { return '' } const pages = getCurrentPages() // 在App里调用该方法,页面还没有生成,长度为0 if (!pages.length) { return 'App' } const currentPage = pages.pop() return setUrlQuery(currentPage.route, currentPage.options) } /** *将传入的字符串的首字母改为大写,其他不变 * * @export * @param {string} str 原字符 * @return {*} {string} * @example xhr => Xhr */ export function firstStrtoUppercase(str: string): string { return str.replace(/\b(\w)(\w*)/g, function ($0: string, $1: string, $2: string) { return `${$1.toUpperCase()}${$2}` }) } /** *将传入的字符串的首字母改为小写,其他不变 * * @export * @param {string} str 原字符 * @return {*} {string} * @example Xhr => xhr */ export function firstStrtoLowerCase(str: string): string { return str.replace(/\b(\w)(\w*)/g, function ($0: string, $1: string, $2: string) { return `${$1.toLowerCase()}${$2}` }) } /** * 安全的转换对象,包括循环引用,如果是循环引用就返回Circular * * @export * @param {object} obj 需要转换的对象 * @return {*} {string} */ export function safeStringify(obj: object): string { const set = new Set() const str = JSON.stringify(obj, function (_key, value) { if (set.has(value)) { return 'Circular' } typeof value === 'object' && set.add(value) return value }) set.clear() return str } /** * 解决Vue3抛出的proxy对象循环引用的问题 * * @export * @template T * @param {IAnyObject} obj * @return {*} {T} */ export function getObjectWithForIn<T = IAnyObject>(obj: IAnyObject): T { if (!variableTypeDetection.isObject(obj)) return obj as unknown as T const result = {} for (const key in obj) { result[key] = obj[key] } return result as T } export function validateOptionsAndSet(this: any, targetArr: [any, string, ToStringTypes][]) { targetArr.forEach( ([target, targetName, expectType]) => toStringValidateOption(target, targetName, expectType) && (this[targetName] = target) ) } export function sleepRun(fn: () => void, delay = 200) { setTimeout(() => { fn() }, delay) }