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. android查看报错日志,android运行错误日志帮看下 不懂啊
  2. MySQL查询出错提示 --secure-file-priv解决方法
  3. Angular新建组件以及组件之间的调用
  4. Nhibernate 对view 查询的几种方法
  5. integer加1_利用Abaqus UEL开发自定义单元1
  6. 用位运算实现四则运算之加减乘除(用位运算求一个数的1/3)
  7. HDU多校2 - 6763 Total Eclipse(贪心+并查集)
  8. 操作系统:Linux 环境变量配置的 6 种方法!
  9. 基于以太坊发布属于自己的数字货币(代币)完整版
  10. 实现三元组表示的两个稀疏矩阵的加法_K-BERT | 基于知识图谱的语言表示模型
  11. Java数据库篇6——多表查询
  12. 运营商缺的是应用还是想法--广州晨皓
  13. 数据--第41棵 - 图的存储结构
  14. 数学猜想验证步骤_10大仍未解开的数学难题
  15. c语言ftell函数,C语言中ftell函数的使用方法
  16. PMP之项目风险管理
  17. fid和is_fid解释
  18. 互联网广告行业术语及缩写
  19. HTML、纯JS实现语音播放,实现定时刻播放
  20. 【中等】Leetcode-旋转链表//题目分析//首尾相连

热门文章

  1. LeetCode 5364. 按既定顺序创建目标数组
  2. PAT1002. 写出这个数
  3. 远程桌面连接_Win10 系统远程桌面连接怎么打开
  4. mate10支持html,华为Mate 10再曝光:配置强劲,全面屏十分惊艳
  5. 测试面试题集-3.生活物品测试:行李箱、电梯、洗衣机
  6. 民熙科技发布货物资产数字化系统“识物链”2.0版本
  7. BTC36 CLUB国际基金拟向美国SEC提交那斯达克股票上市申请
  8. 欧科云链OKLink:以太坊七日链上交易量上升30.67%
  9. 风控扫盲:巴塞尔下的分池与量化风控岗
  10. 关于GPS定位反欺诈研究