Object 序列化
export const paramString = (obj: any) => {
return Object.keys(obj).map(key => (`${key}=${obj[key]||''}`)).join('&')
}
web 本地存储修复
Storage.prototype.getItemFix = key => {
let value = null
try {
value = JSON.parse(localStorage.getItem(key))
} catch (error) {
value = localStorage.getItem(key)
}
if (['null', 'undefined'].includes(value)) return null
return value
}
自动注册异步组件
// 统一注册全局异步组件(业务组件 和 ui组件)
export default (Vue, options) => {
// require.context 中 mode 属性,default:async,默认会打包到app.js文件里;
// 可以使用 lazy 设置为 chunk module
const context = require.context('@/components/', false, /^p|v|ui+\.vue$/, 'lazy');
// 遍历获取组件对象,注册组件
context.keys().map(fileName => {
const componentname = fileName.replace("./", "").replace(".vue", "")
// 注意: 这里直接使用 ()=> import('path') 和 require 按需方式都不会生效
Vue.component(componentname, () => context(fileName))
})
}
图片懒加载的原理主要是判断当前图片是否到了可视区域这一核心逻辑实现的
getBoundingClientRect()
拿到所有的图片 dom 。
遍历每个图片判断当前图片(element.getBoundingClientRect().top)是否到了可视区范围(document.body.clientHeight)内。
如果到了就设置图片的 src 属性。
绑定 window 的 scroll 事件,对其进行节流事件监听。
IntersectionObserver
目标元素与视口产生一个交叉区,所以这个 API 叫做"交叉观察器"
var io = new IntersectionObserver(callback, option)
// 开始观察
io.observe(document.getElementById('example'))
// 停止观察
io.unobserve(element)
.target:被观察的目标元素,是一个 DOM 节点对象
.isIntersecting: 目标是否可见
let observer = new IntersectionObserver((entries, self) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
let img = entry.target
let src = img.dataset.src
if (src) {
img.src = src
img.removeAttribute('data-src')
}
// 解除观察
self.unobserve(entry.target)
}
})
}, config)
otehr js知识
// mixins.js 类。函数的装饰器
export function mixins(...list) {
return function (target) {
Object.assign(target.prototype, ...list)
}
}
// main.js
import { mixins } from './mixins.js'
const Foo = {
foo() { console.log('foo') }
};
@mixins(Foo)
class MyClass {}
let obj = new MyClass();
obj.foo() // 'foo'
// js (~-1 == 0)
// 把一维数组切割成每个元素包含指定长度二维数组
splitArray(a, size = 3) {
const arr = []
for (let i = 0; i < a.length; i += size) {
arr.push(a.slice(i, i + size))
}
console.log(arr)
}
// vuecli
config.optimization.runtimeChunk('single') // 更好的缓存app.js
config.optimization.minimize(true) // 代码压缩
/////////////////
input type=file accept=""时,
可解决ios/iphone上不能选择除图片外的其他文件问题。
// 快速清空数组
const ay = [1,2]
ay.length = 0
// 文件上传FormData
function upload(e = {}) {
const formData = new FormData()
const oFile = e.file // 文件对象
formData.append('file', oFile)
uploadImg(formData, {
fileName: oFile.name,
fileType: oFile.type
})
}
export function debounce(cb, delay) {
let timer = null
return function (...args) {
clearTimeout(timer)
timer = setTimeout(() => {
cb.apply(this, args)
}, delay)
}
}
export function throttle(cb, delay) {
let timer = null
return () => {
if (timer) return false
timer = setTimeout(e => {
timer = null
clearTimeout(timer)
cb && cb()
}, delay)
}
}
export function sum(n) {
if (n < 2) return n
return sum(n - 1) + n
}
export function tick(cb, delay = 1000 * 10) {
cb.timer = setInterval(() => {
cb && cb()
}, delay)
return cb.timer
}
export const touchEv = {
onTouchStart(cb) {
this.longClick = 0 // 初始化
this.timeOutEvent = setTimeout(() => {
this.longClick = 1 // 长按标志位
// 此处为长按事件逻辑
console.log('长按事件')
cb && cb()
}, 500) // 一般为300毫秒;浏览器默认时间
},
onTouchEnd() {
clearTimeout(this.timeOutEvent) // 清除计时器
if (this.timeOutEvent !== 0 && this.longClick === 0) {
// 判断是否非长按事件
// 此处为点击事件
console.log('点击事件')
}
}
}
export function deepCopy(data) {
const t = Object.prototype.toString.call(data)
let o = {}
const isObj = t.includes('Array') || t.includes('Object')
console.log(o)
if (isObj) {
o = t.includes('Array') ? [] : {}
} else {
return data
}
if (isObj) {
for (const i in data) {
o[i] = deepCopy(data[i])
console.log(o)
}
}
return o
}