我正在参加「掘金·启航计划」
观察者模式:
什么是观察者模式,就是说在完成任务的情况下,又要完成另一类任务,这两个任务是两种(两类)任务,就需要一个观察者,来观察一个目标是否要做他自己的任务,然后观察者要去做目标任务相关联的任务
简言之:观察者要观察目标在干什么,这件事和观察者有没有关系,有关系的那观察者就去干这件事
我这里有一组数据,假如说是后台获取的,其中的任何一个数据都可以被改变或者请求,我都需要进行日志保存和打印,我就需要一个观察者来对数据的变化进行检测,我们常用的vue就是通过这种方式来监听的
vue中通过观察者来监听data中的数据变化,通过render函数渲染
手写观察者模式
class Target {
constructor(data) {
this.data = data
// 观察者
this.observer = new this.observer('#list')
this.init()
}
init() {
this.validate(this.data)
this.prox()
}
validate(data) {
// const data = this.data
// 将data中的数据解构出来
const { name, age, sex, hobby } = data
name.length < 6 && (data.name = '')
typeof age !== 'number' && (data.age = 0)
!['男', '女'].includes(sex) && (data.sex = '男')
}
// 代理对象
prox() {
const _this = this
for (let key in this.data) {
Object.defineProperty(this, key, {
get() {
// 更新日志
this.observer.update('get', key, _this.data[key])
return _this.data[key]
},
set(newValue) {
this.observer.update('set', key, _this.data[key], newValue)
_this.data[key] = newValue
}
})
}
}
}
// observer用于打印日志
class Observer {
constructor(el) {
this.el = document.querySelector(el)
this.pool = []
}
update(type, key, value, newValue) {
switch (type) {
case 'get':
this.getProp(key, value)
break
case 'set':
this.setProp(key, value, newValue)
break
default:
break
}
}
getProp(key, value) {
const obj = {
type: 'get',
dataTime: new Date(),
key,
value
}
this.pool.push(obj)
}
setProp(key, value, newValue) {
const obj = {
type: 'set',
dataTime: new Date(),
key,
value,
newValue
}
this.pool.push(obj)
}
log(o) {
const li = document.createElement('li')
let htmlStr = ''
switch (o.type) {
case 'get':
htmlStr = `${o.dataTime}---${o.key}---${o.value}`
break
case 'set':
htmlStr = `${o.dataTime}---${o.key}---${o.value}---${o.newValue}`
break
default:
break
}
li.innerHTML = htmlStr
this.el.appenChild(li)
console.log(this.pool)
}
}
;(() => {
const myTarget = new Target({
name: '张三',
age: 18,
sex: '男'
})
const init = () => {
console.log(myTarget.name)
console.log(myTarget)
}
init()
})()
发布订阅: 是观察者模式的一种延申,监听事件处理函数是否执行,同一个事件可以绑定多个事件处理函数
class Event {
// 事件处理函数集合
handlers = {
// click数组集合
// type: []
// 订阅
}
on(type, handler, once) {
if (!this.handlers[type]) {
this.handlers[type] = []
}
if (!this.handlers[type].includes(handler)) {
this.handlers[type].push(handler)
handler.once = once
}
}
// 绑定once限定一次
once(type, handler) {
this.on(type, handler, true)
}
// 解绑
off(type, handler) {
if (!this.handlers[type]) {
this.handlers[type] = this.handlers[type].filter(h => {
return h !== handler
})
}
}
// 触发事件
trigger(type) {
if (this.handlers[type]) {
this.handlers[type].forEach(handler => {
handler.call(this)
if (handler.once) {
this.off(type, handler)
}
})
}
}
}
const ev = new Event()