JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 11
  • Score
    100M100P100Q834F
  • License MIT

A scattered collection of utilities

Package Exports

  • kayran

Readme

kayran / 七零八碎工具函数合集

Installation

NPM


waitFor / 以优雅方式书写 await

Param

/**
 * @param {Promise} 需要包装的Promise
 * @returns {any[]} [0]为Promise.prototype.then返回的结果,[1]为Promise.prototype.catch返回的结果
 */
// 示例

import { waitFor } from 'kayran'

const [res] = await waitFor(new Promise((resolve, reject) => {
  resolve('res')
}))
console.log(res) // 'res'

const [, err] = await waitFor(new Promise((resolve, reject) => {
  reject('err')
}))
console.log(err) // 'err'

getMediaDuration / 获取音视频文件的时长

Param

/**
 * @param {File|string} 音视频url或二进制文件
 * @returns {Promise<number>} 时长 单位秒 四舍五入
 */
// 示例

import { getMediaDuration } from 'kayran'

getMediaDuration('https://xxx.mp4')

typeOf / 获取变量的精确类型

动机:原生js的typeof等类型检测手段都存在各种缺陷

Param

/**
 * @param {any} 需要判断的变量
 * @returns {string} 变量类型(全小写) 如string null undefined file...
 */
// 示例

import { typeOf } from 'kayran'

typeOf(1) // 'number'

isEllipsis / 判断dom是否触发溢出省略(text-overflow: ellipsis)

Param

/**
 * @param {Element} 需要判断的元素
 * @returns {boolean} 是否触发溢出省略
 */
// 示例

import { isEllipsis } from 'kayran'

isEllipsis(document.querySelector('.text'))

isEmpty & notEmpty / 判空 & 判非空

notEmpty() 等同于 !isEmpty()

Param

/**
 * @param {any} 需要判断的变量
 * @returns {boolean} 结果
 */
// 示例

import { isEmpty, notEmpty } from 'kayran'

isEmpty(0)  // false
isEmpty({}) // true
isEmpty([]) // true

jsonToFormData / json转FormData

Param

/**
 * @param {object} 需要转换的对象
 * @param {(value?: any, key?: any) => any} mapFn 每个属性会执行该回调函数,返回值为新的属性值
 * @returns {FormData} 转换后的FormData实例
 */
// 示例

import { jsonToFormData } from 'kayran'

const formData = jsonToFormData({
  a: 1
})

formData.get('a') // '1'
// 绑定到FormData上,像Array.from一样使用

import { jsonToFormData } from 'kayran'

if (FormData.from === undefined) {
  FormData.from = jsonToFormData
}

const formData = FormData.from({
  a: '1',
  b: '2'
})
// mapFn示例

import { jsonToFormData } from 'kayran'

const formData = jsonToFormData({
  a: 1
}, v => v + 1)

formData.get('a') // '2'

::: tip
回调函数的返回值为undefined时,该元素不会被添加到FormData实例中(类似filter效果)。 :::


pickDeepBy / lodash-pickBy的递归版本

Param

/**
 * @param {object} obj 原始对象
 * @param {(value?: any, key?: any) => boolean} predicate 每个属性都会调用的方法
 * @returns {object} 新的对象
 */
// 示例

import { pickDeepBy } from 'kayran'

pickDeepBy({
  a: 1,
  b: NaN
}, (v, k) => ![NaN, null, undefined].includes(v))

// { a: 1 }

pickDeepBy不会改变原始对象。


isSameOrigin / 判断是否同源

Param

/**
 * @param {string} url 需要判断的url
 * @returns {boolean}
 */
// 示例

import { isSameOrigin } from 'kayran'

isSameOrigin('www.google.com')

parseQueryString / 获取 url 中某个查询参数的值

Param

/**
 * 获取当前url某个查询参数的值
 * 支持微信公众号授权特例:授权后会重定向回来并在链接中加入一个code参数 但微信没有考虑hash路由的情况 所以获取这个code需要特殊处理
 * @param {object}
 *        {string} key 查询参数的key 如果为空 则返回查询参数映射的对象 可以解构使用
 *        {string} [mode='hash'] router模式 可选值'history'/'hash'
 *        {boolean} del 是否在url中删除该值(删除会引发页面刷新)
 * @returns {string|object} 查询参数中key对应的value / 如果key为空 则返回查询参数整个对象
 */
