let eventHub = new Vue()
// 訂閱
eventHub.$on('eventName', (data) => {
console.log('😍' + data)
})
// 發佈
eventHub.$emit('eventName', 'cats') // '😍 cats'
複製代碼
取消發佈,在發佈以前調用,不能取消匿名函數。node
let eventHub = new Vue()
let fn = (data) => {
console.log('😍' + data)
}
// 訂閱
eventHub.$on('eventName', fn)
// 取消發佈
eventHub.$off('eventName', fn)
// 發佈
eventHub.$emit('eventName', 'cats') // 沒有結果
複製代碼
文件結構面試
eventHub/
src/
index.ts
test/
index.ts 放測試代碼
複製代碼
將函數存在一個對象中,命名爲cache,格式爲, js { 'xxx': [fn1, fn2], 'xxx2': [fn1, fn2], }
數組
onbash
off函數
class EventHub {
cache = {}
// ts 語法 === js的 this.cache={}
// 對象的屬性
on(eventName, fn) {
// 若是沒有,初始化
if (this.cache[eventName] === undefined){
this.cache[eventName] = []
}
// 把fn 推動 this.cache[eventName] 數組
let array = this.cache[eventName]
array.push(fn)
}
emit(eventName) {
let array = this.cache[eventName]
if (array === undefined) {
array = []
}
// 把this.cache中函數依次執行
array.forEach(fn => {
fn()
})
}
}
export default EventHub
複製代碼
測試代碼ts測試
import EventHub from '../src/index'
const eventHub = new EventHub()
console.assert(eventHub instanceof Object === true, 'eventHub 是個對象')
// on emit
let called = false
eventHub.on('xxx', () => {
called = true
console.log('called:' + called)
})
eventHub.emit('xxx')
複製代碼
on(eventName, fn) {
// this.cache[eventName] 若是不存在,爲[];不然爲他本身
// if (this.cache[eventName] === undefined) {
// this.cache[eventName] = []
// }
// 將上面的代碼優化爲 下面一句(下同)
this.cache[eventName] = this.cache[eventName] || []
// let array = this.cache[eventName]
// array.push(fn)
this.cache[eventName].push(fn)
}
複製代碼
emit(eventName) {
// let array = this.cache[eventName]
// if (array === undefined) {
// array = []
// }
// 此處與on優化方式相同 --> this.cache[eventName] || []
// this.cache[eventName].forEach(fn =>
// fn()
// )
// 上方的代碼優化爲下面一句
(this.cache[eventName] || []).forEach(fn => fn())
}
複製代碼
// ? 能夠不傳遞參數 ...拓展運算符 能夠傳遞多個參數
emit(eventName, ...args?) {
(this.cache[eventName] || []).forEach(fn => fn(...args))
}
複製代碼
測試 傳遞參數代碼優化
// 測試 on emit
eventHub.on('xxx', (y) => {
console.log('called:' + called)
console.assert( y === 'hello')
})
eventHub.emit('xxx', 'hello')
複製代碼
off(eventName, fn) {
// 把fn從this.cache[eventName] 刪掉
this.cache[eventName] = this.cache[eventName] || []
// 找一個元素是數組的第幾項 array.indexOf(searchElement)
// 方法返回在數組中能夠找到一個給定元素的第一個索引,若是不存在,則返回-1。
// 可是兼容性很差,不兼容IE11,這裏本身實現一個函數
let index
for (let i = 0; i < this.cache[eventName].length; i++) {
if (this.cache[eventName][i] === fn) {
index = i
break
}
}
if(index === undefined) {
return
} else {
this.cache[eventName].splice(index, 1)
}
}
複製代碼
off(eventName, fn) {
// this.cache[eventName] = this.cache[eventName] || [] 優化爲下面一句
let index = indexOf(this.cache[eventName], fn)
// if(index === undefined) {
// return
// } else {
// this.cache[eventName].splice(index, 1)
// } 優化爲下面一句
if (index === undefined) return
this.cache[eventName].splice(index, 1)
}
}
export default EventHub
function indexOf(array, item) {
if (array === undefined) return -1
let index = -1
for (let i = 0; i < array.length; i++) {
if (array[i] === item) {
index = i
break
}
}
}
複製代碼
TypeScript 能夠簡單理解爲 Type + JavaScript,如今咱們來給全部參數加上類型定義ui
class EventHub {
// 聲明爲一個cache 對象
// - key: value
// - key是string : value 數組
// - 數組中是函數 參數(未知) 和 返回值(爲空)
private cache: { [key: string]: Array<(data: unknown) => void>} = {}
// unknow 第一次傳遞的爲何類型,之後只能傳遞此種類型,不能修改
// void 返回值爲空
on(eventName: string, fn: (data: unknown) => void) {
this.cache[eventName] = this.cache[eventName] || []
this.cache[eventName].push(fn)
}
// data? 表示能夠爲空,不傳遞
emit(eventName: string, data?: unknown) {
(this.cache[eventName] || []).forEach(fn => fn(data))
}
off(eventName: string, fn: (data: unknown) => void) {
let index = indexOf(this.cache[eventName], fn)
if (index === undefined) return
this.cache[eventName].splice(index, 1)
}
}
export default EventHub
function indexOf(array: Array<unknown>, item: unknown) {
if (array === undefined) return -1
let index = -1
for (let i = 0; i < array.length; i++) {
if (array[i] === item) {
index = i
break
}
}
}
複製代碼
測試代碼使用TypeScriptthis
import EventHub from '../src/index'
// 定義一種類型 TestCase 傳遞string參數,返回值爲空
type TestCase = (message: string) => void
// 第一個測試用例,起名爲test1 在最後調用
// 斷言 eventHub是個對象
const test1: TestCase = message => {
const eventHub = new EventHub()
console.assert(eventHub instanceof Object === true, 'eventHub 是個對象')
// 肯定成功以後打出message
console.log(message)
}
const test2: TestCase = message => {
const eventHub = new EventHub()
// on emit
let called = false
eventHub.on('xxx', y => {
called = true
console.assert(y === 'hello')
})
eventHub.emit('xxx', 'hello')
console.assert(called)
console.log(message)
}
const test3: TestCase = message => {
const eventHub = new EventHub()
let called = false
const fn1 = () => {
called = true
}
eventHub.on('yyy', fn1)
eventHub.off('yyy', fn1)
eventHub.emit('yyy')
console.assert(called === false)
console.log(message)
}
test1('eventHub 能夠建立對象')
test2('.on 以後,.emit會觸發on的函數')
test3('.off有用')
複製代碼
這就是使用TypeScipt編寫的發佈訂閱模式,感謝各位的閱讀 ~spa
歡迎你們留下問題一塊兒探討 ~
但願能夠在面試、工做中助你一臂之力!