1. 程式人生 > >從vue的元件傳值著手淺談觀察者模式

從vue的元件傳值著手淺談觀察者模式

首先,提到觀察者模式,這不禁讓我想到了MVVM,MVVM架構模式感覺用到了觀察者的思想。

我們還是按照慣例,瞭解一下什麼是觀察者模式

 

觀察者模式又叫釋出訂閱模式,(Publish/Subscribe),完成這個動作首先最少得有兩個不同的物件,或者多個物件,他更像是一種一隊多的依賴關係,也就是一種物件的狀態發生改變,與其相關所有的物件的狀態都會發生改變;比如說朋友圈這個功能,一個人可能有上百個好友,當我釋出一條朋友圈後,所有和我成為好友的人都會看見這個朋友圈,當另一個人點贊後,所有你的好友其他點讚的人也會收到通知,這很像觀察者,也就是我是釋出者,我的好友是訂閱者。

然後我們看一下什麼是vue,vue的原理大家都知道,他是一種自底向上的一種深入響應式的雙向繫結模式,即MVVM,也就是說,vue關注model的變化,model的變化讓mvvm框架更新dom,從而產生檢視view變化。

舉一個專案中很常見的例子:

在寫vue專案中我們都用過父子元件傳值,但是兄弟元件傳值是怎麼實現的,首先我們可以用vuex,這很常見,但是還有一種方法不知道你用過沒有,就是Bus,這個Bus只是一種命名而已,叫什麼無所謂,你可以叫飛機大炮都可以,這不重要,我們主要看看他是怎麼實現的:

第一步,我們先在main.js中註冊一下bus:

Vue.prototype.$Bus = new Vue()

我們往vue的原型裡註冊了一個全域性變數$Bus,他的值是vue的例項,也就是說,到現在為止,$Bus裡邊有了vue所有的屬性和方法,這下就好操作了

第二步,我們開始傳送訊息,這就很符合觀察者模式的釋出訂閱模式

我們在元件1中寫如下程式碼:

<template>
    <div>
        <button @click="send">傳送</button>
    </div>
</template>

<script>
export default {
    methods: {
        send () {
            this.$Bus.$emit("send",'接收的資訊')
        }
    }
}
</script>

點選按鈕傳送一條資訊,這個按鈕也就是充當釋出者,我們用到了vue的$emit這個api,那麼訂閱者是什麼呢?我不說你也應該想到了,對,就是他

第三步,在元件三中接收訊息

<template>
    <div>
        {{message}}
    </div>
</template>

<script>
export default {
    data () {
        return {
            message: ''
        }
    },
    mounted () {
        this.$Bus.$on('send', (msg) => {
            this.message = msg
        })
    }
}
</script>

就是用$on這個屬性充當接收者

從上可以看出,vue很多地方用到了觀察者的思想,包括他的雙向繫結也是如此,首先我們看看vue的機制:

 

 從上圖我們可以看出,vue是通過Object.defineProperty實現對資料的劫持,然後中間做了一箇中轉,最後渲染到vue層。

我們可以肯定的是,vue.js借鑑了觀察者模式,但是我感覺還是有點區別的,觀察者模式跟注重的是事件驅動,比如我買房這個動作,第一次和銷售瞭解可能沒有合適的房源,然後銷售就會跟你說: ‘如果有合適的房源我們會第一時間通知你’,當有新房源的時候他會給你打電話通知你,這一系列的根源是買房這個事件,他驅動了整套流程。而vue我們都知道是資料驅動,也就是隻有data裡的值發生改變的話,Object.defineProperty才會對他劫持,從而去更新dom,觸發檢視的更新。

 

那麼有沒有更符合觀察者模式特徵的?

當然是node.js的events事件了。

首先我們看看events的工作流程:

var events = require('events');
// 建立 eventEmitter 物件
var eventEmitter = new events.EventEmitter();
// 建立事件處理程式
var connectHandler = function connected() {
   console.log('連線成功。');
   // 觸發 data_received 事件 
   eventEmitter.emit('data_received');
}
// 繫結 connection 事件處理程式
eventEmitter.on('connection', connectHandler);
// 使用匿名函式繫結 data_received 事件
eventEmitter.on('data_received', function(){
   console.log('資料接收成功。');
});
// 觸發 connection 事件 
eventEmitter.emit('connection');
console.log("程式執行完畢。");

輸出一下:

這就完全符合觀察者的工作模式,由emit釋出,由on接收。所以說,node.js提供了很好的監聽機制,還有他對整個事務的處理 。其支援了nodejs最特色的I/O模式,比如我們啟動http服務時會監聽其 connect / close,http.request時會監聽 data / end等。

 

還有沒有類似的案例呢?

當然,js有一個事件監聽者----addEventListener,也有點觀察者的意思,具體用法我就不說了,想必大家用的都很熟悉。

其實只要你認真想一想,還是有很多地方有觀察者的身影的,最簡單的就是一個點選事件,是不是也有其意思,釋出者是一個按鈕,而接收者可以是表單,彈層等任何東西。

那麼,對於觀察者模式存在的意義有哪些呢?

首先我們說說他的優點:

1,觀察者模式需要在觀察者和被觀察者之間建立一個耦合,他需要一個更加抽象化將二者聯絡在一起

2,觀察者模式支援廣播,也就是一對多的關係,這就讓我們很容易想到一個技術,就是socket,具體可以參考vue專案使用websocket技術

然鵝,他也是優缺點的:

1,建立訂閱者本身要消耗一定的時間和記憶體

2,當訂閱一個訊息時,也許此訊息並沒有發生,但這個訂閱者會始終存在記憶體中。

3,觀察者模式弱化了物件之間的聯絡,這本是好事情,但如果過度使用,物件與物件之間的聯絡也會被隱藏的很深,會導致專案的難以跟蹤維護和理解。

好了,對於觀察者模式我的理解就到這裡,歡迎指正!

&n