自定义浏览器事件,模拟浏览器事件流
来源:互联网 发布:云计算 erp 编辑:程序博客网 时间:2024/04/28 14:29
简述
我认为,事件是我们前端最为熟悉的编程模式,在前端开发中能接触太多太多,而且相对而言,事件是一种相对容易理解,逻辑性高的的模式,对于优化组件/插件的逻辑是一个很好的应用模式。
这文章主要是用JavaScript实现3级dom事件机制,后面的更新会涉及应用倒组件开发当中。
- 浏览器事件一:事件的基础应用
- 浏览器事件二:浏览器是如何实现事件
- 浏览器事件三:自定义事件
如何实现
jQuery 实现方式
jQuery 是实现了一个独立的事件方法,甚至可以在自定义对象(object)上绑定事件,功能十分强大。
例:
//import jQuery$(selector).on('yourEvent',function(){ console.log('i m yourEvent handler');})$(selector).trigger('yourEvent')
上面例子就是jQuery 的自定义事件实现方式,下面再展示一个绑定对象上的事件,它其实是一个订阅/发布模式的实现 —> cowboy 实现的简易订阅/发布
例:
(function($) { var o = $({}); $.subscribe = function() { o.on.apply(o, arguments); }; $.unsubscribe = function() { o.off.apply(o, arguments); }; $.publish = function() { o.trigger.apply(o, arguments); };}(jQuery));
jQuery的事件实现原理这里不作陈述,这里提供Aaron的jQuery源码解析传送门
jQuery实现的优点
- 良好的维护性
jQuery是一个使用率最高的前端库,这意味这它能提供非常友好的文档,以及学习社区。从项目的角度上来看这是提高维护性的一个做法。 - 良好的兼容性
解决兼容性是意见相当麻烦琐碎的事情,如果没有充足的经验,很难再编码的的开始就预计到那些兼容问题,所以jQuery 本身某种层度就是提供兼容处理封装。
jQuery实现的缺点
- 依赖jQuery
实现上,我们并不是所有项目都需要依赖jQuery,jQuery本身虽然十分好,但是jq链式操作dom写出来的页面/组件,再可读性上确实不尽人意,业界都是认同那是一坨意大利面(特别是webapp项目)。所以其实从另一个层面上看,jQuery并不是一个十分好提高维护性的方案。 - 能实现的功能有限
如果单纯做组件抽象,或者基于监听响应实现的对象,jq的实现确实是满足并且能提供简洁的实现方法,但是在某些需求上不一定能满足,如:如果我们希望组件的实现逻辑更加清晰,希望加入一个事件响应流,能在组件之间链式传播。 - 性能上
jQuery事件实现内部也是已经实现事件的,如果在jq之上在添加自定义的事件功能,性能上必然有影响(不可控),性能影响不会很大,但做性能优化时会是一个问题。
任意对象绑定事件
在原生JavaScript对象,自定义的object 对象并没有事件的概念, 而实际上 我们希望某些组件拥有事件驱动,js拥有完整的事件驱动对象,但是我们开发者没有办法使用(第二章有提及),不过我们还是能基于官方的文档事件一个与js一样的事件对象。
官方自定义 eventtarget
我们从官方的事件文档中看到一个简单的事件驱动对象实现例子。
var eventTarget = function() { this.listeners = {};};eventTarget.prototype.listeners = null;eventTarget.prototype.addEventListener = function(type, callback) { if(!(type in this.listeners)) { this.listeners[type] = []; } this.listeners[type].push(callback);};eventTarget.prototype.removeEventListener = function(type, callback) { if(!(type in this.listeners)) { return; } var stack = this.listeners[type]; for(var i = 0, l = stack.length; i < l; i++) { if(stack[i] === callback){ stack.splice(i, 1); return this.removeEventListener(type, callback); } }};eventTarget.prototype.dispatchEvent = function(event) { if(!(event.type in this.listeners)) { return; } var stack = this.listeners[event.type]; event.target = this; for(var i = 0, l = stack.length; i < l; i++) { stack[i].call(this, event); }};
这个例子可以是我们实现自己事件的最顶层类。
如何绑定到自定义对象
假设我们已经有了 eventTarget对象,下面我们要做的就是把事件绑定到对象上
var component = function(){};component.prototype = new eventTarget();var com_1 = new component();com_1.addEventListener('click',function(){ console.log('i m listenning click event')});com_1.dispatchEvent(new MouseEvent('click')) //i m listenning click event
加入htmlElement事件流
htmlElement的事件流是独立的,实际上的C++在做事件流的传递,自定义的事件没法加入到这个事件流当中。
这种冒泡的事件流机制非常常见,在ios,Android中的事件驱动都是类似这种机制。在事件中这样的思想/机制能把事件的耦合度降低。在大型组件的事件逻辑中,加入这种机制个人认为是非常好的。
这里提供一个实现思路,鄙人愚见,请大神指点。
创建自己的对象的事件流
var flowEvent = function (parentNode) { this.listeners = {}; this.childrenNode = []; this.parentNode = parentNode; // 父节点 parentNode && parentNode.childrenNode.push(this) //加入父节点的子节点}flowEvent.prototype = new eventTarget(); //继承事件flowEvent.prototype.dispatchEvent = function (event) { //重写事件分发方法 if(!(event.type in this.listeners)) { return; } var stack = this.listeners[event.type]; //要独立lisenter event.target = this; for(var i = 0, l = stack.length; i < l; i++) { stack[i].call(this, event); } if(event.target){ //todo 加入阻止同类事件&阻止传递 this.childrenNode.length>0 && this.childrenNode.forEach(function (v) { v.dispatchEvent(event) }) }else{ this.parentNode && this.parentNode.dispatchEvent(event) }}
- 自定义浏览器事件,模拟浏览器事件流
- 模拟IE浏览器事件
- extjs的自定义事件和浏览器事件
- 浏览器 事件流
- 浏览器事件流
- 浏览器事件
- 浏览器事件
- 浏览器事件
- 浏览器事件
- safari浏览器实现模拟click点击事件
- 跨浏览器实现自定义事件处理
- JavaScript自定义跨浏览器事件处理工具
- 浏览器事件机制与自定义事件的实现
- 浏览器事件机制与自定义事件的实现
- 浏览器事件之鼠标事件
- 用户关闭浏览器事件
- 捕获浏览器关闭事件
- 浏览器关闭事件
- 通过sinacloud 部署自己的简单网站
- 函数之概览
- R tutorial 19 - handle error in Logistic Regression 逻辑回归 (2)
- eclipse出现的问题
- J2EE之反射中的class类(一)
- 自定义浏览器事件,模拟浏览器事件流
- R tutorial 20 - Logistic Regression 逻辑回归 (3)
- C语言动态内存管理
- Ranking
- ecshop数据库表14(ecs_article_cat)文章分类信息表
- 【SQL 基础】SQL的处理流程
- Django RuntimeError: maximum recursion depth exceeded
- 日常小结-经典IPC问题实现
- 数据库——导入数据出现警告/错误解决