釋出-訂閱模式與實戰
阿新 • • 發佈:2022-03-25
##含義說明
釋出-訂閱模式又叫觀察者模式,它定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都將得到通知先訂閱再發布
##作用
1.支援簡單的廣播通訊,當物件狀態發生改變時,會自動通知已經訂閱過的物件。
2.可以應用在非同步程式設計中替代回撥函式可以訂閱ajax之後的事件只需要訂閱自己需要的部分(那麼ajax掉用釋出之後訂閱的就可以拿到訊息了)(不需要關心物件在非同步執行時候的狀態)
3.物件之間的鬆耦合兩個物件之間都互相不瞭解彼此但是不影響通訊當有新的訂閱者出現的時候釋出的程式碼無需要改變同樣釋出的程式碼改變只要之前約定的事件的名稱沒有改變也不影響訂閱
4.vue react之間實現跨元件之間的傳值
##缺點
1. 建立訂閱者需要消耗一定的時間和記憶體。
2.雖然可以弱化物件之間的聯絡,如果過度使用的話,反而使程式碼不好理解及程式碼不好維護等等##生活中的例項
比如小紅最近在淘寶網上看上一雙鞋子,但是呢聯絡到賣家後,才發現這雙鞋賣光了,但是小紅對這雙鞋又非常喜歡,所以呢聯絡賣家,問賣傢什麼時候有貨,賣家告訴她,要等一個星期後才有貨,賣家告訴小紅,要是你喜歡的話,你可以收藏我們的店鋪,等有貨的時候再通知你,所以小紅收藏了此店鋪,但與此同時,小明,小花等也喜歡這雙鞋,也收藏了該店鋪;等來貨的時候就依次會通知他們;
如何實現釋出--訂閱模式?
1.首先要想好誰是釋出者(比如上面的賣家)。
2.然後給釋出者新增一個快取列表,用於存放回調函式來通知訂閱者(比如上面的買家收藏了賣家的店鋪,賣家通過收藏了該店鋪的一個列表名單)。
3.最後就是釋出訊息,釋出者遍歷這個快取列表,依次觸發裡面存放的訂閱者回調函式。
新增key 封裝好的js
var Event = ( function(){ var list = {}, listen, trigger, remove; listen = function (key,fn){ if(!list[key]){ list[key] = []; } list[key].push(fn); }; trigger = function(){ //取出key var key = Array.prototype.shift.call(arguments) var fns = list[key] //遍歷陣列 執行函式 if(!fns || fns.length === 0){ return false; } for(var i = 0,fn;fn = fns[i++];){ fn.apply(this,arguments) } }; remove = function(key ,fn){ var fns = list[key]; if(!fns){ return false; } if(!fn){ fns && (fns.length = 0); }else { for(var i = fns.length-1 ; i>=0;i--){ var _fn =fns[i]; if(_fn === fn){ fns.splice(i,1); } } } }; return { listen:listen, trigger:trigger, remove:remove } })();
-
模組間通訊
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>01</title>
</head>
<body>
<button id="count">點選</button>
<div id="showcount" style="color: rgb(17, 94, 94);"></div>
<script src="./pubsub.js">
</script>
<script>
//釋出
var a = ( function () {
var count = 0;
var button = document. getElementById("count");
button.onclick = function() {
Event.trigger( "add", count++);
}
})();
//訂閱
var b = (function () {
var div = document.getElementById("showcount");
Event.listen( 'add' , function (count){
div.innerHTML = count;
});
})();
</script>
</body>
</html>
跨元件傳值
//HelloWorld.vue
<template>
<div class="hello">
<input type="text" v-model="name" />
<button @click="doPub">跨元件傳值</button>
<Son />
</div>
</template>
<script>
import PubSub from '@/utils/pubsub.js'
import Son from './Son'
export default {
name: 'HelloWorld',
comments:{
Son
},
props: {
msg: String
},
data(){
return{
name:''
}
},
methods: {
doPub(){
PubSub.trigger("color",this.name);
}
},
}
//Son.vue
<template>
<div>
<h1>兒子元件</h1>
<Children />
</div>
</template>
<script>
import Children from './Children.vue'
//Children.vue
<template>
<div>
<h1>孫子元件</h1>
<h1>{{content}}</h1>
</div>
</template>
<script>
import PubSub from '@/utils/pubsub.js'