// 示例

import { parseQueryString } from 'kayran'

const code = parseQueryString('code')

//or

const { code } = parseQueryString()

注意:如果search和hash中同时包含code 如http://localhost:8080/?code=1#/?code=2 取的是search中的code 即返回1


Param

/**
 * @param {string|object} src link url
 * @returns {Promise}
 */
// 示例

import { loadLink } from 'kayran'

await loadLink('https://cdn.bootcdn.net/ajax/libs/normalize/8.0.1/normalize.min.css')

loadScript / 动态加载js

Param

/**
 * @param {string|object} src 脚本url
 * @returns {Promise}
 */
// 示例

import { loadScript } from 'kayran'

loadScript('https://cdn.jsdelivr.net/npm/vue/dist/vue.js').then(e => {
  console.log(Vue)
})

loadStyle / 动态加载style

Param

/**
 * @param {string|object|HTMLElement} arg style元素的innerText 或传对象指定style的各项属性 或style元素本身
 * @returns {Promise<HTMLElement>}
 */
// 示例

import { loadStyle } from 'kayran'

await loadStyle(`
ul {
  list-style: none;
}
`)

validator / 输入校验

Param

/**
 * @param {string} 需要校验的内容
 * @returns {string} 校验失败提示信息 如果校验通过则返回''
 */
// 示例

import { validator } from 'kayran'

const { idCard } = validator

const errMsg = idCard('xxx')

if (errMsg) {
  Toast(errMsg) // '格式不正确'
  return
}

该方法不是通过true和false来标识校验是否通过 因为错误往往需要一个友好的原因提示

// 如果仅仅想知道是否校验通过

!idCard('xxx') // true通过 false失败

lng / 经度

/**
 * @param {string|number} 需要判断的值
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { lng } = validator

lat / 纬度

/**
 * @param {string|number} 需要判断的值
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { lat } = validator

phone / 手机

/**
 * @param {string|number} 需要判断的值
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { phone } = validator

ipv4

/**
 * @param {string} 需要判断的值
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { ipv4 } = validator

ipv6

/**
 * @param {string} 需要判断的值
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { ipv6 } = validator

url

含ipv4 不含ipv6

/**
 * @param {string} 需要判断的值
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { url } = validator

base64

/**
 * @param {string} 需要判断的字符串
 * @param {object}
 *        {string} mediaType 媒体类型,可选值参考 https://en.wikipedia.org/wiki/Data_URI_scheme
 *        {boolean} [scheme=true] 是否包含前缀
 * @returns {boolean} 结果
 */

import { validator } from 'kayran'

const { base64 } = validator

base64(1, {
  mediaType: 'image',
  scheme: false
}) // false

idCard / 身份证

/**
 * @param {string|number} 需要判断的值
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { idCard } = validator

postcode / 邮编

/**
 * @param {string|number} 需要判断的值
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { postcode } = validator

tel / 座机

/**
 * @param {string|number} 需要判断的值
 * @param {object}
 *        {boolean} [multiple=true] 是否允许多个
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { tel } = validator

email / 邮箱

/**
 * @param {string} 需要判断的值
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { email } = validator

len / 字符长度

/**
 * @param {string} 需要判断的值
 * @param {
 *          number |
 *          [number, number] |
 *          {
 *            min?: number
 *            max?: number
 *          }
 *        }
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { len } = validator

len('123', [1, 3])

int / 整数

/**
 * @param {string|number} 需要判断的值
 * @param {
 *          string | 
 *          {
 *            range?: string
 *            positiveSign?: boolean
 *          }
 *        }
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { int } = validator

int(0, '(0,2)')

decimal / 小数

/**
 * @param {string|number} 需要判断的值
 * @param {
 *          string |
 *          {
 *            range?: string,
 *            decimalPlaces?: number | [number, number]
 *          }
 *        }
 * @returns {string} 判断结果
 */

import { validator } from 'kayran'
const { decimal } = validator

decimal(80, '[80,+∞]')

