说在前面:写js时候,当一个变量一旦发生变化,就自动执行相应的程序,而不用手动执行,js-signals可以很方便的解决这个问题。
一.js-signals简介
js-signals是用于在JavaScript中的软件组件之间定义和触发基于事件的消息的库,它是一个类似于Event Emitter / Dispatcher或Pub / Sub系统的事件/消息系统,主要区别在于每个事件类型都有自己的控制器功能,而不依赖于字符串来广播/订阅事件,它还具有通常在其他系统上不可用的一些额外功能。
本人因为项目需要,寻找关于js-signals的学习资料,发现都是英文的,所以自己写个学习小结,也希望帮助后来需要学习的同学们。后面第三部分用户指南,会详细介绍js-signals的具体用法。
github:https://github.com/millermedeiros/js-signals
example:http://www.javascriptoo.com/js-signals
官方使用详解:https://millermedeiros.github.io/js-signals/
官方documentation:https://millermedeiros.github.io/js-signals/docs/
作者博客:http://blog.millermedeiros.com/
http://blog.millermedeiros.com/js-signals-custom-eventmessaging-system-for-javascript/
二.不同设计模式实现之间的比较
命名约定
建议您始终以过去时态命名信号。这个惯例是基于AS3-Signals的建议,其背后的原因是避免与常规属性混淆并保持一致性。尝试组合多个单词,如果您尝试描述的事件没有过去时的形式或如果您有命名冲突。
三.用法示例
1.引入js-signals:
node.js
var Signal = require('signals');
var mySignal = new Signal();
AMD
define(['signals'], function(Signal){
var mySignal = new Signal();
});
Browser globals
<script src="js/libs/signals.min.js"></script>
<script>
var Signal = signals.Signal;
var mySignal = new Signal();
</script>
2.声明Signal对象:
//store local reference for brevity
var Signal = signals.Signal;
3.用户自定义对象:
//custom object that dispatch signals
var myObject = {
started : new Signal(), //past tense is the recommended signal naming convention
stopped : new Signal()
};
4.添加/调度/删除单个监听器(Single Listener):给started 信号绑定事件 onstarted(function)
function onStarted(param1, param2){
alert(param1 + param2);
}
myObject.started.add(onStarted); //添加监听器
myObject.started.dispatch('foo', 'bar'); //给 started 信号绑定的事件传送参数(param1, param2),即('foo', 'bar')
myObject.started.remove(onStarted); //删除监听器
5.添加/调度/删除多个监听器(Multiple Listeners)
function onStopped(){
alert('stopped');
}
function onStopped2(){
alert('stopped listener 2');
}
myObject.stopped.add(onStopped);
myObject.stopped.add(onStopped2);
myObject.stopped.dispatch();
myObject.stopped.removeAll(); //remove all listeners of the `stopped` signal
6.多次调度(Multiple Dispatches),也就是多次运行handler
var i = 0;
myObject.started.add(function(){
i += 1;
alert(i);
});
myObject.started.dispatch(); //will alert 1,调度一次
myObject.started.dispatch(); //will alert 2,调度两次
7.Multiple Dispatches + addOnce()
var i = 0;
myObject.started.addOnce(function(){
i += 1;
alert(i);
});
myObject.started.dispatch(); //will alert 1
myObject.started.dispatch(); //nothing happens
8.启用/禁用信号(Enable/Disable Signal)
var i = 0;
myObject.started.add(function(){
i += 1;
alert(i);
});
myObject.started.dispatch(); //will alert 1
myObject.started.active = false;
myObject.started.dispatch(); //nothing happens
myObject.started.active = true;
myObject.started.dispatch(); //will alert 2
9.Stop/Halt Propagation(停止/终止 传播)
方法一:直接调用signal.halt()停止
myObject.started.add(function(){
myObject.started.halt(); //防止下一个listener在队列中被执行
});
myObject.started.add(
function(){ alert('second listener'); //不会被调用,因为第一个监听器停止传播
});
myObject.started.dispatch();
方法二:通过返回值 false 停止
myObject.started.add(function(){
return false; //if handler returns `false` will also stop propagation
});
myObject.started.add(function(){
alert('second listener'); //won't be called since first listener stops propagation
});
myObject.started.dispatch();
10.设置侦听器处理程序的执行上下文
var foo = 'bar';
var obj = {
foo : 10
};
function handler1(){
alert(this.foo);
}
function handler2(){
alert(this.foo);
}
//note that you cannot add the same handler twice to the same signal without removing it first
myObject.started.add(handler1); //默认执行上下文,参数是windows.foo
myObject.started.add(handler2, obj); //设置不同的上下文,传入obj.foo
myObject.started.dispatch(); //first handler will alert "bar", second will alert "10".
11.设置监听器的优先级
var handler1 = function(){
alert('foo');
};
var handler2 = function(){
alert('bar');
};
myObject.started.add(handler1); //默认优先级为0,add(handler,context,priority)
myObject.started.add(handler2, null, 2); //设置优先级为2,'handler2' 将比'handler1' 提早运行
myObject.started.dispatch(); //will alert "bar" than "foo"
12.启用/禁用单个SignalBinding
var handler1 = function(){
alert('foo bar');
};
var handler2 = function(){
alert('lorem ipsum');
};
var binding1 = myObject.started.add(handler1); //methods `add()` and `addOnce()` returns a SignalBinding object
myObject.started.add(handler2);
myObject.started.dispatch(); //execute handler1 , will alert "foo bar" than "lorem ipsum"
binding1.active = false; //disable a single binding
myObject.started.dispatch(); //will alert "lorem ipsum"
binding1.active = true;
myObject.started.dispatch(); //will alert "foo bar" than "lorem ipsum"
13.手动执行信号处理程序:不用signal.dispatch(),用 SignalBinding.execute()
var handler = function(){
alert('foo bar');
};
var binding = myObject.started.add(handler); //methods `add()` and `addOnce()` returns a SignalBinding object
binding.execute(); //will alert "foo bar"
14.检索匿名监听器:本人觉得可能是系统默认绑定的handler
var binding = myObject.started.add(function(){
alert('foo bar');
});
var handler = binding.getListener(); //reference to the anonymous function
15.删除/分离匿名监听器
var binding = myObject.started.add(function(){
alert('foo bar');
});
myObject.started.dispatch(); //will alert "foo bar"
binding.detach();//分离监听器
alert(binding.isBound()); //will alert `false`
myObject.started.dispatch(); //nothing happens
16.检查绑定是否只执行一次
var binding1 = myObject.started.add(function(){
alert('foo bar');
});
var binding2 = myObject.started.addOnce(function(){
alert('foo bar');
});
alert(binding1.isOnce()); //alert "false"
alert(binding2.isOnce()); //alert "true"
17.更改监听器执行上下文
var foo = 'bar';
var obj = {
foo : "it's over 9000!"
};
var binding = myObject.started.add(function(){
alert(this.foo);//this 指的是 windows,也就是说默认绑定的上下文环境是windows
});
myObject.started.dispatch(); //will alert "bar"
binding.context = obj;
myObject.started.dispatch(); //will alert "it's over 9000!"
18.将默认参数添加到信号调度
var binding = myObject.started.add(function(a, b, c){
alert(a +' '+ b +' '+ c);
});
binding.params = ['lorem', 'ipsum']; //set default parameters of the binding
myObject.started.dispatch('dolor'); //will alert "lorem ipsum dolor"
类似于:
var binding = myObject.started.add(function(a, b, c){
alert(a +' '+ b +' '+ c);
});
myObject.started.dispatch('lorem', 'ipsum','dolor'); //will alert "lorem ipsum dolor"
19.检查信号是否绑定某个特定的监听器
function onStart(a){
console.log(a);
}
myObject.started.add(onStart);
myObject.started.has(onStart); // true
20.记住以前分派的值/忘记值
myObject.started.memorize = true; // default is false
myObject.started.dispatch('foo');
// add()/addOnce() will automatically fire listener if signal was dispatched before
// will log "foo" since it keeps record of previously dispatched values
myObject.started.addOnce(console.log, console);
// dispatching a new value will overwrite the "memory"
myObject.started.dispatch('lorem');
// will log "lorem"
myObject.started.addOnce(console.log, console);
myObject.started.forget(); // forget previously dispatched values (reset signal state)
myObject.started.addOnce(console.log, console); // won't log till next dispatch (since it "forgot")
myObject.started.dispatch('bar'); // log "bar"
21.一次性监听多个信号见 CompoundSignal repository
四.库函数解析
1. signals ,Signals命名空间
2.Signal类
var mySignal = new Signal();//mySignal 是 Signals 类的一个对象。
Signal类属性
mySignal.active = false/true; //该信号监听调度是否停止,默认true可用
mySignal.memorize = false/true; //该信号是否记录之前的调度参数并且自动执行,默认为false不记录
mySignal.VERSION = ''; //记录当前信号的版本
Signals类方法
add();添加监听器
//add(listener, listenerContext, priority);
//listener 属于function类型,是信号操作函数
//listenerContext 属于object类型,是监听器的执行上下文环境,可选
//priority 属于Number类型,是该监听器的优先级,高优先级的先执行,默认为0,可选
//返回值是 SignalBinding 类型
mySignal.add(listener, listenerContext, priority);
addOnce();添加一次性监听器,运行完一次即可自动remove
//add(listener, listenerContext, priority);
//listener 属于function类型,是信号操作函数
//listenerContext 属于object类型,是监听器的执行上下文环境,可选
//priority 属于Number类型,是该监听器的优先级,高优先级的先执行,默认为0,可选
//返回值是 SignalBinding 类型
mySignal.addOnce(listener, listenerContext, priority);
dispatch();调度/广播信号到所有监听器,加入队列,即让监听器运行
//dispatch(params),paras可选
mySignal.dispatch();
dispose();删除所有相关的信号对象和绑定,无返回值
mySignal.dispose();
forget();清除记忆的arguments,无返回值
mySignal.forget();
getNumListeners();返回该信号绑定的监听器的个数
mySignal.getNumListeners();
halt();停止分发事件,blocking the dispatch to next listeners on the queue.
mySignal.halt();
has();检查该信号是否与特定监听器绑定
//listener ; 监听器的执行函数
//context ;执行的上下文环境,可选
// 返回值为true 或者 false
mySignal.has(listener, context);
remove();删除监听器
//listener ; 监听器的执行函数
//context ;执行的上下文环境,可选
//返回监听器的执行函数handler
mySignal.remove(listener, context);
removeAll();删除该信号的所有监听器
mySignal.removeAll();
toString();返回当前的object的
3.SignalBinding类
var binding = myObject.started.add(function(){
alert('foo bar');
});
等同于
//SignalBinding(signal, listener, isOnce, listenerContext(可选), priority(可选))
var
binding = new SignalBinding(myObject.started, handler, false, myObject, 0)
function handler(){
alert('foo bar');
}
SignalBinding类属性
binding.active = false/true; //该信号监听调度是否停止,默认true可用
binding.context = object; //绑定的上下文环境
binding.params = ''; //默认在Signal.dispatch()期间传递给监听器的参数
SignalBinding类方法
binding.detach();//分离信号和监听器
binding.execute();//手动执行
binding.getListener();//返回绑定的特定监听函数
binding.getSignal();//返回绑定的特定信号量
binding.isBound();//判断是否绑定成功,true or false
binding.isOnce();//判断是否是一次绑定
binding.toString()//转换为字符串
函数简易查询索引地址:https://millermedeiros.github.io/js-signals/docs/symbolindex.html
五.应用实例
<!DOCTYPE html>
<html>
<head>
<title>test signal</title>
<script type="text/javascript" src="signals.js"></script>
</head>
<body>
<script type="text/javascript">
//custom object that defines a `started` signal
var myObject = {
started: new signals.Signal()
};
// a handler function
function onStarted(param1, param2){
alert(param1 + param2);
}
// listen for the `started` signal and then run the `onStarted` handler
myObject.started.add(onStarted); //add listener
// dispatch the `started` signal, running the handler, passing in parameters
myObject.started.dispatch('foo', 'bar');
</script>
</body>
</html>
来源:oschina
链接:https://my.oschina.net/u/4340310/blog/4319723