每日 30 秒 ⏱ 發佈與訂閱

前言

設計模式、發佈、訂閱、Event、事件javascript

今天分享一個開發中比較經常使用到的設計模式發佈-訂閱模式也能夠叫觀察者模式,在發佈-訂閱模式中主要有兩個角色:發佈者 和 訂閱者。html

生活中最經常使用到的一個場景就是當你在QQ空間發佈一條心情的時候全部你的QQ好友都會收到你的QQ動態,在這個例子中 就是 發佈者,而 QQ 好友 則會是訂閱者。前端

const createEventHub = () => ({
    hub: Object.create(null),

    emit(event, data) {
        (this.hub[event] || []).forEach(handler => handler(data));
    },

    on(event, handler) {
        if (!this.hub[event]) this.hub[event] = [];
        this.hub[event].push(handler);
    },

    off(event, handler) {
        const i = (this.hub[event] || []).findIndex(h => h === handler);
        if (i > -1) this.hub[event].splice(i, 1);
    }
});
複製代碼

代碼分析

使用 Object.prototype.create 方法來快速建立了一個內部對象:java

hub: Object.create(null)
複製代碼

使用 Array.prototype.forEach 來遍歷監聽事件對應的全部操做:git

emit(event, data) {
    (this.hub[event] || []).forEach(handler => handler(data));
}
複製代碼

使用 Array.prototype.push 來存儲事件對應的操做:github

on(event, handler) {
    if (!this.hub[event]) this.hub[event] = [];
    this.hub[event].push(handler);
}
複製代碼

使用 Array.prototype.findIndex 來查詢事件對應的操做並使用 Array.prototype.splice 來去除操做:ajax

off(event, handler) {
    const i = (this.hub[event] || []).findIndex(h => h === handler);
    if (i > -1) this.hub[event].splice(i, 1);
}
複製代碼

使用場景

當用戶輸入 表單數據頁面數據data 進行同步更新,反之當 data 被其餘操做修改時 對 頁面數據表單數據 進行同步更新,這樣就簡單的實現了一個相似 Vue 的數據雙向綁定。設計模式

記得在項目開發過程當中 大叔 在一個 jQuery 的前端項目中爲了方便數據的變動和維護引入了 Vue 使得項目變得臃腫和複雜,若是使用 發佈-訂閱模式 則能夠很方便的來實現這個操做而無需引入這麼大的一個框架。微信

當單頁面項目並不巨大,咱們無需引入像 ReduxVuex 這樣的數據管理庫,使用 發佈-訂閱模式 也能夠很方便的管理組件之間的數據變動和依賴更新。框架

結構
<h2>用戶數據</h2>
<div id="info">
    <h3>
        用戶名:<span id="username"></span>
    </h3>
    <h3>
        密碼:<span id="password"></span>
    </h3>
</div>

<h2>請輸入用戶數據</h2>
<div id="form">
    <input type="text" name="username" oninput="hub.emit('oninput', 'username')" />
    <input type="text" name="password" oninput="hub.emit('oninput', 'password')" />
    <button type="button" onclick="hub.emit('submit')">肯定</button>
    <button type="button" onclick="hub.emit('resetFormData')">重置</button>
</div>
複製代碼
腳本
// 基礎表單數據
let data = {
    username: '',
    password: '',
}

const hub = createEventHub()

// 監聽表單輸入事件
hub.on('oninput', (name) => {
    const dom = document.querySelector(`[name="${name}"]`)
    hub.emit('setFormData', { name, value: dom.value })
})

// 監聽數據變動事件
hub.on('setFormData', ({ name, value }) => {
    data[name] = value
})

// 監聽數據變動事件
hub.on('setFormData', ({ name, value }) => {
    const dom = document.querySelector(`#${name}`)
    dom.innerHTML = value
})

// 監聽數據變動事件
hub.on('setFormData', ({ name, value }) => {
    const dom = document.querySelector(`[name="${name}"]`)
    dom.value = value
})

// 監聽頁面數據提交事件
hub.on('submit', () => {
    // ajax 發送數據請
    // 這裏用 setTimeout 來模擬 ajax 請求發送
    setTimeout(() => {
        alert('數據發送成功')
        hub.emit('resetFormData')
    }, 1000)
})

// 監聽頁面數據提交事件
hub.on('resetFormData', () => {
    hub.emit('setFormData', { name: 'username', value: '' })
    hub.emit('setFormData', { name: 'password', value: '' })
})
複製代碼

一塊兒成長

在困惑的城市裏總少不了並肩同行的 夥伴 讓咱們一塊兒成長。

  • 若是您想讓更多人看到文章能夠點個 點贊
  • 若是您想激勵小二能夠到 Github 給個 小星星
  • 若是您想與小二更多交流添加微信 m353839115

微信公衆號

本文原稿來自 PushMeTop

相關文章
相關標籤/搜索