Javascript与浏览器交互的途径主要是事件的形式。事件是一种观察者的设计模式,对象可以发布时间,然后其它对象可以观察该对象,等待这些时刻到来并通过运行代码来响应。

观察者模式主要由主体和观察者组成。主体负责发布事件,同时观察者通过订阅这些事件来观察该主体。该模式的一个关键概念是主体并不知道观察者的任何事情,也就是说它可以独自存在并正常运行即使观察者不存在。从另一方面来讲观察者知道主体并能注册事件的回调函数(事件处理程序)。

事件是与DOM交互的最常用的方式,但也可以用于非DOM的代码中—通过实现自定义事件。自定义事件的机制其实就是创建一个可以管理事件的对象。让其他对象监听那些事件。

 1 function EventTarget(){
 2     this.handles={};
 3 }
 4 EventTarget.prototype = {
 5     constructor: EventTarget,
 6     addHandler:function(type,fn){
 7         if(!(this.handles[type] instanceof Array)){
 8             this.handles[type] = [];
 9         }
10         this.handles[type].push(fn);
11     },
12     fire:function(event){
13         if(!event.target){
14             event.target = this;
15         }
16         if(this.handles[event.type] instanceof Array){
17             var handles = this.handles[event.type];
18             for(var i=0,len=handles.length;i<len;i++){
19                 handles[i](event);
20             }
21         }
22     },
23     removeHandler:function(type,fn){
24         if (this.handles[type] instanceof Array) {
25             var handles = this.handles[type];
26             for (var i =0,len = handles.length;i<len;i++) {
27                 if(handles[i] == fn){
28                     break;
29                 }
30             };
31             handles.splice(i,1);
32         };
33     }
34 }

EventTarget有一个单独的属性,用于储存事件处理程序,三个方法中,addHandler用于添加事件处理程序,将事件添加到相应的事件型号的数组下,用push添加到数组的最后。removeHandler用于移除相应的事件。fire用于触发相应事件类型下的所有事件,通过for的形式循环触发。

要使用这个自定义事件类型,可以通过以下这个方式。

 1 function Person(name){
 2     this.name = name;
 3     this.etarget = new EventTarget();
 4 }
 5 Person.prototype = {
 6     constructor:Person,
 7     say:function(message){
 8         this.etarget.fire({type:'message',target:this,message:message});
 9     },
10     addMess:this.addMess = function(type,fn){
11         this.etarget.addHandler(type,fn);
12     }
13 }

这样就可以做到事件监听机制的使用了。在这里,一旦调用say方法,便触发了事件,它包含了事件的细节。同时在其中fire不是公开调用的,这段代码可以按以下方式使用。

1 var person = new Person('Tom');
2 person.addMess('message',function(event){
3     console.log(event.target.name+'says:'+event.message);
4 })
5 person.say('hello!!!');

 EXAMPLE:拖放

拖放是一种常见的用户界面模式,在HTML5中也有类似的API实现了该功能,在这里我们会用javascript和html来实现这个功能。

拖放的核心函数调用就是mousemove了,通过鼠标移动不断触发,并不断调整位置,实现拖动的连续性。

 1  var Dragdrop = (function(){
 2      var dragging = null;
 3      dragHandler = function(event){
 4          var event = event||window.event,
 5          target = event.target ||event.srcElement;
 6          switch(event.type){
 7              case 'mousedown':
 8                  if(target.className.indexOf('draggable') > -1){
 9                      dragging = target;
10                  }
11                  break;
12              case 'mousemove':
13                  if(dragging != null){
14                      dragging.style.left = event.pageX+'px';
15                      dragging.style.top = event.pageY+'px';
16                  }
17                  break;
18              case 'mouseup':
19                  dragging = null;
20                  break;
21          }
22      };
23      return {enable : function(){
24          document.addEventListener('mouseup',dragHandler,false);
25          document.addEventListener('mousemove',dragHandler,false);
26          document.addEventListener('mousedown',dragHandler,false);
27      },
28      disable: function(){
29          document.removeEventListener('mouseup',dragHandler,false);
30          document.removeEventListener('mousemove',dragHandler,false);
31          document.removeEventListener('mousedown',dragHandler,false);
32      }}
33  })();

