<body>
观察者模式又叫发布订阅模式,定义了一种一对多关系,
让多个观察者同时监听某一个主题,
当这个主题发生改变(触发)的时候通知所有的观察者
1、功能模块之间的任何变化都不会影响到 另一边 变化
2、解藕 减少对象和对象之前的相互引用
3、对象和对象之间存在一种动态的关系
4、能够单独扩展以及重用
每一个程序所负责的代码功能写好之后 订阅下 需要的时候进行发布
<hr>
<div class="app">
<input type="text"><br>
<button>提交</button>
<span></span>
<ul></ul>
</div>
<script>
/*
例:
程序a 写提交按钮后向ul添加li
程序b 写计算评论的数量
*/
// 场景 接手该项目 添加新功能 没办法修改原先的代码 这里就要用到观察者模式
let observer = (function(){
let eventObj = {},
id = -1; // 订阅的时候给每一个对象标示一个ID 方便以后解绑
return {
// 订阅方法
subscription(name, fn){ // 订阅者
eventObj[name] || (eventObj[name] = [])
let idSign = (++id).toString()
eventObj[name].push({
id: idSign,
fn: fn
})
return idSign
},
// 发布方法
publish(name){
eventObj[name].forEach(item => {
item.fn()
});
// while(length--){
// eventObj[name][length].fn()
// }
},
// 解除订阅
unSubscription(name, id){
let eObj = eventObj[name],
length = eObj.length;
eObj.forEach((item, index) =>{
if(item.id == id) {
eObj.splice(index, 1)
}
})
}
}
})();
// 程序a
(function(){
let app = document.getElementsByClassName('app')[0],
inpText = app.getElementsByTagName('input')[0],
btn = app.getElementsByTagName('button')[0],
oUl = app.getElementsByTagName('ul')[0];
let addLi = function(){
let vale = inpText.value,
li = document.createElement('li')
li.innerHTML = vale;
// 此处省略100行代码
console.log(oUl)
oUl.appendChild(li)
}
// 订阅
let id = observer.subscription('addLi', addLi)
console.log(id)
})();
// 程序b
(function(){
let app = document.getElementsByClassName('app')[0],
btn = app.getElementsByTagName('button')[0],
oUl = app.getElementsByTagName('ul')[0],
oSpan = app.getElementsByTagName('span')[0],
addComment = function(){
let aLi = oUl.children
oSpan.innerHTML = aLi.length
// 此处省略100行代码
}
// 订阅
let id = observer.subscription('addComment', addComment)
observer.unSubscription('addComment', id)
console.log(id)
})();
// 我们要做的是:判断有没有值 有值再让添加
(function(){
let inpText = document.getElementsByTagName('input')[0],
btn = document.getElementsByTagName('button')[0]
btn.addEventListener('click', function(){
if(inpText.value){
// 发布
observer.publish('addLi')
observer.publish('addComment')
}
})
})()
</script>
</body>
案例
<body>
<div id="one">1</div>
<div id='two'>2</div>
<div id="three">3</div>
<button id='btn'>点击</button>
<script>
let scence = {
list: {
dom: [],
callback: []
},
// 订阅 监听
addListen(el, fn){
let list = this.list,
index = 0;
for (const key in list) {
list[key].push(arguments[index])
index ++
}
},
// 执行
publish(){
let list = this.list
list['dom'].forEach((item, index) =>{
this.list['callback'][index].apply(document.querySelector(item), arguments)
})
}
}
// 订阅
scence.addListen('#one', function(){
this.style.border = '1px solid red'
})
scence.addListen('#two', function(){
this.style.color = 'red'
})
scence.addListen('#three', function(){
this.style.backgroundColor = 'yellow'
})
// 执行
btn.onclick = function(){
scence.publish()
}
</script>
网友评论