延迟函数
const delay = ms => new Promise((resolve, reject) => setTimeout(resolve, ms))
async fn() {
const startTime = +new Date()
await delay(2000)
const endTime = +new Date()
// 考虑到JS单线程,真实值会略微大于延迟时间
console.log(startTime - endTime)
}
获取数组交集
const intersection = (list, ...args) => list.filter(item => args.every(list => list.includes(item)))
intersection([1, 4], [3, 4], [4, 5]) // [4]
intersection([1, 2], [3, 4]) // []
函数柯里化
const curring = fn => {
const { length } = fn
const curried = (...args) => {
return (args.length >= length
? fn(...args)
: (...args2) => curried(...args.concat(args2)))
}
return curried
}
const listMerge = (a, b, c) => [a, b, c]
const curried = curring(listMerge)
curried(1)(2)(3) // [1, 2, 3]
curried(1, 2)(3) // [1, 2, 3]
curried(1, 2, 3) // [1, 2, 3]
字符串前/后面空格去除与替换
// 去除前面空格
const trimStart = str => str.replace(new RegExp('^([\\s]*)(.*)$'), '$2')
// 去除后面空格
const trimEnd = str => str.replace(new RegExp('^(.*?)([\\s]*)$'), '$1')
trimStart(' abc ') // "abc "
trimEnd(' 123 ') // " 123"
获取当前子元素是其父元素下子元素的排位
const getIndex = el => {
if (!el) {
return -1
}
let index = 0
do {
index++
} while (el = el.previousElementSibling);
return index
}
判断是否是移动端
const isMobile = () => 'ontouchstart' in window
禁止网页复制粘贴
const html = document.querySelector('html')
html.oncopy = () => false
html.onpaste = () => false
去除字符串中的HTML代码
const removeHTML = (str = '') => str.replace(/<[\/\!]*[^<>]*>/ig, '')
自定义事件
事件本质是一种消息,事件模式本质上是观察者模式的实现,即能用观察者模式的地方,自然也能用事件模式。
目前自定义事件主要有两种方式实现:JS
原生的Event()
和 CustomEvent()
Event()
Event()
构造函数创建一个新的事件对象Event
let myEvent = new Event(typeArg, eventInit);
-
typeArg
DOMString
类型,表示创建事件的名称; -
eventInit
可选配置项;-
bubbles
该事件是否冒泡,默认false
-
cancelable
该事件能否被取消,默认false
-
composed
指示事件是否会在影子DOM
根节点之外触发侦听器,默认false
-
// 创建一个支持冒泡且不能被取消的 summer 事件
let myEvent = new Event("summer", {bubbles: true, cancelable: false});
// 注册summer事件
testDOM.addEventListener("summer", e => {
// 回调参数e 就是dispatchEvent分发的myEvent
console.log('summer 事件触发', e)
});
button.addEventListener("click", () => {
// 触发testDOM 上的summer事件
testDOM.dispatchEvent(myEvent);
});
CustomEvent()
CustomEvent()
构造函数创建一个新的事件对象CustomEvent
let myEvent = new CustomEvent(typeArg, eventInit);
-
typeArg
DOMString
类型,表示创建事件的名称; -
eventInit
可选配置项;-
detail
该事件中需要被传递的数据,在EventListener
获取,默认null
-
bubbles
该事件是否冒泡,默认false
-
cancelable
指该事件能否被取消,默认false
-
// 创建 spring 事件
let myEvent = new CustomEvent("spring", {
detail: { name: "CustomEvent" }
});
// 注册spring事件监听器
window.addEventListener("spring", e => {
alert(`spring事件触发,是 ${e.detail.name} 触发。`);
});
testDOM.addEventListener("click", () => {
// 派发事件,触发spring事件
window.dispatchEvent(myEvent);
})
还可以给自定义事件添加属性:
myEvent.age = 18;
IE8 兼容
分发事件时,需要使用 dispatchEvent
方法触发,它在 IE8
及以下版本中需要进行使用 fireEvent
方法兼容:
if(window.dispatchEvent) {
window.dispatchEvent(myEvent);
} else {
window.fireEvent(myEvent);
}
两者区别
从支持的参数可以看出:Event()
适合创建简单的自定义事件,而 CustomEvent()
支持参数传递的自定义事件,它支持 detail
参数,作为事件中需要被传递的数据,并在 EventListener
获取。
注意
- 当一个事件触发时,若相应的元素及其上级元素上都没有进行事件监听,则不会有回调操作执行;
- 当需要对子元素进行监听,可以在其父元素进行事件托管(
bubbles: true
),让事件在冒泡阶段被监听器捕获并执行,并使用event.target
获取到具体触发事件的元素。var myEvent = new Event("summer", { bubbles: true }); document.addEventListener("summer", ev => { console.log(ev.target) // testDOM }); button.addEventListener("click", () => { // 用document的子元素testDOM 去触发 summer事件 testDOM.dispatchEvent(myEvent); });
网友评论