观察者模式
·
Yin灏
/**
* 创建一个观察者
*/
// 将观察者放在闭包中,当页面加载就立即执行
var Observer = (function () {
// 防止消息队列暴露而被篡改,故将消息容器作为静态私有变量保存
var _message = {};
return {
// 注册信息接口
regist: function (type, fn) {
// 如果此消息不存在则该创建一个该消息类型
if (typeof _message[type] === "undefined") {
// 将动作推入到该消息对应的动作执行队伍中
_message[type] = [fn];
} else {
// 如果消息存在
_message[type].push(fn);
}
},
// 发布信息接口
fire: function () {
// 如果该消息没有被注册,则返回
if (!_message[type]) {
return;
}
// 定义消息信息
var events = {
type, // 消息类型
args: args || {}, // 消息携带数据
},
i = 0,
len = _message[type].length;
for (; i < len; i++) {
// 依次执行注册的消息对应的动作序列
_message[type][i].call(this, events);
}
},
// 移除信息接口
remove: function (type, fn) {
// 如果消息动作队列存在
if (_message[type] instanceof Array) {
// 从最后一个消息动作遍历
var i = _message[type].length - 1;
for (; i >= 0; i--) {
_message[type][i] === fn && _message[type].splice(i, 1);
}
}
},
};
})();
/**
* 拉出来溜溜
*/
// 订阅一条消息
Observer.regist("test", function (e) {
console.log(e.type, e.args.msg);
});
// 发布这条消息
Observer.fire("test", { msg: "传递参数" }); // test 传递参数
/**
* 大显身手
*/
// 外观模式 简化获取元素
function $(id) {
return document.getElementById(id);
}
// 工程师 A
(function () {
// 追加一则消息
function addMsgItem(e) {
var text = e.args.text,
ul = $("msg"),
li = document.createElement("li"),
span = document.createElement("span");
li.innerHTML = text;
// 关闭按钮
span.onclick = function () {
ul.removeChild(li); // 移除留言
// 发布删除留言消息
Observer.fire("removeCommentMessage", {
num: -1,
});
};
// 添加删除按钮
li.appendChild(span);
// 添加留言节点
ul.appendChild(li);
}
// 注册添加评论信息
Observer.regist("addCommentMessage", addMsgItem);
})();
// 工程师 B
(function () {
// 更改用户消息数目
function changeMsgNum(e) {
// 获取需要增加的用户消息数目
var num = e.args.num;
// 增加用户消息数目并写入页面中
$("msg_num").innerHTML = parseInt($("msg_num").innerHTML) + num;
}
// 注册添加评论信息
Observer.regist("addCommentMessage", changeMsgNum).regist(
"removeCommentMessage",
changeMsgNum
);
})();
// 工程师 C
(function () {
// 用户点击提交按钮
$("user_submit").onclick = function () {
var text = $("user_input");
if (text.value === "") {
return;
}
// 发布一条评论
Observer.fire("addCommentMessage", {
text: text.value,
num: 1,
});
text.value = "";
};
})();