init
This commit is contained in:
277
uni_modules/nutui-uni/components/_utils/common.ts
Normal file
277
uni_modules/nutui-uni/components/_utils/common.ts
Normal file
@@ -0,0 +1,277 @@
|
||||
import { isArray, isDef, isObject } from './is'
|
||||
|
||||
// 变量类型判断
|
||||
export function TypeOfFun(value: any) {
|
||||
if (value === null)
|
||||
return 'null'
|
||||
|
||||
const type = typeof value
|
||||
if (type === 'undefined' || type === 'string')
|
||||
return type
|
||||
|
||||
const typeString = toString.call(value)
|
||||
switch (typeString) {
|
||||
case '[object Array]':
|
||||
return 'array'
|
||||
case '[object Date]':
|
||||
return 'date'
|
||||
case '[object Boolean]':
|
||||
return 'boolean'
|
||||
case '[object Number]':
|
||||
return 'number'
|
||||
case '[object Function]':
|
||||
return 'function'
|
||||
case '[object RegExp]':
|
||||
return 'regexp'
|
||||
case '[object Object]':
|
||||
if (undefined !== value.nodeType) {
|
||||
if (value.nodeType === 3)
|
||||
return /\S/.test(value.nodeValue) ? 'textnode' : 'whitespace'
|
||||
else
|
||||
return 'element'
|
||||
}
|
||||
else {
|
||||
return 'object'
|
||||
}
|
||||
default:
|
||||
return 'unknow'
|
||||
}
|
||||
}
|
||||
//
|
||||
export const objectToString = Object.prototype.toString
|
||||
export const toTypeString = (value: unknown): string => objectToString.call(value)
|
||||
|
||||
export function toRawType(value: unknown): string {
|
||||
// extract "RawType" from strings like "[object RawType]"
|
||||
return toTypeString(value).slice(8, -1)
|
||||
}
|
||||
|
||||
export const win = window
|
||||
|
||||
export const docu = document
|
||||
|
||||
export const body = docu.body
|
||||
|
||||
export function getPropByPath(obj: any, keyPath: string) {
|
||||
try {
|
||||
return keyPath.split('.').reduce((prev, curr) => prev[curr], obj)
|
||||
}
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
catch (error) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
export function floatData(format: any, dataOp: any, mapOps: any) {
|
||||
const mergeFormat = Object.assign({}, format)
|
||||
const mergeMapOps = Object.assign({}, mapOps)
|
||||
|
||||
if (Object.keys(dataOp).length > 0) {
|
||||
Object.keys(mergeFormat).forEach((keys) => {
|
||||
if (Object.prototype.hasOwnProperty.call(mergeMapOps, keys)) {
|
||||
const tof = TypeOfFun(mergeMapOps[keys])
|
||||
if (tof === 'function')
|
||||
mergeFormat[keys] = mergeMapOps[keys](dataOp)
|
||||
|
||||
if (tof === 'string')
|
||||
mergeFormat[keys] = dataOp[mergeMapOps[keys]]
|
||||
}
|
||||
else {
|
||||
if (dataOp[keys])
|
||||
mergeFormat[keys] = dataOp[keys]
|
||||
}
|
||||
})
|
||||
return mergeFormat
|
||||
}
|
||||
|
||||
return format
|
||||
}
|
||||
|
||||
export function myFixed(num: any, digit = 2) {
|
||||
if (Object.is(Number.parseFloat(num), Number.NaN))
|
||||
return console.warn(`传入的值:${num}不是一个数字`)
|
||||
|
||||
num = Number.parseFloat(num)
|
||||
return (Math.round((num + Number.EPSILON) * 10 ** digit) / 10 ** digit).toFixed(digit)
|
||||
}
|
||||
|
||||
export function preventDefault(event: Event, isStopPropagation?: boolean) {
|
||||
if (typeof event.cancelable !== 'boolean' || event.cancelable)
|
||||
event.preventDefault()
|
||||
|
||||
if (isStopPropagation)
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
function cacheStringFunction<T extends (str: string) => string>(fn: T): T {
|
||||
const cache: Record<string, string> = Object.create(null)
|
||||
return ((str: string) => {
|
||||
const hit = cache[str]
|
||||
|
||||
return hit || (cache[str] = fn(str))
|
||||
}) as T
|
||||
}
|
||||
|
||||
const hyphenateRE = /\B([A-Z])/g
|
||||
export const hyphenate = cacheStringFunction((str: string) =>
|
||||
str.replace(hyphenateRE, '-$1').toLowerCase(),
|
||||
)
|
||||
|
||||
export function padZero(num: number | string, length = 2): string {
|
||||
num += ''
|
||||
while ((num as string).length < length)
|
||||
num = `0${num}`
|
||||
|
||||
return num.toString()
|
||||
}
|
||||
|
||||
export const clamp = (num: number, min: number, max: number): number => Math.min(Math.max(num, min), max)
|
||||
|
||||
export function getScrollTopRoot(): number {
|
||||
return window.scrollY || document.documentElement.scrollTop || document.body.scrollTop || 0
|
||||
}
|
||||
|
||||
type ObjectIndex = Record<string, unknown>
|
||||
|
||||
const { hasOwnProperty } = Object.prototype
|
||||
|
||||
function assignKey(to: ObjectIndex, from: ObjectIndex, key: string) {
|
||||
const val = from[key]
|
||||
|
||||
if (!isDef(val))
|
||||
return
|
||||
|
||||
if (!hasOwnProperty.call(to, key) || !isObject(val))
|
||||
to[key] = val
|
||||
|
||||
else
|
||||
// eslint-disable-next-line unicorn/new-for-builtins
|
||||
to[key] = deepAssign(Object(to[key]), val)
|
||||
}
|
||||
|
||||
export function deepAssign(to: ObjectIndex, from: ObjectIndex): ObjectIndex {
|
||||
Object.keys(from).forEach((key) => {
|
||||
assignKey(to, from, key)
|
||||
})
|
||||
|
||||
return to
|
||||
}
|
||||
|
||||
export function omit(obj: Record<string, unknown>, keys: string[]) {
|
||||
if (Object.prototype.toString.call(obj) === '[object Object]')
|
||||
return obj
|
||||
|
||||
return Object.keys(obj).reduce((prev, key) => {
|
||||
if (!keys.includes(key))
|
||||
prev[key] = obj[key]
|
||||
|
||||
return prev
|
||||
}, {} as Record<string, unknown>)
|
||||
}
|
||||
|
||||
export interface Deferred<T> extends Promise<T> {
|
||||
resolve: (value?: T) => void
|
||||
reject: (value?: any) => void
|
||||
}
|
||||
|
||||
export function createDeferred<T>(): Deferred<T> {
|
||||
let resolve: Deferred<T>['resolve'] = noop
|
||||
let reject: Deferred<T>['reject'] = noop
|
||||
const promise = new Promise((_resolve, _reject) => {
|
||||
resolve = _resolve
|
||||
reject = _reject
|
||||
}) as unknown as Deferred<T>
|
||||
|
||||
promise.resolve = resolve
|
||||
promise.reject = reject
|
||||
return promise
|
||||
}
|
||||
|
||||
export function toArray<T>(value?: T | T[]): T[] {
|
||||
if (!value)
|
||||
return []
|
||||
return Array.isArray(value) ? value : [value]
|
||||
}
|
||||
|
||||
export function noop() { }
|
||||
|
||||
export function getRandomId() {
|
||||
return Math.random().toString(36).slice(-8)
|
||||
}
|
||||
|
||||
export function isLooseEqual(a: any, b: any): boolean {
|
||||
if (a === b)
|
||||
return true
|
||||
|
||||
const isObjectA = isObject(a)
|
||||
const isObjectB = isObject(b)
|
||||
|
||||
if (isObjectA && isObjectB)
|
||||
return JSON.stringify(a) === JSON.stringify(b)
|
||||
else if (!isObjectA && !isObjectB)
|
||||
return String(a) === String(b)
|
||||
else
|
||||
return false
|
||||
}
|
||||
|
||||
export function isEqualArray(a: any, b: any): boolean {
|
||||
if (a === b)
|
||||
return true
|
||||
|
||||
if (!isArray(a) || !isArray(b))
|
||||
return false
|
||||
|
||||
if (a.length !== b.length)
|
||||
return false
|
||||
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (!isLooseEqual(a[i], b[i]))
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
export function isEqualValue(a: any, b: any): boolean {
|
||||
if (a === b)
|
||||
return true
|
||||
|
||||
if (isArray(a) && isArray(b))
|
||||
return isEqualArray(a, b)
|
||||
|
||||
return isLooseEqual(a, b)
|
||||
}
|
||||
|
||||
export function cloneDeep<T = any>(obj: T, cache = new WeakMap()): T {
|
||||
if (obj === null || typeof obj !== 'object')
|
||||
return obj
|
||||
if (cache.has(obj))
|
||||
return cache.get(obj)
|
||||
let clone
|
||||
if (obj instanceof Date) {
|
||||
clone = new Date(obj.getTime())
|
||||
}
|
||||
else if (obj instanceof RegExp) {
|
||||
clone = new RegExp(obj)
|
||||
}
|
||||
else if (obj instanceof Map) {
|
||||
clone = new Map(Array.from(obj, ([key, value]) => [key, cloneDeep(value, cache)]))
|
||||
}
|
||||
else if (obj instanceof Set) {
|
||||
clone = new Set(Array.from(obj, value => cloneDeep(value, cache)))
|
||||
}
|
||||
else if (Array.isArray(obj)) {
|
||||
clone = obj.map(value => cloneDeep(value, cache))
|
||||
}
|
||||
else if (Object.prototype.toString.call(obj) === '[object Object]') {
|
||||
clone = Object.create(Object.getPrototypeOf(obj))
|
||||
cache.set(obj, clone)
|
||||
for (const [key, value] of Object.entries(obj))
|
||||
clone[key] = cloneDeep(value, cache)
|
||||
}
|
||||
else {
|
||||
clone = Object.assign({}, obj)
|
||||
}
|
||||
cache.set(obj, clone)
|
||||
return clone
|
||||
}
|
||||
167
uni_modules/nutui-uni/components/_utils/date.ts
Normal file
167
uni_modules/nutui-uni/components/_utils/date.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* 时间戳转换 或 获取当前时间的时间戳
|
||||
*/
|
||||
export function getTimeStamp(timeStr?: string | number) {
|
||||
if (!timeStr)
|
||||
return Date.now()
|
||||
let t = timeStr
|
||||
t = (t as number > 0) ? +t : t.toString().replace(/-/g, '/')
|
||||
return new Date(t).getTime()
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为闫年
|
||||
* @return {Boolse} true|false
|
||||
*/
|
||||
export function isLeapYear(y: number): boolean {
|
||||
return (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回星期数
|
||||
* @return {string}
|
||||
*/
|
||||
export function getWhatDay(year: number, month: number, day: number): string {
|
||||
const date = new Date(`${year}/${month}/${day}`)
|
||||
const index = date.getDay()
|
||||
const dayNames = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
||||
return dayNames[index]
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回星期数
|
||||
* @return {number}
|
||||
*/
|
||||
export function getMonthPreDay(year: number, month: number): number {
|
||||
const date = new Date(`${year}/${month}/01`)
|
||||
let day = date.getDay()
|
||||
if (day === 0)
|
||||
day = 7
|
||||
|
||||
return day
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回月份天数
|
||||
* @return {number}
|
||||
*/
|
||||
export function getMonthDays(year: string, month: string): number {
|
||||
if (month.startsWith('0'))
|
||||
month = month.split('')[1]
|
||||
|
||||
return ([0, 31, isLeapYear(Number(year)) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] as number[])[
|
||||
month as any
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* 补齐数字位数
|
||||
* @return {string}
|
||||
*/
|
||||
export function getNumTwoBit(n: number): string {
|
||||
n = Number(n)
|
||||
return (n > 9 ? '' : '0') + n
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期对象转成字符串
|
||||
* @return {string}
|
||||
*/
|
||||
export function date2Str(date: Date, split?: string): string {
|
||||
split = split || '-'
|
||||
const y = date.getFullYear()
|
||||
const m = getNumTwoBit(date.getMonth() + 1)
|
||||
const d = getNumTwoBit(date.getDate())
|
||||
return [y, m, d].join(split)
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回日期格式字符串
|
||||
* @param i 0返回今天的日期、1返回明天的日期,2返回后天得日期,依次类推
|
||||
* @return {string} '2014-12-31'
|
||||
*/
|
||||
export function getDay(i: number): string {
|
||||
i = i || 0
|
||||
let date = new Date()
|
||||
const diff = i * (1000 * 60 * 60 * 24)
|
||||
date = new Date(date.getTime() + diff)
|
||||
return date2Str(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间比较
|
||||
* @return {boolean}
|
||||
*/
|
||||
export function compareDate(date1: string, date2: string): boolean {
|
||||
const startTime = new Date(date1.replace('-', '/').replace('-', '/'))
|
||||
const endTime = new Date(date2.replace('-', '/').replace('-', '/'))
|
||||
if (startTime >= endTime)
|
||||
return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间是否相等
|
||||
* @return {boolean}
|
||||
*/
|
||||
export function isEqual(date1: string, date2: string): boolean {
|
||||
const startTime = new Date(date1).getTime()
|
||||
const endTime = new Date(date2).getTime()
|
||||
if (startTime === endTime)
|
||||
return true
|
||||
|
||||
return false
|
||||
}
|
||||
export function getMonthWeek(year: string, month: string, date: string, firstDayOfWeek = 0): number {
|
||||
const dateNow = new Date(Number(year), Number.parseInt(month) - 1, Number(date))
|
||||
let w = dateNow.getDay() // 星期数
|
||||
const d = dateNow.getDate()
|
||||
let remainder = 6 - w
|
||||
if (firstDayOfWeek !== 0) {
|
||||
w = w === 0 ? 7 : w
|
||||
remainder = 7 - w
|
||||
}
|
||||
return Math.ceil((d + remainder) / 7)
|
||||
}
|
||||
export function getYearWeek(year: string, month: string, date: string): number {
|
||||
const dateNow = new Date(Number(year), Number.parseInt(month) - 1, Number(date))
|
||||
const dateFirst = new Date(Number(year), 0, 1)
|
||||
const dataNumber = Math.round((dateNow.valueOf() - dateFirst.valueOf()) / 86400000)
|
||||
return Math.ceil((dataNumber + (dateFirst.getDay() + 1 - 1)) / 7)
|
||||
}
|
||||
export function getWeekDate(year: string, month: string, date: string, firstDayOfWeek = 0): string[] {
|
||||
const dateNow = new Date(Number(year), Number.parseInt(month) - 1, Number(date))
|
||||
const nowTime = dateNow.getTime()
|
||||
let day = dateNow.getDay()
|
||||
if (firstDayOfWeek === 0) {
|
||||
const oneDayTime = 24 * 60 * 60 * 1000
|
||||
// 显示周日
|
||||
const SundayTime = nowTime - day * oneDayTime // 本周的周日
|
||||
// 显示周六
|
||||
const SaturdayTime = nowTime + (6 - day) * oneDayTime // 本周的周六
|
||||
|
||||
const sunday = date2Str(new Date(SundayTime))
|
||||
const saturday = date2Str(new Date(SaturdayTime))
|
||||
return [sunday, saturday]
|
||||
}
|
||||
else {
|
||||
day = day === 0 ? 7 : day
|
||||
const oneDayTime = 24 * 60 * 60 * 1000
|
||||
// 显示周一
|
||||
const MondayTime = nowTime - (day - 1) * oneDayTime // 本周的周一
|
||||
// 显示周日
|
||||
const SundayTime = nowTime + (7 - day) * oneDayTime // 本周的周日
|
||||
|
||||
const monday = date2Str(new Date(MondayTime))
|
||||
const sunday = date2Str(new Date(SundayTime))
|
||||
return [monday, sunday]
|
||||
}
|
||||
}
|
||||
export function formatResultDate(date: string) {
|
||||
const days = [...date.split('-')]
|
||||
days[2] = getNumTwoBit(Number(days[2]))
|
||||
days[3] = `${days[0]}-${days[1]}-${days[2]}`
|
||||
days[4] = getWhatDay(+days[0], +days[1], +days[2])
|
||||
return days
|
||||
}
|
||||
100
uni_modules/nutui-uni/components/_utils/env.ts
Normal file
100
uni_modules/nutui-uni/components/_utils/env.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
/** 枚举EPlatform */
|
||||
enum EPlatform {
|
||||
/** App */
|
||||
AppPlus = 'APP-PLUS',
|
||||
/** App nvue */
|
||||
AppPlusNvue = 'APP-PLUS-NVUE',
|
||||
/** H5 */
|
||||
H5 = 'H5',
|
||||
/** 微信小程序 */
|
||||
MpWeixin = 'MP-WEIXIN',
|
||||
/** 支付宝小程序 */
|
||||
MpAlipay = 'MP-ALIPAY',
|
||||
/** 百度小程序 */
|
||||
MpBaidu = 'MP-BAIDU',
|
||||
/** 字节跳动小程序 */
|
||||
MpToutiao = 'MP-TOUTIAO',
|
||||
/** QQ小程序 */
|
||||
MpQq = 'MP-QQ',
|
||||
/** 360小程序 */
|
||||
Mp360 = 'MP-360',
|
||||
/** 微信小程序/支付宝小程序/百度小程序/字节跳动小程序/QQ小程序/360小程序 */
|
||||
Mp = 'MP',
|
||||
/** 快应用通用(包含联盟、华为) */
|
||||
QuickappWebview = 'quickapp-webview',
|
||||
/** 快应用联盟 */
|
||||
QuickappWebviewUnion = 'quickapp-webview-union',
|
||||
/** 快应用华为 */
|
||||
QuickappWebviewHuawei = 'quickapp-webview-huawei',
|
||||
}
|
||||
|
||||
/** 使用条件编译获取平台信息 */
|
||||
function ifDefPlatform(): EPlatform {
|
||||
let platform: EPlatform
|
||||
// #ifdef APP-PLUS
|
||||
platform = EPlatform.AppPlus
|
||||
// #endif
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
platform = EPlatform.AppPlusNvue
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
platform = EPlatform.H5
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
platform = EPlatform.MpWeixin
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
platform = EPlatform.MpAlipay
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU
|
||||
platform = EPlatform.MpBaidu
|
||||
// #endif
|
||||
// #ifdef MP-TOUTIAO
|
||||
platform = EPlatform.MpToutiao
|
||||
// #endif
|
||||
// #ifdef MP-QQ
|
||||
platform = EPlatform.MpQq
|
||||
// #endif
|
||||
// #ifdef MP-360
|
||||
platform = EPlatform.Mp360
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
platform = EPlatform.Mp
|
||||
// #endif
|
||||
// #ifdef quickapp-webview
|
||||
platform = EPlatform.QuickappWebview
|
||||
// #endif
|
||||
// #ifdef quickapp-webview-union
|
||||
platform = EPlatform.QuickappWebviewUnion
|
||||
// #endif
|
||||
// #ifdef quickapp-webview-huawei
|
||||
platform = EPlatform.QuickappWebviewHuawei
|
||||
// #endif
|
||||
return platform
|
||||
}
|
||||
|
||||
/** 平台类型 */
|
||||
export const platform: EPlatform = ifDefPlatform()
|
||||
|
||||
/** H5 */
|
||||
export const isH5 = platform === EPlatform.H5
|
||||
/** 微信小程序 */
|
||||
export const isMpWeixin = platform === EPlatform.MpWeixin
|
||||
/** 支付宝小程序 */
|
||||
export const isMpAlipay = platform === EPlatform.MpAlipay
|
||||
/** 百度小程序 */
|
||||
export const isMpBaidu = platform === EPlatform.MpBaidu
|
||||
/** 字节跳动小程序 */
|
||||
export const isMpToutiao = platform === EPlatform.MpToutiao
|
||||
/** QQ小程序 */
|
||||
export const isMpQq = platform === EPlatform.MpQq
|
||||
/** 360小程序 */
|
||||
export const isMp360 = platform === EPlatform.Mp360
|
||||
/** 微信小程序/支付宝小程序/百度小程序/字节跳动小程序/QQ小程序/360小程序 */
|
||||
export const isMp = platform === EPlatform.Mp
|
||||
/** 快应用通用(包含联盟、华为) */
|
||||
export const isQuickappWebview = platform === EPlatform.QuickappWebview
|
||||
/** 快应用联盟 */
|
||||
export const isQuickappWebviewUnion = platform === EPlatform.QuickappWebviewUnion
|
||||
/** 快应用华为 */
|
||||
export const isQuickappWebviewHuawei = platform === EPlatform.QuickappWebviewHuawei
|
||||
9
uni_modules/nutui-uni/components/_utils/index.ts
Normal file
9
uni_modules/nutui-uni/components/_utils/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export * from './common'
|
||||
export * from './date'
|
||||
export * from './env'
|
||||
export * from './interceptor'
|
||||
export * from './is'
|
||||
export * from './props'
|
||||
export * from './pxCheck'
|
||||
export * from './raf'
|
||||
export * from './style'
|
||||
37
uni_modules/nutui-uni/components/_utils/interceptor.ts
Normal file
37
uni_modules/nutui-uni/components/_utils/interceptor.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { isPromise } from './is'
|
||||
|
||||
export type Interceptor = (...args: any[]) => Promise<boolean> | boolean | undefined | void
|
||||
|
||||
export function funInterceptor(interceptor: Interceptor | undefined, {
|
||||
args = [],
|
||||
done,
|
||||
canceled,
|
||||
}: {
|
||||
args?: unknown[]
|
||||
done: (val?: any) => void
|
||||
canceled?: () => void
|
||||
}) {
|
||||
if (interceptor) {
|
||||
const returnVal = interceptor(null, ...args)
|
||||
|
||||
if (isPromise(returnVal)) {
|
||||
returnVal
|
||||
.then((value) => {
|
||||
if (value)
|
||||
done(value)
|
||||
else if (canceled)
|
||||
canceled()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
else if (returnVal) {
|
||||
done()
|
||||
}
|
||||
else if (canceled) {
|
||||
canceled()
|
||||
}
|
||||
}
|
||||
else {
|
||||
done()
|
||||
}
|
||||
}
|
||||
96
uni_modules/nutui-uni/components/_utils/is.ts
Normal file
96
uni_modules/nutui-uni/components/_utils/is.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
const toString = Object.prototype.toString
|
||||
|
||||
export function is(val: unknown, type: string) {
|
||||
return toString.call(val) === `[object ${type}]`
|
||||
}
|
||||
|
||||
export function isDef<T = unknown>(val?: T): val is T {
|
||||
return typeof val !== 'undefined'
|
||||
}
|
||||
|
||||
export function isUnDef<T = unknown>(val?: T): val is T {
|
||||
return !isDef(val)
|
||||
}
|
||||
|
||||
export function isObject(val: any): val is Record<any, any> {
|
||||
return val !== null && is(val, 'Object')
|
||||
}
|
||||
|
||||
export function isEmpty<T = unknown>(val: T): val is T {
|
||||
if (isArray(val) || isString(val))
|
||||
return val.length === 0
|
||||
|
||||
if (val instanceof Map || val instanceof Set)
|
||||
return val.size === 0
|
||||
|
||||
if (isObject(val))
|
||||
return Object.keys(val).length === 0
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function isDate(val: unknown): val is Date {
|
||||
return is(val, 'Date')
|
||||
}
|
||||
|
||||
export function isNull(val: unknown): val is null {
|
||||
return val === null
|
||||
}
|
||||
|
||||
export function isNullAndUnDef(val: unknown): val is null | undefined {
|
||||
return isUnDef(val) && isNull(val)
|
||||
}
|
||||
|
||||
export function isNullOrUnDef(val: unknown): val is null | undefined {
|
||||
return isUnDef(val) || isNull(val)
|
||||
}
|
||||
|
||||
export function isNumber(val: unknown): val is number {
|
||||
return is(val, 'Number')
|
||||
}
|
||||
|
||||
export function isPromise<T = any>(val: unknown): val is Promise<T> {
|
||||
return (
|
||||
is(val, 'Promise')
|
||||
|| ((isObject(val) || isFunction(val))
|
||||
&& isFunction((val as any).then)
|
||||
&& isFunction((val as any).catch))
|
||||
)
|
||||
}
|
||||
|
||||
export function isString(val: unknown): val is string {
|
||||
return is(val, 'String')
|
||||
}
|
||||
|
||||
export function isFunction(val: unknown): val is () => void {
|
||||
return typeof val === 'function'
|
||||
}
|
||||
|
||||
export function isBoolean(val: unknown): val is boolean {
|
||||
return is(val, 'Boolean')
|
||||
}
|
||||
|
||||
export function isRegExp(val: unknown): val is RegExp {
|
||||
return is(val, 'RegExp')
|
||||
}
|
||||
|
||||
export function isArray(val: any): val is Array<any> {
|
||||
return val && Array.isArray(val)
|
||||
}
|
||||
|
||||
export function isWindow(val: any): val is Window {
|
||||
return typeof window !== 'undefined' && is(val, 'Window')
|
||||
}
|
||||
|
||||
export function isElement(val: unknown): val is Element {
|
||||
return isObject(val) && !!val.tagName
|
||||
}
|
||||
|
||||
export function isMap(val: unknown): val is Map<any, any> {
|
||||
return is(val, 'Map')
|
||||
}
|
||||
|
||||
export function isUrl(path: string): boolean {
|
||||
const reg = /^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?/
|
||||
return reg.test(path)
|
||||
}
|
||||
83
uni_modules/nutui-uni/components/_utils/props.ts
Normal file
83
uni_modules/nutui-uni/components/_utils/props.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* prop type helpers
|
||||
* help us to write less code and reduce bundle size
|
||||
* copy from https://github.com/youzan/vant/blob/main/packages/vant/src/utils/props.ts
|
||||
*/
|
||||
import type { ExtractPropTypes, PropType, StyleValue } from 'vue'
|
||||
|
||||
export const unknownProp = null as unknown as PropType<unknown>
|
||||
|
||||
export const numericProp = [Number, String]
|
||||
|
||||
export const truthProp = {
|
||||
type: Boolean,
|
||||
default: true as const,
|
||||
}
|
||||
|
||||
export const nullableBooleanProp = {
|
||||
type: Boolean as PropType<boolean | undefined>,
|
||||
default: undefined,
|
||||
}
|
||||
|
||||
export function makeRequiredProp<T>(type: T) {
|
||||
return {
|
||||
type,
|
||||
required: true as const,
|
||||
}
|
||||
}
|
||||
|
||||
export function makeArrayProp<T>(defaultVal: T[] = []) {
|
||||
return {
|
||||
type: Array as PropType<T[]>,
|
||||
default: () => defaultVal,
|
||||
}
|
||||
}
|
||||
|
||||
export function makeObjectProp<T>(defaultVal: T) {
|
||||
return {
|
||||
type: Object as PropType<T>,
|
||||
default: () => defaultVal,
|
||||
}
|
||||
}
|
||||
|
||||
export function makeNumberProp<T>(defaultVal: T) {
|
||||
return {
|
||||
type: Number,
|
||||
default: defaultVal,
|
||||
}
|
||||
}
|
||||
|
||||
export function makeNumericProp<T>(defaultVal: T) {
|
||||
return {
|
||||
type: numericProp,
|
||||
default: defaultVal,
|
||||
}
|
||||
}
|
||||
|
||||
export function makeStringProp<T>(defaultVal: T) {
|
||||
return {
|
||||
type: String as unknown as PropType<T>,
|
||||
default: defaultVal,
|
||||
}
|
||||
}
|
||||
|
||||
export type ClassType = string | object | Array<ClassType>
|
||||
|
||||
export const commonProps = {
|
||||
/**
|
||||
* @description 自定义类名
|
||||
*/
|
||||
customClass: {
|
||||
type: [String, Object, Array] as PropType<ClassType>,
|
||||
default: '',
|
||||
},
|
||||
/**
|
||||
* @description 自定义样式
|
||||
*/
|
||||
customStyle: {
|
||||
type: [String, Object, Array] as PropType<StyleValue>,
|
||||
default: '',
|
||||
},
|
||||
}
|
||||
|
||||
export type CommonProps = ExtractPropTypes<typeof commonProps>
|
||||
3
uni_modules/nutui-uni/components/_utils/pxCheck.ts
Normal file
3
uni_modules/nutui-uni/components/_utils/pxCheck.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function pxCheck(value: string | number): string {
|
||||
return Number.isNaN(Number(value)) ? String(value) : `${value}px`
|
||||
}
|
||||
30
uni_modules/nutui-uni/components/_utils/raf.ts
Normal file
30
uni_modules/nutui-uni/components/_utils/raf.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
const _window = window as any
|
||||
|
||||
export const inBrowser = typeof window !== 'undefined'
|
||||
|
||||
function requestAniFrame() {
|
||||
if (typeof _window !== 'undefined') {
|
||||
return (
|
||||
_window.requestAnimationFrame
|
||||
|| _window.webkitRequestAnimationFrame
|
||||
|| function (callback: () => void) {
|
||||
_window.setTimeout(callback, 1000 / 60)
|
||||
}
|
||||
)
|
||||
}
|
||||
else {
|
||||
return function (callback: () => void) {
|
||||
setTimeout(callback, 1000 / 60)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function cancelRaf(id: number) {
|
||||
if (inBrowser)
|
||||
cancelAnimationFrame(id)
|
||||
|
||||
else
|
||||
clearTimeout(id)
|
||||
}
|
||||
|
||||
export default requestAniFrame()
|
||||
167
uni_modules/nutui-uni/components/_utils/style.ts
Normal file
167
uni_modules/nutui-uni/components/_utils/style.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
import type { CSSProperties } from 'vue'
|
||||
import { hyphenate } from './common'
|
||||
import { isArray, isEmpty, isNumber, isObject, isString } from './is'
|
||||
import type { CommonProps } from './props'
|
||||
|
||||
export type NormalizedStyle = Record<string, string | number>
|
||||
|
||||
const listDelimiterRE = /;(?![^(]*\))/g
|
||||
const propertyDelimiterRE = /:([\s\S]+)/
|
||||
const styleCommentRE = /\/\*.*?\*\//g
|
||||
|
||||
export function parseStringStyle(cssText: string): NormalizedStyle {
|
||||
const ret: NormalizedStyle = {}
|
||||
cssText
|
||||
.replace(styleCommentRE, '')
|
||||
.split(listDelimiterRE)
|
||||
.forEach((item) => {
|
||||
if (item) {
|
||||
const tmp = item.split(propertyDelimiterRE)
|
||||
tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim())
|
||||
}
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
export function stringifyStyle(styles: NormalizedStyle | string | undefined): string {
|
||||
let ret = ''
|
||||
if (!styles || isString(styles))
|
||||
return ret
|
||||
|
||||
for (const key in styles) {
|
||||
const value = styles[key]
|
||||
const normalizedKey = key.startsWith('--') ? key : hyphenate(key)
|
||||
if (isString(value) || typeof value === 'number') {
|
||||
// only render valid values
|
||||
ret += `${normalizedKey}:${value};`
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
export function getPx(value: string | number, unit = false) {
|
||||
if (isNumber(value))
|
||||
return unit ? `${value}px` : Number(value)
|
||||
|
||||
return unit ? `${Number.parseInt(value)}px` : Number.parseInt(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 样式转换
|
||||
* 对象转字符串,或者字符串转对象
|
||||
* @param {object | string} customStyle 需要转换的目标
|
||||
* @param {string} target 转换的目的,object-转为对象,string-转为字符串
|
||||
*/
|
||||
export function addStyle(customStyle: string | object, target = 'object') {
|
||||
// 字符串转字符串,对象转对象情形,直接返回
|
||||
if (
|
||||
isEmpty(customStyle)
|
||||
|| (typeof customStyle === 'object' && target === 'object')
|
||||
|| (target === 'string' && typeof customStyle === 'string')
|
||||
) {
|
||||
return customStyle
|
||||
}
|
||||
|
||||
// 字符串转对象
|
||||
if (target === 'object') {
|
||||
// 去除字符串样式中的两端空格(中间的空格不能去掉,比如padding: 20px 0如果去掉了就错了),空格是无用的
|
||||
customStyle = trim(customStyle)
|
||||
// 根据";"将字符串转为数组形式
|
||||
const styleArray = customStyle.split(';')
|
||||
const style: any = {}
|
||||
// 历遍数组,拼接成对象
|
||||
for (let i = 0; i < styleArray.length; i++) {
|
||||
// 'font-size:20px;color:red;',如此最后字符串有";"的话,会导致styleArray最后一个元素为空字符串,这里需要过滤
|
||||
if (styleArray[i]) {
|
||||
const item = styleArray[i].split(':')
|
||||
style[trim(item[0])] = trim(item[1])
|
||||
}
|
||||
}
|
||||
return style
|
||||
}
|
||||
// 这里为对象转字符串形式
|
||||
let string = ''
|
||||
for (const i in customStyle as any) {
|
||||
// 驼峰转为中划线的形式,否则css内联样式,无法识别驼峰样式属性名
|
||||
const key = i.replace(/([A-Z])/g, '-$1').toLowerCase()
|
||||
string += `${key}:${customStyle[i]};`
|
||||
}
|
||||
// 去除两端空格
|
||||
return trim(string)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 去除空格
|
||||
* @param str 需要去除空格的字符串
|
||||
* @param pos both(左右)|left|right|all 默认both
|
||||
*/
|
||||
export function trim(str: string, pos = 'both') {
|
||||
str = String(str)
|
||||
if (pos === 'both')
|
||||
return str.replace(/^\s+|\s+$/g, '')
|
||||
|
||||
if (pos === 'left')
|
||||
return str.replace(/^\s*/, '')
|
||||
|
||||
if (pos === 'right')
|
||||
return str.replace(/(\s*$)/g, '')
|
||||
|
||||
if (pos === 'all')
|
||||
return str.replace(/\s+/g, '')
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
export function normalizeStyle(value: unknown): NormalizedStyle | string | undefined {
|
||||
if (isArray(value)) {
|
||||
const res: NormalizedStyle = {}
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const item = value[i]
|
||||
const normalized = isString(item)
|
||||
? parseStringStyle(item)
|
||||
: (normalizeStyle(item) as NormalizedStyle)
|
||||
if (normalized) {
|
||||
for (const key in normalized) {
|
||||
if (!isEmpty(normalized[key]))
|
||||
res[key] = normalized[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
if (isString(value))
|
||||
return value
|
||||
|
||||
if (isObject(value))
|
||||
return value
|
||||
}
|
||||
|
||||
export function normalizeClass(value: unknown): string {
|
||||
let res = ''
|
||||
if (isString(value)) {
|
||||
res = value
|
||||
}
|
||||
else if (isArray(value)) {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const normalized = normalizeClass(value[i])
|
||||
if (normalized)
|
||||
res += `${normalized} `
|
||||
}
|
||||
}
|
||||
else if (isObject(value)) {
|
||||
for (const name in value) {
|
||||
if (value[name])
|
||||
res += `${name} `
|
||||
}
|
||||
}
|
||||
return res.trim()
|
||||
}
|
||||
|
||||
export function getMainClass(props: CommonProps, componentName: string, cls?: object) {
|
||||
return normalizeClass([props.customClass, { [componentName]: true }, cls])
|
||||
}
|
||||
|
||||
export function getMainStyle(props: CommonProps, style?: CSSProperties) {
|
||||
return stringifyStyle(normalizeStyle([props.customStyle, style]))
|
||||
}
|
||||
Reference in New Issue
Block a user