Observer

作者: 小米和豆豆 | 来源:发表于2021-01-20 20:11 被阅读0次

    ///仅供学习使用

    Create Observer

    comn.service.ts
    import { Injectable } from '@angular/core';
    @Injectable({
      providedIn: 'root'
    })
    export class ComnService {
      constructor() { }
      public storeObj={};
      set(key,value){
        this.storeObj[key]=value
      }
      get(key){
        return this.storeObj[key];
      }
    }
    
    app-get-value.ts
    import { Observable } from 'rxjs';
    let OBS: Observable<any> = new Observable(observer => {
          //公共方法里获取数据
          let params = this.comnService.get('data')
          if (params) {
            this.title = params.title
            console.log(params)
          }
          observer.next(params);
        })
    //将obs对象存起来,其他地方消费
    this.comnService.set('OBSR', OBS)
    
    app-set-value.ts
     this.OBS = this.comnService.get('OBSR');
     this.comnService.set('data', {
        type: 'set-title',
        title: new_title
     });
    //上面修改值后 调用subscribe 来通知发布者,在app-get-value.ts会自动监听到变化,来执行响应操作
    this.OBS.subscribe((res) => { 
      console.log(res)
    });
    



    Event Observer

        import { fromEvent } from 'rxjs';
        import { map } from 'rxjs/operators';
    
        // 创建发出点击事件的 observable
        const source = fromEvent(document, 'click');
        // 映射成给定的事件时间戳
        const example = source.pipe(map(event => `Event time: ${event.timeStamp}`));
        // 输出 (示例中的数字以运行时为准): 'Event time: 7276.390000000001'
        const subscribe = example.subscribe(val => console.log(val));
    

    监听页面

      import { Observable } from 'rxjs';
      import {HostListener} from '@angular/core';
     // 监听页面大小变化
        Observable.fromEvent(window, 'resize').subscribe((event) => {
          console.log('页面变化了');
          console.log(event);
        });
        // 监听页面刷新
        Observable.fromEvent(window, 'beforeunload').subscribe((event) => {
          console.log('页面刷新了');
          console.log(event);
        });
    
    @HostListener('window:resize', ['$event'])
      onResize(event) {
        event.target.innerWidth; 
      }
    

    观察者模式:定义了对象间一种一对多的依赖关系,当目标对象 Subject 的状态发生改变时,所有依赖它的对象 Observer 都会得到通知。
    优点 :

    1. 目标者与观察者,功能耦合度降低,专注自身功能逻辑;
    2. 观察者被动接收更新,时间上解耦,实时接收目标者更新状态;

    缺点 :

    1. 不能对事件通知进行细分管控,如 “筛选通知”,“指定主题事件通知” 。
    2. 观察者对象不能只接收自己需要的更新通知 , 目标对象会通知所有观察者;
    // 目标者类
    class Subject {
      constructor() {
        this.observers = [];  // 观察者列表
      }
      // 添加
      add(observer) {
        this.observers.push(observer);
      }
      // 删除
      remove(observer) {
        let idx = this.observers.findIndex(item => item === observer);
        idx > -1 && this.observers.splice(idx, 1);
      }
      // 通知
      notify() {
        for (let observer of this.observers) {
          observer.update();
        }
      }
    }
    
    // 观察者类
    class Observer {
      constructor(name) {
        this.name = name;
      }
      // 目标对象更新时触发的回调
      update() {
        console.log(`目标者通知我更新了,我是:${this.name}`);
      }
    }
    
    // 实例化目标者
    let subject = new Subject();
    
    // 实例化两个观察者
    let obs1 = new Observer('小王');
    let obs2 = new Observer('小李');
    
    // 向目标者添加观察者
    subject.add(obs1);
    subject.add(obs2);
    
    // 目标者通知更新
    subject.notify();  
    // 输出:
    // 目标者通知我更新了,我是小王
    // 目标者通知我更新了,我是小李
    

    发布订阅模式(Publisher && Subscriber):基于一个事件(主题)通道,希望接收通知的对象 Subscriber 通过自定义事件订阅主题,被激活事件的对象 Publisher 通过发布主题事件的方式通知各个订阅该主题的 Subscriber 对象。

    // 事件中心
    let pubSub = {
      list: {},
      subscribe: function (key, fn) {   // 订阅
        if (!this.list[key]) {
          this.list[key] = [];
        }
        this.list[key].push(fn);
      },
      publish: function(key, ...arg) {  // 发布
        for(let fn of this.list[key]) {
          fn.call(this, ...arg);
        }
      },
      unSubscribe: function (key, fn) {     // 取消订阅
        let fnList = this.list[key];
        if (!fnList) return false;
    
        if (!fn) {
          // 不传入指定取消的订阅方法,则清空所有key下的订阅
          fnList && (fnList.length = 0);
        } else {
          fnList.forEach((item, index) => {
            if (item === fn) {
              fnList.splice(index, 1);
            }
          })
        }
      }
    }
    
    // 订阅
    pubSub.subscribe('onwork', time => {
      console.log(`上班了:${time}`);
    })
    pubSub.subscribe('offwork', time => {
      console.log(`下班了:${time}`);
    })
    pubSub.subscribe('launch', time => {
      console.log(`吃饭了:${time}`);
    })
    
    // 发布
    pubSub.publish('offwork', '18:00:00'); 
    pubSub.publish('launch', '12:00:00');
    
    // 取消订阅
    pubSub.unSubscribe('onwork');
    

    类似例子 DOM事件监听 vue 父子传值 pubsub.js 事件总线等

    相关文章

      网友评论

          本文标题:Observer

          本文链接:https://www.haomeiwen.com/subject/nuatwktx.html