Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
|
427ed9399f | 3 weeks ago |
16 changed files with 306 additions and 190 deletions
@ -1,51 +1,87 @@ |
|||||
// type FireKey = string
|
// 从完整事件名称中提取原始事件名称(移除作用域前缀)
|
||||
|
type ExtractOriginalEventName<T extends string, S extends string> = T extends `${S}:${infer Original}` ? Original : never |
||||
|
|
||||
|
// 从完整事件映射中提取原始事件映射
|
||||
|
type ExtractBaseEventMaps<T extends Record<string, any>, S extends string> = { |
||||
|
[K in keyof T as ExtractOriginalEventName<K & string, S>]: T[K] |
||||
|
} |
||||
|
|
||||
type FireFN = (...argu: any[]) => void |
type FireFN = (...argu: any[]) => void |
||||
|
|
||||
class FireEvent<T extends Record<string | symbol, FireFN>> { |
// 支持作用域的事件类
|
||||
#events: Record<keyof T, FireFN[]> = {} as any |
class ScopedFireEvent< |
||||
|
T extends Record<string, FireFN>, // 完整的事件映射类型
|
||||
|
S extends string, // 作用域类型
|
||||
|
B extends Record<string, FireFN> = ExtractBaseEventMaps<T, S>, // 从完整事件映射中提取的基础事件映射
|
||||
|
> { |
||||
|
#scope: S |
||||
|
#events: Record<string, FireFN[]> = {} |
||||
|
|
||||
|
constructor(scope: S) { |
||||
|
this.#scope = scope |
||||
|
} |
||||
|
|
||||
|
// 获取完整的事件名称(添加作用域前缀)
|
||||
|
public getFullEventName(eventName: string): string { |
||||
|
if (this.#scope === "") return eventName |
||||
|
return `${this.#scope}:${eventName}` |
||||
|
} |
||||
|
|
||||
print() { |
print() { |
||||
Object.keys(this.#events).forEach(key => { |
Object.keys(this.#events).forEach(key => { |
||||
console.log(`${key}: ${this.#events[key]}\n`) |
console.log(`${key}: ${this.#events[key]}\n`) |
||||
}) |
}) |
||||
} |
} |
||||
on<S extends keyof T>(name: S, fn: T[S]) { |
|
||||
if (!this.#events[name]) { |
// 订阅事件,支持自动添加作用域前缀
|
||||
this.#events[name] = [] |
on<K extends keyof B>(name: K, fn: B[K]) { |
||||
|
const fullName = this.getFullEventName(name as string) |
||||
|
if (!this.#events[fullName]) { |
||||
|
this.#events[fullName] = [] |
||||
} |
} |
||||
this.#events[name].push(fn) |
this.#events[fullName].push(fn as FireFN) |
||||
} |
} |
||||
emit<S extends keyof T>(name: S, ...argu: Parameters<T[S]>) { |
|
||||
if (this.#events[name]) { |
// 触发事件,支持自动添加作用域前缀
|
||||
this.#events[name].forEach(fn => { |
emit<K extends keyof B>(name: K, ...argu: Parameters<B[K]>) { |
||||
|
const fullName = this.getFullEventName(name as string) |
||||
|
if (this.#events[fullName]) { |
||||
|
this.#events[fullName].forEach(fn => { |
||||
fn(...argu) |
fn(...argu) |
||||
}) |
}) |
||||
} |
} |
||||
} |
} |
||||
off<S extends keyof T>(name: S, fn?: T[S]) { |
|
||||
const len = this.#events[name].length |
// 取消订阅事件,支持自动添加作用域前缀
|
||||
|
off<K extends keyof B>(name: K, fn?: B[K]) { |
||||
|
const fullName = this.getFullEventName(name as string) |
||||
|
const len = this.#events[fullName]?.length || 0 |
||||
if (!len) { |
if (!len) { |
||||
return |
return |
||||
} |
} |
||||
if (!fn) { |
if (!fn) { |
||||
this.#events[name] = [] |
this.#events[fullName] = [] |
||||
} else { |
} else { |
||||
for (let i = len - 1; i >= 0; i--) { |
for (let i = len - 1; i >= 0; i--) { |
||||
const _fn = this.#events[name][i] |
const _fn = this.#events[fullName][i] |
||||
if (_fn === fn) { |
if (_fn === fn) { |
||||
this.#events[name].splice(i, 1) |
this.#events[fullName].splice(i, 1) |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
once<S extends keyof T>(name: S, fn: T[S]) { |
|
||||
const _fn: any = (...argu: any[]) => { |
// 一次性订阅事件,支持自动添加作用域前缀
|
||||
|
once<K extends keyof B>(name: K, fn: B[K]) { |
||||
|
const _fn: FireFN = (...argu: any[]) => { |
||||
fn(...argu) |
fn(...argu) |
||||
this.off<S>(name, _fn) |
this.off(name, _fn as B[K]) |
||||
} |
} |
||||
this.on(name, _fn) |
this.on(name, _fn as B[K]) |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
export function buildEmitter<T extends Record<string | symbol, FireFN>>() { |
// 创建作用域事件发射器的工厂函数 - 仅需一个泛型参数
|
||||
return new FireEvent<T>() |
export function buildEmitter<T extends Record<string | symbol, FireFN>>(scope?: string): ScopedFireEvent<T, typeof scope> { |
||||
|
return new ScopedFireEvent<T, typeof scope>(scope) |
||||
} |
} |
||||
|
@ -1,3 +0,0 @@ |
|||||
export type EventMaps = { |
|
||||
"update-progress": (data: { percent: number; all: number; now: number }) => void |
|
||||
} |
|
@ -0,0 +1,16 @@ |
|||||
|
export const EventScope = "updater" as const |
||||
|
|
||||
|
// 原始事件映射类型
|
||||
|
export type BaseEventMaps = { |
||||
|
"download-progress": (data: { percent: number; all: number; now: number }) => void |
||||
|
error: () => void |
||||
|
"checking-for-update": () => void |
||||
|
"update-available": () => void |
||||
|
"update-not-available": () => void |
||||
|
"update-downloaded": () => void |
||||
|
} |
||||
|
|
||||
|
// 将 EventScope 添加到所有事件名称前缀
|
||||
|
export type EventMaps = { |
||||
|
[K in keyof BaseEventMaps as `${typeof EventScope}:${K}`]: BaseEventMaps[K] |
||||
|
} |
@ -1,6 +1,6 @@ |
|||||
import { broadcast } from "utils/main" |
import { broadcast } from "utils/main" |
||||
import { EventMaps } from "../common" |
import { EventMaps, BaseEventMaps, EventScope } from "../events" |
||||
|
|
||||
export function emit(key: keyof EventMaps, ...args: Parameters<EventMaps[keyof EventMaps]>) { |
export function emit(key: keyof BaseEventMaps, ...args: Parameters<EventMaps[keyof EventMaps]>) { |
||||
broadcast(key, ...args) |
broadcast<EventMaps>(EventScope, key, ...args) |
||||
} |
} |
||||
|
@ -1,16 +1,20 @@ |
|||||
import { EventMaps } from "helper/updater/common" |
import { EventMaps, EventScope } from "helper/updater/events" |
||||
import { defineStore } from "pinia" |
import { defineStore } from "pinia" |
||||
|
import { Updater } from "." |
||||
|
|
||||
export const useSettingStore = defineStore( |
export const useUpdateStore = defineStore( |
||||
"Updater", |
"Updater", |
||||
() => { |
() => { |
||||
getApi<EventMaps>().on("update-progress", (_, data) => { |
getApi<EventMaps>().on(EventScope, "download-progress", (_, data) => { |
||||
console.log(data) |
console.log(data) |
||||
}) |
}) |
||||
|
|
||||
return {} |
return {} |
||||
}, |
}, |
||||
{ |
{ |
||||
persist: false, |
persist: false, |
||||
}, |
}, |
||||
) |
) |
||||
|
|
||||
|
export const triggerHotUpdate = () => { |
||||
|
Updater.getInstance().triggerHotUpdate() |
||||
|
} |
||||
|
@ -1,7 +1,9 @@ |
|||||
<script setup lang="ts"></script> |
<script setup lang="ts"> |
||||
|
import { triggerHotUpdate } from "common/event/Updater/hook" |
||||
|
</script> |
||||
|
|
||||
<template> |
<template> |
||||
<div h-full flex flex-col>sad</div> |
<div h-full flex flex-col @click="triggerHotUpdate">sad</div> |
||||
</template> |
</template> |
||||
|
|
||||
<style lang="scss" scoped></style> |
<style lang="scss" scoped></style> |
||||
|
Loading…
Reference in new issue