decimal('80.1', {
  decimalPlaces: [0, 1]
})

getFinalProp / 获取最终prop(适用于组件开发者)

Vue提供了prop的局部配置和默认值配置,但在封装组件时,还会非常需要一个“全局配置”,否则可能导致每个组件实例进行重复的配置。

举个例子,Element 的size与zIndex就是支持全局配置的。

当配置多了以后,由于存在不同的优先级,最终组件采用的是哪一项配置,需要进行一定的判断,

在涉及到对象时,判断可能会变得相当复杂。

getFinalProp的作用就是帮助你计算出最终的配置。

Features

  • 和Vue的props一样,提供是否必传、数据类型和自定义的校验
  • 对于plain object类型的prop,支持深合并、浅合并和直接覆盖
  • 支持将对象的键统一为驼峰命名,以避免引发某些bug
  • 支持动态生成默认值

Param

/**
 * @param {any[]} propSequence - prop序列(权重从高到低,最后是默认配置)
 * @param {object} config - 配置
 * @param {string} config.name - prop名称,用于报错提示
 * @param {string|string[]} config.type - 数据类型校验
 * @param {function} config.validator - 自定义校验
 * @param {boolean} config.required = false - 是否必传校验
 * @param {string} config.mergeObject = 'deep' - 合并对象的方式
 * @param {string} config.camelCase = true - 是否将对象的键统一为驼峰命名
 * @returns {any} 最终的prop
 */
// 示例

import { getFinalProp } from 'kayran'

getFinalProp([1, 2, undefined]) // 1

config.mergeObject

  • 'deep': 深合并,高权重prop的对象键会覆盖低权重prop的同名键,包含嵌套的对象(默认值)
  • 'shallow': 浅合并,高权重prop的对象键会覆盖低权重prop的同名键,不含嵌套的对象
  • false: 不合并,直接覆盖,高权重prop的对象会直接覆盖低权重prop的对象,与值类型的表现一致

config.camelCase

Vue的prop同时支持驼峰和短横线格式,如果用户同时传了同一个prop的两种格式,值还是不相同的,问题来了,此时应该取哪一个值?

在多个配置进行合并时,结果会更加难以预测,所以getFinalProp在合并对象后默认将对象的键统一为驼峰命名。

::: tip 为什么不默认使用短横线命名?
参见Vue官方风格指南 :::

怎么判断某个prop有没有传?

以该prop是否全等于undefined作为标识

动态生成默认值

使用场景:需要根据用户传的参数来决定默认值

用法:最后一个prop使用function类型,function的参数是前面所有prop的计算结果

// 示例

getFinalProp([{
  a: {
    a: 1
  }
}, {
  a: {
    a: 2,
    b: 1
  }
}, config => ({
  a: {
    c: config.a.a === 1 ? 1 : null
  }
})])

/**
 * 将得到:
 * {
 *   a: {
 *     a: 1,
 *     b: 1,
 *     c: 1
 *   }
 * }
 */

getGlobalAttrs / 获取全局attrs(适用于组件开发者)

在Vue组件中,声明过的prop可以通过 this.$props 获取,没有声明的可以通过 this.$attrs 获取,

但是全局配置就无法区分哪部分是props哪部分是attrs了。

getGlobalAttrs就是帮助你获取全局配置中的attrs的。

使用场景:二次封装组件时,往往需要使用 v-bind="$attrs" 来实现不破坏底层组件的原生能力,

getGlobalAttrs就是在此基础上提供全局配置的能力。

Param

/**
 * @param {object} globalConfig - 全局配置
 * @param {object} $props - this.$props(当前组件接收到的 props 对象)
 * @returns {object} globalAttrs - 全局配置中的attrs部分
 */
<!-- 示例 -->

<template>
  <某底层组件 v-bind="Attrs"/>
</template>

<script>
import { getFinalProp, getGlobalAttrs } from 'kayran'
import globalConfig from './config'

export default {
  computed: {
    // Attrs即为局部与全局attrs经过权重计算得到的结果
    Attrs () {
      return getFinalProp([
        this.$attrs,
        getGlobalAttrs(globalConfig, this.$props)
      ])
    }
  }
}
</script>