Skip to main content

One post tagged with "dom"

View All Tags

· 3 min read
Swnb

3 个使用 @swnb/event 的理由

github

1. 简化 web 事件监听模型

react 里面, 有时候你不得不这么写来处理监听事件

example.tsx

_10
useEffect(() => {
_10
const callback = () => {}
_10
_10
target.addEventListner("event", callback)
_10
_10
return () => {
_10
target.removeEvenListner("event", callback)
_10
}
_10
}, [target])

如果你想要处理多个事件

example.tsx

_15
useEffect(() => {
_15
const callback1 = () => {}
_15
target.addEventListner("event1", callback1)
_15
_15
const callback2 = () => {}
_15
target.addEventListner("event2", callback2)
_15
_15
// ....
_15
_15
return () => {
_15
target.removeEvenListner("event1", callback1)
_15
target.removeEvenListner("event2", callback2)
_15
// ....
_15
}
_15
}, [target])

这太难受了

如果你使用 @swnb/event

example.tsx

_10
import { EventProxy } from "@swnb/event"
_10
useEffect(
_10
() =>
_10
EventProxy.new(target)
_10
.on("event1", (...args) => {}) // 支持类型提示 !!!
_10
.on("event2", (...args) => {}) // 支持类型提示 !!!
_10
.on("event3", (...args) => {}), // 支持类型提示 !!!
_10
[target]
_10
)

编程从来没有这么简单过

2. Promise support

考虑一个场景, 你要建立一个 websocket 连接, 并等待连接打开, 并设置最大连接时长, 考虑正确的释放资源, 你可能会写如下的代码

websocket.ts

_18
async function connect(url: string, timeout: number) {
_18
const ws = new WebSocket(url)
_18
_18
return new Promise<WebSocket>((res, rej) => {
_18
const timeID = setTimeout(() => {
_18
rej(new Error("timeout"))
_18
ws.removeEventListener("open", onOpen)
_18
}, timeout)
_18
_18
function onOpen() {
_18
res(ws)
_18
clearTimeout(timeID)
_18
ws.removeEventListener("open", onOpen)
_18
}
_18
_18
ws.addEventListener("open", onOpen)
_18
})
_18
}

实在是太烦人了

如果你使用 @swnb/event

websocket.ts

_10
import { EventProxy } from "@swnb/event"
_10
_10
async function connect(url: string, timeout: number) {
_10
const ws = new WebSocket(url)
_10
_10
await EventProxy.new(ws).waitUtil("open", { timeout }) // 支持类型提示 !
_10
_10
return ws
_10
}

编程从来没有这么简单过

考虑一个更加复杂的场景, 创建一个 webrtc 连接, 等待连接 connected

rtc.ts

_12
import { EventProxy } from "@swnb/event"
_12
_12
async function connect(timeout: number) {
_12
const connection = new RTCPeerConnection()
_12
_12
await EventProxy.new(connection).waitUtil("connectionstatechange", {
_12
timeout,
_12
where: (ev) => connection.connectionState === "connected",
_12
})
_12
_12
return connection
_12
}

使用 where 可以选择你想要的那个 connectionState

3. 观察一个 web 对象的所有事件

如果你想知道 video 在播放的时候触发了哪些事件, 可以考虑这么写

video.ts

_10
import { EventProxy } from "@swnb/event"
_10
// 支持类型提示 !
_10
EventProxy.new(videoDom, { proxyAllEvent: true }).any((eventName, ...args) => {
_10
console.log(eventName)
_10
})

放在 react 里面可以这么写

video.tsx

_15
import { EventProxy } from "@swnb/event"
_15
import { useEffect, useRef } from "react"
_15
_15
function Video() {
_15
const videoDomRef = useRef<HTMLVideoElement>(null)
_15
useEffect(() => {
_15
return EventProxy.new(videoDomRef.current!, { proxyAllEvent: true }).any((eventName, ...args) => {
_15
console.log(eventName)
_15
})
_15
}, [])
_15
_15
const url = "" // 你的 video 链接
_15
_15
return <video muted autoPlay src={url} ref={videoDomRef} />
_15
}

打开控制台, 你会看到所有 video 的事件触发顺序和时间

编程从来没有这么简单过