Vue 수준에서 - 게시 및 구독 모드와 관찰자 모드의 차이 분석

머리말

관찰자 모드와 게시-구독 모드는 일상적인 개발에서 자주 사용되며 잘 구분하지 못했습니다. 최근에 Vue의 소스코드를 보다가 옵저버 모드가 설계되어 있어서 더 흥미가 생겨서 배우러 갔습니다.

1. 게시 및 구독 모드

게시-구독 패턴이란 무엇입니까?

1을 기준으로 事件中心알림을 받는 객체는 먼저 이벤트를 구독해야 하는 구독자이고 이벤트를 트리거하는 객체는 게시자이며 게시자는 이벤트를 트리거하여 각 구독자에게 알립니다.

예: 예를 들어 일반적으로 구독하는 WeChat 공식 계정은 공식 계정(이벤트 센터)과 공식 계정을 구독한 사용자(구독자)의 두 가지 역할을 포함합니다. 공식 계정의 작성자가 기사를 게시하면 공식 계정을 구독하는 사용자는 뉴스를 받게 되며 여기에는 공식 계정의 작성자(게시자)라는 또 다른 역할이 포함됩니다.

애플리케이션 시나리오

vue의 이벤트 버스는 사용되는 게시-구독 모드이며 를 사용하고 $emit형제 $on구성 요소와 통신하며 매개 변수를 전달합니다.

vue에서 게시-구독 모드를 수동으로 구현합니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue 中发布订阅模式</title>
</head>
<body>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>  
    // Vue 的实例,创建事件总线
    let bus = new Vue()
    // 订阅事件
    bus.$on('eventName1', val => {
      
      
      console.log('eventName1---->', val)
    })
    bus.$on('eventName2', val => {
      
      
      console.log('eventName2---->', val)
    })

    // 发布事件
    bus.$emit('eventName1', 'eventName1')
    bus.$emit('eventName2', 'eventName2')
  }
  </script>
</body>
</html>

인쇄 결과:

여기에 이미지 설명 삽입

위의 코드에서 bus우리가 만든 것이 事件总线바로 Vue 인스턴스입니다. 이 인스턴스를 다른 구성 요소에 도입하고 $on 메서드를 사용하여 이벤트를 수신하고 $emit 메서드를 사용하여 이벤트를 트리거할 수 있습니다. 동일한 이벤트 버스 인스턴스를 공유함으로써 서로 다른 구성 요소가 이벤트를 통해 통신하여 분리를 달성할 수 있습니다.

销毁이벤트 버스 모드를 사용할 때 문제가 발생하지 않도록 적절한 시간에 이벤트 버스가 활성화되는지 확인해야 합니다 内存泄漏. 이벤트 버스는 구성 요소의 수명 주기 후크에서 제거될 수 있습니다.

beforeDestroy() {
    
    
  bus.$off();
}

2. 관찰자 모드

1) 옵저버 패턴이란?

대상 개체와 관찰자 개체는 상호 의존적 관계를 가지고 있습니다.관찰자는 개체의 상태를 관찰합니다.개체의 상태가 변경되면 개체에 의존하는 모든 관찰자에게 업데이트 작업을 수행하도록 알립니다.

관찰자 모드는 게시-구독 모드보다 하나 적습니다 事件中心.

  • 대상 객체[Subject]: 관찰 대상으로, 일련의 관찰자를 유지하고 添加、删除和通知관찰자를 위한 방법을 제공합니다.
  • 옵저버 객체[Observe]: Subject 상태 변경 알림을 수신하고 처리합니다.
  • 대상 개체 [Subject]의 상태가 변경되면 모든 관찰자 개체 [Observe]에게 업데이트 작업을 수행하도록 알립니다.

2) 적용 시나리오

Vue의 관찰자 모드 애플리케이션 시나리오: 데이터 반응형 변경 .

이전 Vue 소스 코드 학습 - 데이터 응답 원칙 기사에서 각 응답 속성에는 dep 인스턴스가 있고 dep는 이 속성에 의존하는 감시자를 저장한다는 것을 배웠습니다(watcher는 데이터 변경을 관찰하는 함수입니다). 업데이트 메서드를 호출하도록 의존하는 모든 관찰자에게 알립니다. 따라서 관찰자는 그것에 의존하는 모든 관찰자에게 알리기 위해 대상 객체에 의해 수집되어야 합니다 .
감시자에 dep를 저장해야 하는 이유는 무엇입니까? 그 이유는 현재 실행 중인 watcher가 현재 자신에게 통지한 dep를 알아야 하기 때문입니다 .

3) vue의 관찰자 모드

관찰자(구독자) - 감시자

  • update(): 이벤트가 발생했을 때 구체적으로 해야 할 일.

Targeter(게시자) - Dep

  • subs数组: 모든 관찰자를 저장합니다.
  • addSub(): 관찰자를 추가합니다.
  • removeSub(): 관찰자를 제거합니다.
  • notify(): 옵저버에게 알리고, 이벤트 발생 시 모든 옵저버의 update()를 호출합니다.

이벤트 센터 없음

옵저버 패턴을 수동으로 구현

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>观察者模式</title>
</head>
<body>
  <script>
    // 目标者(发布者)
    class Dep {
      
      
      constructor () {
      
      
        // 记录所有的订阅者
        this.subs = []
      }
      // 添加订阅者
      addSub (sub) {
      
      
        if (sub && sub.update) {
      
      
          this.subs.push(sub)
        }
      }
      // 发布通知
      notify () {
      
      
        this.subs.forEach(sub => {
      
      
          sub.update()
        })
      }
    }
    
    // 观察者(订阅者)
    class Watcher {
      
      
      update () {
      
      
        console.log('update')
      }
    }
    
    //创建实例化对象 测试一下
    let dep = new Dep()
    let watcher = new Watcher()
    let watcher1 = new Watcher()
    // 添加订阅者
    dep.addSub(watcher)
    dep.addSub(watcher1)
    // 开启通知
    dep.notify()
    // 执行结果 update --->
  </script>
</body>
</html>

인쇄 결과: 업데이트 알림을 두 번 트리거합니다.

여기에 이미지 설명 삽입

3. 게시-구독 모드와 옵저버 모드의 차이점

1) 조성 분석

  • 观察者관찰자 모드에는 두 가지 역할 만 있습니다 目标者. 그 중 관찰되는 인물이 핵심이다.
  • 发布者게시-구독 모델에는 및 뿐만 订阅者아니라 하나도 있습니다 事件中心. 그중에서도 이벤트 센터가 주목된다.
관찰자 패턴 게시-구독 모델
2자 3자
초점은 관찰 대상(대상)에 있습니다. 초점은 이벤트 허브에 있습니다.

2) 관계 분석

  • 관찰자와 대상이 느슨하게 결합되어 있습니다.
  • 게시자와 구독자, 결합이 전혀 없습니다.

3) 사용 관점에서의 분석

  • 주로 단일 애플리케이션 내에서 사용되는 관찰자 모드(Vue의 데이터 응답 변경은 관찰자 모드임)
  • 게시-구독 모드, 교차 애플리케이션 모드(예: 일반적으로 사용되는 모드 消息中间件)

참조 가능:
게시 구독 모드 및 관찰자 모드

추천

출처blog.csdn.net/weixin_45811256/article/details/131782621