发布-订阅模式与实战

##含义说明
发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知先订阅再发布
##作用
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

    }

})();
  1. 模块间通信

<!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'

商城场景

posted @ 2022-03-25 19:16  Clematis  阅读(162)  评论(0)    收藏  举报