现在还不能实现真正的交互,因为我们无法知道到底什么时候开始拖动,拖动结束。这时就可以用自定义事件来指示这个事件的发生。实现方式主要是先创建一个新的EventTarget的对象,然后添加enable和disable方法,最后返回这个对象:

 1 var Dragdrop = (function(){
 2     var dragEvent = new EventTarget(),
 3     dragging = null;
 4     dragHandler = function(event){
 5         var event = event||window.event,
 6         target = event.target ||event.srcElement;
 7         switch(event.type){
 8             case 'mousedown':
 9                 if(target.className.indexOf('draggable') > -1){
10                     dragging = target;
11                     dragEvent.fire({target:dragging,type:'dragstart'});
12                 }
13                 break;
14             case 'mousemove':
15                 if(dragging != null){
16                     dragging.style.left = event.pageX+'px';
17                     dragging.style.top = event.pageY+'px';
18                     dragEvent.fire({target:dragging,type:'dragmove',pos:{left:event.pageX,top:event.pageY}});
19                 }
20                 break;
21             case 'mouseup':
22                 dragging = null;
23                 dragEvent.fire({target:dragging,type:'dragstop'});
24                 break;
25         }
26     };
27     dragEvent.enable = function(){
28         document.addEventListener('mouseup',dragHandler,false);
29         document.addEventListener('mousemove',dragHandler,false);
30         document.addEventListener('mousedown',dragHandler,false);
31     };
32     dragEvent.disable = function(){
33         document.removeEventListener('mouseup',dragHandler,false);
34         document.removeEventListener('mousemove',dragHandler,false);
35         document.removeEventListener('mousedown',dragHandler,false);
36     };
37     return dragEvent;
38 })();

在对代码的主要改动处都以特殊的字体标出来了,这些改动使得Dragdrop对象支持了事件,使用方式如下:

1 Dragdrop.addHandler('dragstart',function(event){
2     console.log('drag start!');
3 });
4 Dragdrop.addHandler('dragmove',function(event){
5     console.log('dragmove,pos:'+event.pos.left+':'+event.pos.top);
6 });
7 Dragdrop.addHandler('dragstop',function(event){
8     console.log('dragstop');
9 });

这样就死的Dragdrop对象更加健壮了,就可以处理一下复杂的拖放事件了。

所有代码集合如下:

<html>
<head><script type="text/javascript">function EventTarget(){this.handles={};}EventTarget.prototype = {constructor: EventTarget,addHandler:function(type,fn){if(!(this.handles[type] instanceof Array)){this.handles[type] = [];}this.handles[type].push(fn);},fire:function(event){if(!event.target){event.target = this;}if(this.handles[event.type] instanceof Array){var handles = this.handles[event.type];for(var i=0,len=handles.length;i<len;i++){handles[i](event);}}},removeHandler:function(type,fn){if (this.handles[type] instanceof Array) {var handles = this.handles[type];for (var i =0,len = handles.length;i<len;i++) {if(handles[i] == fn){break;}};handles.splice(i,1);};}}var Dragdrop = (function(){var dragEvent = new EventTarget(),dragging = null;dragHandler = function(event){var event = event||window.event,target = event.target ||event.srcElement;switch(event.type){case 'mousedown':if(target.className.indexOf('draggable') > -1){dragging = target;dragEvent.fire({target:dragging,type:'dragstart'});}break;case 'mousemove':if(dragging != null){dragging.style.left = event.pageX+'px';dragging.style.top = event.pageY+'px';dragEvent.fire({target:dragging,type:'dragmove',pos:{left:event.pageX,top:event.pageY}});}break;case 'mouseup':dragging = null;dragEvent.fire({target:dragging,type:'dragstop'});break;}};dragEvent.enable = function(){document.addEventListener('mouseup',dragHandler,false);document.addEventListener('mousemove',dragHandler,false);document.addEventListener('mousedown',dragHandler,false);};dragEvent.disable = function(){document.removeEventListener('mouseup',dragHandler,false);document.removeEventListener('mousemove',dragHandler,false);document.removeEventListener('mousedown',dragHandler,false);};return dragEvent;})();/*function Person(name){this.name = name;this.etarget = new EventTarget();}Person.prototype = {constructor:Person,say:function(message){this.etarget.fire({type:'message',target:this,message:message});},addMess:this.addMess = function(type,fn){this.etarget.addHandler(type,fn);}}var person = new Person('Tom');person.addMess('message',function(event){console.log(event.target.name+'says:'+event.message);})person.say('hello!!!');*/Dragdrop.addHandler('dragstart',function(event){console.log('drag start!');});Dragdrop.addHandler('dragmove',function(event){console.log('dragmove,pos:'+event.pos.left+':'+event.pos.top);});Dragdrop.addHandler('dragstop',function(event){console.log('dragstop');});</script>
</head>
<body><div class="draggable" style="position:absolute;width:100px;height:100px;background:silver"></div>
</body>
</html>

