JS模仿AS3事件机制
练习下自定义事件的实现,想让JS可以用AS3的语法使用自定义事件,实现很简单,因为没考虑复杂的情况吧。试过后发现有些地方还是模仿不了,最主要不一样的地方是:
1.侦听函数没法自动绑定那个函数所在的object,必须手动把object传进去,像这样:dispatcher.addEventListener(SampleDispatcher.ACTION, e.action, e);
最后还要传“e”这个obj进去,否则函数action里的this不指向e
2.使用的时候继承十分麻烦,还得小心翼翼,看demo就知道了。
- //事件发送者类
- var EventDispatcher = function() {
- this.listeners = {};
- }
- EventDispatcher.prototype = {
- addEventListener: function(type, fn, obj) {
- if (!fn) {
- throw new Error("function no found");
- }
- if (!this.listeners[type]) {
- this.listeners[type] = [];
- }
- var lis = this.listeners[type];
- if (!lis) {
- lis = [];
- }
- lis.push({"fn": fn, "obj": obj});
- },
- dispatchEvent: function(event) {
- var lis = this.listeners[event.type];
- if (lis && lis.length) {
- for (var i=0; i<lis.length; i++) {
- event.target = this;
- lis[i].fn.call(lis[i].obj, event)
- }
- }
- },
- removeEventListener: function(type, fn, obj) {
- var lis = this.listeners[type],
- ret = false;
- if (!lis) {
- return false;
- }
- for (var i=lis.length-1; i>-1; i--) {
- if (!fn || (lis[i].fn == fn && lis[i].obj == obj)) {
- delete lis[i];
- lis.splice(i, 1);
- ret = true;
- }
- }
- if (!lis.length) {
- delete this.listeners[type];
- }
- return ret;
- },
- hasEventListener: function(type) {
- var lis = this.listeners[type]
- return lis && lis.length > 0 ? true: false;
- }
- }
- //事件类
- var Event = function(type) {
- this.type = type;
- this.target = null;
- }
- Event.prototype = {
- toString: function(){
- return this.type;
- },
- //clone功能未完善
- clone: function(){
- return new Event(this.type);
- }
- }
复制代码完全仿照《Actionscript3殿堂之路》里事件发送和处理的例子,写了个demo:
- //输出
- var trace = function(msg) {
- document.write("<p>" + msg + "</p>");
- }
- //OrderEvent事件类
- var OrderEvent = function(type) {
- OrderEvent.superclass.constructor.call(this, OrderEvent.ORDER_DISHES);
- this.dishes = [];
- }
- YAHOO.extend(OrderEvent, Event);
- OrderEvent.ORDER_DISHES = "order";
- //服务生Waiter类
- var Waiter = function() {}
- Waiter.prototype.replyOrderFood = function(event) {
- trace("你好," + event.target.name + "!你点的菜是:"+ event.dishes);
- trace("我马上吩咐厨房去做");
- }
- //客人类Customer
- var Customer = function(name) {
- Customer.superclass.constructor.call(this);
- this.name = name;
- }
- YAHOO.extend(Customer, EventDispatcher);
- Customer.prototype.order = function(dishes) {
- var orderDish = new OrderEvent();
- orderDish.dishes = dishes? dishes: ["农家小炒", "麻婆豆腐", "烤鱿鱼"];
- this.dispatchEvent(orderDish);
- }
- //生成客人和湘缘服务员
- var bang = new Customer("bang"),
- xiangyuanWaiter = new Waiter();
- //注册侦听器,讲服务员的replyOrderFood()方法注册为侦听“order”事件的侦听器
- bang.addEventListener(OrderEvent.ORDER_DISHES, xiangyuanWaiter.replyOrderFood, xiangyuanWaiter);
- //俺点菜了,菜单在俺这个类里面
- bang.order();
- //再点次菜,点些饮料
- bang.order(["鸡尾酒","咖啡"]);
- //吃完饭,移除侦听器
- bang.removeEventListener(OrderEvent.ORDER_DISHES, xiangyuanWaiter.replyOrderFood, xiangyuanWaiter);
复制代码
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论