1、观察者模式
当对象间存在一对多的关系,使用观察者模式。比如:当一个对象被修改,会自动通知依赖它的对象。
let uid = 0
class Dep {
constructor() {
this.id = uid++
// 存储所有的 watcher
this.subs = []
}
addSub(sub) {
this.subs.push(sub)
}
removeSub(sub) {
if(this.subs.length) {
const index = this.subs.indexOf(sub)
if(index > -1) return this.subs.splice(index, 1)
}
}
notify() {
this.subs.forEach(sub => {
sub.update()
})
}
}
class Watcher {
constructor(name) {
this.name = name
}
update() {
console.log('更新')
}
}
2、发布订阅模式
与观察者模式相似,区别在于发布者和订阅者是解耦的,由中间的调度中心去与发布者和订阅者通信。
Vue响应式原理个人更倾向于发布订阅模式。其中 Observer 是发布者,Watcher 是订阅者,Dep 是调度中心。
class EventEmitter {
constructor() {
this.events = {}
}
on(type, cb) {
if(!this.events[type]) this.events[type] = []
this.events[type].push(cb)
}
emit(type, ...args) {
if(this.events[type]) {
this.events[type].forEach(cb => {
cb(...args)
})
}
}
off(type, cb) {
if(this.events[type]) {
const index = this.events[type].indexOf(cb)
if(index > -1) this.events[type].splice(index, 1)
}
}
}
3、Vue.observable 的了解
Vue.observable 可使对象可响应。返回的对象可直接用于渲染函数和计算属性内,并且在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器。
Vue 2.x 中传入的对象和返回的对象是同一个对象。
Vue 3.x 则不是一个对象,源对象不具备响应式功能。
适用的场景:在项目中没有大量的非父子组件通信时,可以使用 Vue.observable 去替代 eventBus和vuex方案。
// store.js
import Vue from 'vue'
export const state = Vue.observable({
count: 1
})
export const mutations = {
setCount(count) {
state.count = count
}
}
// vue 文件
<template>
<div>{{ count }}</div>
</template>
<script>
import { state, mutation } from './store.js'
export default {
computed: {
count() {
return state.count
}
}
}
</script>