목차
머리말
관찰자 모드와 게시-구독 모드는 일상적인 개발에서 자주 사용되며 잘 구분하지 못했습니다. 최근에 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의 데이터 응답 변경은 관찰자 모드임)
- 게시-구독 모드, 교차 애플리케이션 모드(예: 일반적으로 사용되는 모드
消息中间件
)
참조 가능:
게시 구독 모드 및 관찰자 모드