View Code

转载于:https://www.cnblogs.com/cyITtech/p/3566897.html

js 高级应用 自定义事件相关推荐

  1. 【JS】512- JS 自定义事件如此简单!

    在前端开发世界中,JavaScript 和 HTML 之间往往通过 事件 来实现交互.其中多数为内置事件,本文主要介绍 JS自定义事件概念和实现方式,并结合案例详细分析自定义事件的原理.功能.应用及注 ...

  2. JS高级程序设计笔记——事件(一)

    一.事件流 假设有如下HTML代码: <!DOCTYPE html> <html> <head><title>Event</title> & ...

  3. html 自定义js,js 自定义事件

    js怎么自定义事件,并能让用on事件监听 你这个问题全部内容应该是如下吧: 在视频播放的时候,能够用on监听事件的触发,如下: player.on('pause',function(){ consol ...

  4. 使用 JS 关闭警告框及监听自定义事件(amaze ui)

    使用 JS 关闭警告框及监听自定义事件(amaze ui) 一.总结 1.jquery匿名函数:第8行,jquery匿名函数,$(function(){});,有没有很简单,只是少了jquery的前面 ...

  5. html 自动触发 事件,js自动触发事件自定义事件

    在有些情况下,我们需要程序逻辑自动触发元素的事件,例如js提供了click(), form提供了reset(),submit()等方法!在jquery中提供了trigger()方法帮助我们自动触发事件 ...

  6. vue中 点击事件的写法_vue中的事件:原生事件与自定义事件__Vue.js

    模板编译 processAttrs 对于ast attributes处理(v-on/@) 利用onRE与dirRE来捕获事件 这里最重要的就是dynamic的判断,vue中可以用动态参数来命名事件名称 ...

  7. Node.js: 如何继承 events 自定义事件及触发函数

    events 是node.js的核心api ,几乎大部分node.js 的api都继承 events 类(javascript中没有类,也不存在继承,确切说是模拟类和继承,点击查看) 比如我们常见的 ...

  8. Js高级(1) 事件11.30

    JS高级(1) 1.事件 概念:浏览器客户端上客户触发的行为都称为事件,所有的事件都是天生自带的,不需要我们去绑定,只需要我们去触发.通过obj.事件名=function(){} 事件名:onmous ...

  9. JS基础-事件模型(事件事件流自定义事件事件冒泡/代理)

    文章目录 一.事件与事件流 二.事件模型 1.DOM0级模型 2.IE事件模型 3.DOM2级模型 4.DOM3级事件处理方式 三.事件对象 四.事件绑定与解除 1.事件绑定 1.1对象.on事件名字 ...

最新文章

  1. java中二维数组求最大值代码。。。。。。不懂呀
  2. Android开发之2048安卓版
  3. kafak消费者从头开始消费(消费者组)
  4. VS工程切换cuda版本
  5. Java中的weak reference 和 soft reference
  6. php无限极,PHP无限极分类
  7. ajax跨域请求 html5,HTML5中使用postMessage实现Ajax跨域请求的方法
  8. import org.eclipse.californium.scandium.DTLSConnector;
  9. 谈薪资被 HR 怼了:估计你一辈子就是个程序员!气不过啊。。。
  10. Spark入门案例--出租车数据分析
  11. STM32驱动SPI FLASH(W25Q64)
  12. 郭盛华:互联网安全可能是下一个热门投资主题
  13. 语音识别/合成开源项目
  14. JavaScript中canvas绘制太极图案
  15. Windows Live Writer插件开发
  16. Java中对中国标准时间进行格式化(yyyy-MM-dd HH:mm:ss)两种方法
  17. 【Linux系统编程】进程地址空间和虚拟地址空间
  18. 如何学习3DMAX建模放样?
  19. Linux限制cpu睿频限制频率
  20. python考试报名费用_计算机python二级考试报名

热门文章

  1. LeetCode 914. 卡牌分组
  2. simpledateformat格式_大厂都是怎么用Java8代替SimpleDateFormat?
  3. 怎么查看电脑有没有python_使用python获取电脑的磁盘信息方法
  4. Jenkins分布式构建和部署(master-slave)
  5. ITester软件测试小栈长期持续在线征集
  6. SQL从入门到入魔之初入门
  7. 【Twitter】时序图神经网络
  8. Filecoin Gas基础费率降至0.23 nanoFIL
  9. Staked 回应节点遭到 slash 惩罚:由技术性问题导致,将全额赔偿受影响客户
  10. 1月20日到期的5.2万美元比特币期权数量超1万份