Open david2tdw opened 4 years ago
var event = {
list: [],
// 添加注册事件到队列中
listen: function (key, fn) {
if (!this.list[key]) { // 对象内,用this调用对象的属性
this.list[key] = []
}
this.list[key].push(fn);
},
// 通过trigger去查找已经注册过的事件,找到后去执行事件的具体函数,输出对应的内容。
trigger: function () {
console.log(arguments)
// shift() 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
// 绑定arguments对象
// arguments是一个数组, 想当与arguments.shift().
var key = Array.prototype.shift.apply(arguments); // 使用call / apply都可以
var fns = this.list[key];
if (!fns || fns.length === 0) {
return;
}
fns.forEach(fn => {
fn.apply(this, arguments); // 执行对应的注册函数
})
}
}
var initEvent = function (obj) {
for (var i in event) {
obj[i] = event[i]
}
}
var shoesOjb = {}
initEvent(shoesOjb);
shoesOjb.listen('red', size => {
console.log("red尺码是:"+size);
})
shoesOjb.listen('black', size => {
console.log("black尺码是:"+size);
})
shoesOjb.trigger('red', 20);
shoesOjb.trigger('black', 60);
var event = {
list: [],
// 添加注册事件到队列中
listen: function (key, fn) {
if (!this.list[key]) { // 对象内,用this调用对象的属性
this.list[key] = []
}
this.list[key].push(fn);
},
// 通过trigger去查找已经注册过的事件,找到后去执行事件的具体函数,输出对应的内容。
trigger: function () {
var key = Array.prototype.shift.apply(arguments); // 使用call / apply都可以
var fns = this.list[key];
if (!fns || fns.length === 0) {
return;
}
fns.forEach(fn => {
fn.apply(this, arguments); // 执行对应的注册函数
})
},
// 取消订阅事件
remove: function (key, fn) {
var fns = this.list[key]; // 返回对应key的所有函数
if (!fns) { // 如果key对应的消息没有订阅过的话,则返回
return false
}
if (!fn) { // 如果没有传入具体的回调函数,表示需要取消key对应消息的所有订阅
fns && (fns.length = 0)
} else {
fns.forEach((vFn, index) => {
if (vFn === fn) {
fns.splice(index, 1); // 删除订阅者的回调函数
}
})
}
}
}
var initEvent = function (obj) {
for (var i in event) {
obj[i] = event[i]
}
}
var shoesOjb = {}
initEvent(shoesOjb);
shoesOjb.listen('red', fn1 = size => {
console.log("red尺码是:"+size);
})
shoesOjb.listen('black', fn2 = size => {
console.log("black尺码是:"+size);
})
shoesOjb.trigger('red', 20);
shoesOjb.trigger('black', 30);
console.log('移除监听事件red.')
shoesOjb.remove('red', fn1);
console.log('再次触发事件red black.')
shoesOjb.trigger('red', 40);
shoesOjb.trigger('black', 50);
event.js
// 全局发布-订阅模式对象, 通过自执行函数return一个对象,将内部方法暴露出去。
var Event = (function() {
var list = {},
listen,
trigger,
remove
listen = function(key, fn) {
if (!list[key]) {
list[key] = []
}
list[key].push(fn)
}
trigger = function() {
var key = Array.prototype.shift.call(arguments),
fns = list[key]
if (!fns || fns.length === 0) {
return false
}
for (var i = 0, fn; (fn = fns[i++]); ) {
fn.apply(this, arguments)
}
}
remove = function(key, fn) {
var fns = list[key]
if (!fns) {
return false
}
if (!fn) {
fns && (fns.length = 0)
} else {
for (var i = fns.length - 1; i >= 0; i--) {
var _fn = fns[i]
if (_fn === fn) {
fns.splice(i, 1)
}
}
}
}
// 通过自执行函数return一个对象,将内部方法暴露出去
return {
listen: listen,
trigger: trigger,
remove: remove
}
})()
a.js
// a.js 负责处理点击操作及发布消息
// 不需要引入event.js, 会在主页面引入
var a = (function () {
var count = 0 ;
var button = document.getElementById('count')
button.onclick = function () {
Event.trigger('add', count++)
}
})();
b.js
// b.js 负责监听add这个消息,并把点击的总次数显示到页面上来
// 不需要引入event.js, 会在主页面引入
var b = (function() {
var div = document.getElementById('showcount')
Event.listen('add', function(count) {
div.innerHTML = count
})
})()
main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>发布-订阅模式,模块间通信</title>
<script src="event.js"></script>
</head>
<body>
<button id="count">click me</button>
<div id="showcount"></div>
<script src='a.js'></script>
<script src="b.js"></script>
</body>
</html>
定义:
让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。
场景:
DOM事件。
实现:
JS发布-订阅模式