函数防抖
// 频繁触发、耗时操作,只执行最后一次
const debounce = function (fn, delay = 300) {
let timer = null
return function (...args) {
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
// const debounceFn = debounce(fn)
深拷贝以及深拷贝的循环引用问题
const deepClone = val => {
const cache = new WeakMap()
const _deepClone = val => {
if (val === null || typeof val !== 'object') return val
if (cache.has(val)) return cache.get(val) // 使用缓存解决循环引用问题
const target = Array.isArray(val) ? [] : {}
cache.set(val, target)
for (let key in val) {
if (val.hasOwnProperty(key)) {
target[key] = _deepClone(val[key])
}
}
return target
}
return _deepClone(val)
}
// test
const obj = {
arr: [1, 2, 3],
a: 4
}
obj.sub = obj
obj.arr.push(obj)
console.log(obj)
const obj2 = deepClone(obj)
console.log(obj2.arr !== obj.arr)
console.log(obj2.sub !== obj.sub)
console.log(obj2.arr[3] !== obj)
console.log(obj2.arr[3] === obj2)
避免过多的if..else逻辑
// const Condition = val => {
// if (val.startsWith('a')) {
// console.log('a---' + val)
// } else if (val.endsWith('b')) {
// console.log('b---' + val)
// } else if (val.includes('c')) {
// console.log('c---' + val)
// } else {
// console.log('其他---' + val)
// }
// }
const Condition2 = val => {
const map = [
[() => val.startsWith('a'), () => console.log('a---' + val)],
[() => val.endsWith('b'), () => console.log('b---' + val)],
[() => val.includes('c'), () => console.log('c---' + val)]
]
const target = map.find(m => m[0]())
if (target) {
target[1]()
} else {
console.log('其他---' + val)
}
}
参数归一化
// 以数据分组为例
const pepole = [
{ name: '张三', age: 20, sex: '女' },
{ name: '李四', age: 20, sex: '男' },
{ name: '王五', age: 22, sex: '男' },
{ name: '赵六', age: 22, sex: '女' },
{ name: '田七', age: 20, sex: '女' },
{ name: '周八', age: 22, sex: '男' }
]
const groupBy = (array, generateKey) => {
if (typeof generateKey === 'string') {
const key = generateKey
generateKey = item => item[key]
}
return array.reduce((acc, cur) => {
const group = generateKey(cur)
acc[group] = acc[group] || []
acc[group].push(cur)
return acc
}, {})
}
console.log(groupBy(pepole, 'sex'))
console.log(groupBy(pepole, 'age'))
console.log(groupBy(pepole, item => item.sex + ':' + item.age))
js封装进度执行动画
export const animation = (from, to, duration, callback) => {
const speed = (to - from) / duration
const start = Date.now()
const _run = () => {
const now = Date.now()
const progress = from + (now - start) * speed
if (progress > to) {
callback(to)
return cancelAnimationFrame(_run)
}
requestAnimationFrame(_run)
callback(parseInt(progress))
}
requestAnimationFrame(_run)
}
<template>
<div>{{ num }}</div>
<button @click="up">开始</button>
</template>
<script setup>
import { animation } from './animation'
const num = ref(100)
const up = () => {
animation(num.value, 200, 3000, val => (num.value = val))
}
</script>
使用 customRef 实现输入框防抖
export const debounceRef = (value, delay = 1000) => {
let timer
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(val) {
clearTimeout(timer)
timer = setTimeout(() => {
trigger()
value = val
}, delay)
}
}
})
}
<template>
<div class="container">
<input type="text" v-model="value" />
<div class="text">{{ value }}</div>
</div>
</template>
<script setup>
import { debounceRef } from './debounceRef'
const value = debounceRef('')
</script>
组件逐帧渲染
// 减少白屏时间,提升用户感知
export const useDefer = (maxCount = 100) => {
let frameCount = 0
let refId
const updateFrameCount = () => {
refId = requestAnimationFrame(() => {
frameCount++
if (frameCount > maxCount) {
return cancelAnimationFrame(refId)
}
updateFrameCount()
})
}
updateFrameCount()
return i => {
return frameCount >= i
}
}
<template>
<div class="container">
<div v-for="i in 100" :key="i">
<heavy-component v-if="defer(i)"></heavy-component>
</div>
</div>
</template>
<script setup>
import { useDefer } from './useDefer'
const defer = useDefer()
</script>
使用惰性函数
// 避免每次进行函数调用时都要进行if..else判断
// 以文本复制为例
export const creatCopyText = () => {
if (navigator.clipboard) {
return text => navigator.clipboard.writeText(text)
} else {
return text => {
const input = document.createElement('input')
input.setAttribute('value', text)
document.body.appendChild(input)
input.select()
document.execCommand('copy')
document.body.removeChild(input)
}
}
}
<template>
<div>{{ text }}</div>
<button @click="CopyText(text)">点击复制</button>
</template>
<script setup>
import { creatCopyText } from './inhertFn'
const CopyText = creatCopyText()
const text = ref('要复制的文本')
</script>
使用分时函数
// 总的执行时间不变,只提前了页面渲染时间,改变了用户感知
export const performChunk = (datas, comsumer) => {
// 使用了参数的归一化
if (typeof datas === 'number') {
datas = new Array(datas)
}
if (datas.length === 0) return
let i = 0
const _run = () => {
if (i === datas.length) return
requestIdleCallback(deadline => {
while (deadline.timeRemaining() > 0 && i < datas.length) {
comsumer(datas[i])
i++
}
_run()
})
}
_run()
}
<template>
<button @click="addNum">点击插入10w个数字</button>
<div v-for="i in arr" :key="i">{{ i }}</div>
</template>
<script setup>
import { performChunk } from './performChunk'
const datas = new Array(100000).fill(0).map((_, i) => i)
const arr = ref([])
const addNum = () => {
performChunk(datas, item => {
arr.value.push(item)
})
}
</script>
标签:const,log,val,console,js,return,obj,封装,高阶
From: https://www.cnblogs.com/19BigData/p/17550496.html