bin-ui
Version:
基于 vue2.6 / vue-cli3 的 UI 组件库
392 lines (351 loc) • 9.63 kB
JavaScript
const util = {}
/**
* @description 更新标题
* @param {String} title 标题
*/
util.title = function (title) {
window.document.title = title || 'bin-ui'
}
/**
* @description 打开新页面
* @param {String} url 地址
* @param target
*/
util.open = function (url, target = false) {
let a = document.createElement('a')
a.setAttribute('href', url)
if (target) {
a.setAttribute('target', '_blank')
}
a.setAttribute('id', 'b-link-temp')
document.body.appendChild(a)
a.click()
document.body.removeChild(document.getElementById('b-link-temp'))
}
/**
* @description 拷贝到剪切板
* @param {String} content 内容
*/
util.copy = function (content) {
return new Promise(resolve => {
let copyInput = document.createElement('textarea')
copyInput.value = content
copyInput.setAttribute('id', 'b-copy-temp')
document.body.appendChild(copyInput)
copyInput.select() // 选择对象
let result = document.execCommand('Copy') // 执行浏览器复制命令
copyInput.style.display = 'none'
document.body.removeChild(document.getElementById('b-copy-temp'))
resolve(result)
})
}
/**
* 时间格式化
* @param time
* @param cFormat
* @param weekArray
* @returns {*}
*/
util.parseTime = parseTime
/**
* 获取区间范围,如近一周,近三个月,后一个月等
* @param days 为负值时往前,正为之后的日期
* @param mode
* @returns {*}
*/
util.rangeTime = function (days, mode = '{y}-{m}-{d}') {
const startDate = new Date()
const endDate = new Date()
if (days < 0) {
startDate.setTime(startDate.getTime() + 3600 * 1000 * 24 * days)
} else {
endDate.setTime(endDate.getTime() + 3600 * 1000 * 24 * days)
}
const startDateStr = parseTime(startDate, mode)
const endDateStr = parseTime(endDate, mode)
return {
startDate,
endDate,
startDateStr,
endDateStr
}
}
function parseTime(time, cFormat = '{y}-{m}-{d} {h}:{i}:{s}', weekArray) {
if (arguments.length === 0) {
return null
}
let type = typeOf(time)
let date
switch (type) {
case 'date':
date = time
break
case 'number':
date = new Date(time)
break
case 'string':
date = new Date(time.replace(/-/g, '/'))
break
default:
return null
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
return cFormat.replace(/{([ymdhisa])+}/g, (result, key) => {
let value = formatObj[key]
if (key === 'a') {
if (weekArray && weekArray.length === 7) {
return weekArray[value]
}
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
if (result.length > 0 && value < 10) { // 补0
value = '0' + value
}
return value || 0
})
}
/**
* 节流函数,(限制函数的执行频率)返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行
*
* @param {function} func 回调函数
* @param {number} wait 表示时间窗口的间隔
* @param immediate 是否立即执行 true 则先调用,false不先调用
* @return {function} 返回客户调用函数
*/
export function throttle(func, wait, immediate) {
let timeoutID
let lastExec = 0
function wrapper() {
const self = this
const elapsed = Number(new Date()) - lastExec
const args = arguments
function clearExistingTimeout() {
if (timeoutID) {
clearTimeout(timeoutID)
}
}
function clear() {
timeoutID = undefined
}
function exec() {
lastExec = Number(new Date())
func.apply(self, args)
}
if (immediate && !timeoutID) {
exec()
}
clearExistingTimeout()
if (immediate === undefined && elapsed > wait) {
exec()
} else {
timeoutID = setTimeout(immediate ? clear : exec, immediate === undefined ? wait - elapsed : wait)
}
}
return wrapper
}
/**
* 防抖函数,(限制函数的执行频率) 保证再一系列调用时间内,只调用一次
*
* @param {function} func 回调函数
* @param {number} wait 表示时间窗口的间隔
* @return {function} 返回客户调用函数
*/
export function debounce(func, wait) {
return throttle(func, wait, false)
}
/**
* 洗牌函数
* @param arr 需要洗牌的数组
*/
util.shuffle = function (arr) {
let newArr = arr.slice()// 复制一个新数组
for (let i = 0; i < newArr.length; i++) {
let j = util.getRandomInt(0, i)// 在0-当前循环的位置随机一个位置做交换
let t = newArr[i]
newArr[i] = newArr[j]
newArr[j] = t
}
return newArr
}
/**
* 在某个区间随机一个整数
* @param min 最小值
* @param max 最大值
* @return {number}
*/
util.getRandomInt = function (min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
/**
* 清空回车换行符
* @param str
* @returns {*}
*/
util.replaceReturn = function (str) {
return str ? str.replace(/(↵)+|(\n)+|(\r\n)+/g, '') : ''
}
/**
* 返回一个水印canvas
*/
util.getWaterMark = function (str) {
let waterMarkText = str || 'water-mark'
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
canvas.width = canvas.height = 100
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.globalAlpha = 0.08
ctx.font = '20px Microsoft Yahei'
ctx.translate(50, 50)
ctx.rotate(-Math.PI / 4)
ctx.fillText(waterMarkText, 0, 0)
return canvas
}
util.deepClone = deepCopy
util.onOf = oneOf
util.typeOf = typeOf
// 判断是否是对象或数组
function isObject(obj) {
return typeof obj === 'object' && obj !== null
}
// 判定对象数组相等
export function isEqual(obj1, obj2) {
// 两个数据有任何一个不是对象或数组
if (!isObject(obj1) || !isObject(obj2)) {
// 值类型(注意:参与equal的一般不会是函数)
return obj1 === obj2
}
// 如果传的两个参数都是同一个对象或数组
if (obj1 === obj2) {
return true
}
// 两个都是对象或数组,而且不相等
// 1.先比较obj1和obj2的key的个数,是否一样
const obj1Keys = Object.keys(obj1)
const obj2Keys = Object.keys(obj2)
if (obj1Keys.length !== obj2Keys.length) {
return false
}
// 如果key的个数相等,就是第二步
// 2.以obj1为基准,和obj2依次递归比较
for (let key in obj1) {
// 比较当前key的value --- 递归
const res = isEqual(obj1[key], obj2[key])
if (!res) {
return false
}
}
// 3.全相等
return true
}
// 一个值是否在列表中
export function oneOf(value, validList) {
return validList.indexOf(value) > -1
}
// Find components upward
export function findComponentUpward(context, componentName, componentNames) {
if (typeof componentName === 'string') {
componentNames = [componentName]
} else {
componentNames = componentName
}
let parent = context.$parent
let name = parent.$options.name
while (parent && (!name || componentNames.indexOf(name) < 0)) {
parent = parent.$parent
if (parent) name = parent.$options.name
}
return parent
}
// Find component downward
export function findComponentDownward(context, componentName) {
const childrens = context.$children
let children = null
if (childrens.length) {
for (const child of childrens) {
const name = child.$options.name
if (name === componentName) {
children = child
break
} else {
children = findComponentDownward(child, componentName)
if (children) break
}
}
}
return children
}
// Find components downward
export function findComponentsDownward(context, componentName) {
return context.$children.reduce((components, child) => {
if (child.$options.name === componentName) components.push(child)
const foundChilds = findComponentsDownward(child, componentName)
return components.concat(foundChilds)
}, [])
}
// Find components upward
export function findComponentsUpward(context, componentName) {
let parents = []
const parent = context.$parent
if (parent) {
if (parent.$options.name === componentName) parents.push(parent)
return parents.concat(findComponentsUpward(parent, componentName))
} else {
return []
}
}
// Find brothers components
export function findBrothersComponents(context, componentName, exceptMe = true) {
let res = context.$parent.$children.filter(item => {
return item.$options.name === componentName
})
let index = res.findIndex(item => item._uid === context._uid)
if (exceptMe) res.splice(index, 1)
return res
}
function typeOf(obj) {
const toString = Object.prototype.toString
const map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object'
}
return map[toString.call(obj)]
}
export function deepCopy(data) {
const t = typeOf(data)
let o
if (t === 'array') {
o = []
} else if (t === 'object') {
o = {}
} else {
return data
}
if (t === 'array') {
for (let i = 0; i < data.length; i++) {
o.push(deepCopy(data[i]))
}
} else if (t === 'object') {
for (let i in data) {
o[i] = deepCopy(data[i])
}
}
return o
}
export default util