`
keepwork
  • 浏览: 330668 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

EXT--事件

    博客分类:
  • EXT
ext 
阅读更多
 开发者博客www.developsearch.com

 

前言

 

工作中用ExtJS有一段时间了,Ext丰富的UI组件大大的提高了开发B/S应用的效率。虽然近期工作中天天都用到ExtJS,但很少对ExtJS框架原理性的东西进行过深入学习,这两天花了些时间学习了下。我并不推荐大家去研究ExtJS框架的源码,虽然可以学习其中的思想和原理,但太浪费精力了,除非你要自己写框架。

对于ExtJS这种框架,非遇到“杂症”的时候我觉得也没必要去研究其源码和底层的原理,对其一些机制大致有个概念,懂得怎么用就行,这也是本篇博文的主要目的。

 

Ext自己的事件机制

 

Ext中的事件遵循树状模型,和事件相关的类主要有这么几个:Ext.util.Observable、Ext.lib.Event、Ext.EventManager和Ext.EventObject。

Ext使用Ext.lib.Event、Ext.EventManager和Ext.EventObject对原生浏览器事件进行了封装,最后给我们用的是一套统一的跨浏览器的通用事件接口。HTML元素本身已经支持事件,为什么基本上所有的主流JS框架都要实现自己的事件机制呢?一个最主要的原因是HTML元素对事件的处理是通过简单的单一绑定实现的,如果不进行封装,事件只能绑定到一个事件处理句柄。如下面代码所示:

var e = document.getElementById("test");
e.onclick = function() { alert("handler1") };
e.onclick = function() { alert("handler2") };

 单击test按钮后会发现只会弹出一个显示"handler2"的提示框,因为第一个被覆盖。而使用像Ext、jQuery这样的框架就不用担心这个问题,同一个事件可以依次绑定多个事件处理句柄,如下代码所示:

Ext.onReady(function () {
    var test = Ext.get("test");
    test.on("click", function () {
        alert("handler1");
    });
    test.on("click", function () {
        alert("handler2");
    });
});

 

Ext实现自己的事件机制,原因很多,比如为了兼容不同浏览器之间的差异等。Ext对原生浏览器事件的封装都在上面所说的几个类中,如果在项目中要熟练应用Ext,是非常有必要了解一下和事件相关的类和常用函数的。下面开始介绍这些类和它们的功能。

 

Ext.util.Observable

 

Ext.util.Observable在Ext事件模型中有着举足轻重的地位,位于Ext组件的顶端,为Ext组件提供处理事件的最基本的功能。所有继承自Ext.util.Observable类的控件都可以支持事件。可以为这些继承了Ext.util.Observable的对象定义一些事件,然后为这此事件配置监听器。当某个事件触发时,Ext会自动调用对应的监听器,这些就是Ext的事件模型。
下面通过继承Ext.util.Observable来实现一个支持事件的对象:

Ext.onReady(function () {
    //定义一个Person类。
    function Person(name) {
        this.name = name;
        this.addEvents("walk", "eat");
        this.superclass.constructor.call(this);
    }

    //1、让Person继承Ext.util.Observable的所有属性,
    //   这样Person类构造器中的addEvents和Person.superclass.constructor.call()在实例创建时才会起作用。
    //   Person的实例就可以应用Ext的事件相关的on、un等方法和在Person类构造器中的addEvents和Person.superclass.constructor.call()了。
    //2、添加一个info()函数,让它返回Person信息。
    Ext.extend(Person, Ext.util.Observable, {
        info: function (event) {
            return this.name + " is " + (event ? "ing" : "doing nothing") + ".";
        }
    });

    //1、创建一个Person实例,然后为它的事件配置好监听器。
    //2、on是addListener的简写,un是removeListener简写
    var person = new Person("Liam");
    person.on("walk", function () {
        this.state = "walk";
        Ext.Msg.alert("event", this.name + " is walking.");
    });
    person.on("eat", function (meal) {
        this.state = "eat";
        Ext.Msg.alert("event", this.name + " is eating " + meal + ".");
    });

    //测试效果
    Ext.get("btnWalk").on("click", function () {
        person.fireEvent("walk");
    });
    Ext.get("btnEat").on("click", function () {
        person.fireEvent("eat", "breakfast");
    });
    Ext.get("btnInfo").on("click", function () {
        Ext.Msg.alert("info", person.info(person.state));
    });
});

 

以上代码展示了在Ext中如何通过继承Ext.util.Observable给一个类自定义事件,到这,我们大概也了解了addListener/on、addEvents和fireEvent这些函数的基本用法,removeListener/un函数相关内容还会在本文后面介绍。如果要了解Ext.util.Observable的其他细节,可看看Ext官方API文档的介绍。

 

Ext.lib.Event

 

Ext.lib.Event是一个工具类,它封装了不同浏览器的事件处理函数,为上层组件提供了统一功能接口。
对于这个工具类,Ext自带的文档中没有关于这个类的说明,实际中也很少直接用到这个类,只是与事件相关的那些操作最后都会归结为对这些底层函数的调用。
Ext.lib.Event中定义了以下几个主要函数。

getX()、getY()、getXY(),获得发生的事件在页面中的坐标位置:

Ext.get("test").on("click", function () {
    alert(this.getX() + "," + this.getY());
});

 

getTarget(),返回事件的目标元素,该函数用来统一IE和其他浏览器使用的e.target和e.srcElement:

 

Ext.get("test").on("click", function (e) {
    var test = e.getTarget();
    alert(test.value);
});

 

on()和un(),这两个函数就不用多说了。

preventDefault(),用于取消浏览器当前事件所执行的默认操作,比如阻止页面跳转。使用这个函数,我是不是可以阻止弹出浏览器鼠标右键菜单呢?我用下面的代码试了下,结果右键菜单并没有被阻止,谁能告诉我为什么?

//鼠标右键事件没有被阻止?
Ext.getDoc().on("mousedown ", function (e) {
    if (e.button == "2")
        e.preventDefault();
});

 stopPropagation(),停止事件传递。比如divTest元素订阅了click事件,它的子元素btnTest被click时,父元素divTest的click事件也会被触发,stopPropagation()就是用来阻止这种事件冒泡的发生:

Ext.get("divTest").on("click", function () {
    alert("divTest clicked!");
});
Ext.get("btnTest").on("click", function (e) {
    alert("btnTest clicked!");
    //阻止事件冒泡
    e.stopPropagation();
});

 

stopEvent(),停止一个事件,相当于调用preventDefault()和stopPropagation()两个函数。

另外还有一些几乎用不上的函数onAvailable()、getRelatedTarget()等,就不再一一介绍了。

再次说明一下,Ext.lib.Event这个类实际中很少直接用到,用的只是上面讲的一些底层通用函数,并供一些其它和事件相关的类如Ext.EventManager和Ext.EventObject的底层的调用。

 

Ext.EventManager

 

Ext.EventManager,作为事件管理器,定义了一系列事件相关的处理函数。其中最常用的就是onDocumentReady和onWindowResize了。

我们常用的Ext.onReady()就是Ext.EventManager.onDocumentReady()的简写形式,它会在页面文档渲染完毕但图片等资源文件还未下载时调用启动函数。

这里有必要提一下众所周知人人共愤的window.onresize事件:

function resizeProcess(width, height) {
    var p = document.createElement("p");
    p.innerText ="时间:" + new Date().toLocaleTimeString() + ", 宽:" + width + ", 高:" + height;
    document.body.appendChild(p);
}
//原生浏览器resize事件
window.onresize = function () {
    resizeProcess(document.documentElement.clientWidth, document.documentElement.clientWidth);
}

 当为window.onresize添加了事件处理函数resizeProcess后,会发现resizeProcess会被执行多次,尤其是IE6、IE7、IE8,还会出现假死,动不动就崩掉。

 

 如图,IE8浏览器会直接死掉。真心深恶通绝IE6、IE7、IE8,要是有朝一日能因为IE11的出现,IE6到IE10都被消灭,那该是多么大快人心的事!
window.onresize事件处理函数被多次乃至无数次触发的问题,网上有不少解决方案,但稍微理想点的方案用起来都挺麻烦。Ext.EventManager下的onWindowResize事件处理函数就非常好的解决了这个问题:

Ext.onReady(function () {
    function resizeProcess(width, height) {
        var p = document.createElement("p");
        p.innerText = "时间:" + new Date().toLocaleTimeString() + ", 宽:" + width + ", 高:" + height;
        document.body.appendChild(p);
    }
    //Ext封装的resize事件
    Ext.EventManager.onWindowResize(function (width, height) {
        resizeProcess(width, height);
    });
});

 

 

如图,每次改变窗口大小,resizeProcess只执行了一次。

Ext.EventManager还有on/addListener、un/removeListener等函数,这些函数都是都过Ext.lib.Event实现的,这里就不再累述了。

 

Ext.EventObject

 

Ext.EventObject是对事件的封装,它提供了丰富的工具函数,帮助我们获得事件相关的信息。通过Ext.EventObject帮助文档可以了解到,它包含的许多函数都与Ext.lib.Event中的函数功能是相同甚至同名的,如getPageX()、getPageY()、getPageXY()和getTarget()等,这些函数实际上都是通过Ext.lib.Event实现的。

Ext.EventObject对Ext.lib.Event扩展的部分是对鼠标事件和按键事件的增强,定义了一系列按键,可以用来判断某个键是否被按下:

 

Ext.get("text").on("keypress", function (e) {
    if (e.getKey() == Ext.EventObject.SPACE) {
        Ext.Msg.alert("提示", "你按了空格键!");
    }
});

 

Ext.EventObject将浏览器事件和自定义事件结合在一起使用,是对事件的封装。如果要获得浏览器原始的事件,可通过Ext.EventObject的browserEvent获得。但这种原生事件在不同浏览器中可能会有很大差异,所以Ext.EventObject虽然提供该功能,但一般不建议使用。

 

给Ext组件添加事件处理函数

 

添加原生浏览器事件处理函数

我们已经知道可以通过 on/addListener的方式给HTML元素添加事件处理函数,Ext组件也可以通过这种方式添加,如下代码所示:

 

var text = new Ext.form.TextField({
    id: "text", renderTo: Ext.getBody()
});
Ext.get("text").on("mouseover", function (e) {
    alert("mouse over.");
});
//也可以一次添加多个事件处理函数:
Ext.get("text").on({
    "mouseover": function (e) {
        alert("mouse over.");
    },
    "mouseout": function (e) {
        alert("mouse out.");
    }
});

 

这种方式可以给任何原生浏览器所支持的事件添加处理函数。但这种方式不能用于容器类的Ext组件,如Ext.form.FieldSet、Ext.form.FormPanel和Ext.Toolbar等。

添加Ext组件事件处理函数

几乎所有Ext组件根据自身的特性对原生事件都行了扩展,另外封装了一套属于自己的事件,这些事件的处理函数会能接收到与该组件相关的事件参数信息。下面代码是给Ext组件添加事件的两种方式:

 

var text1 = new Ext.form.TextField({
    id: "text1", renderTo: Ext.getBody()
});
//任何一个关于导航类键(arrows、tab、enter、esc等)被敲击则触发此事件
Ext.getCmp("tex1t").on("specialkey", function (field,e) {
    alert(field.getValue() + "," + e.getKey());
});

//也可以在组件创建的时候添加事件处理函数:
var text2 = new Ext.form.TextField({
    id: "text2", renderTo: Ext.getBody(),
    listeners: {
        change: function (field, newValue, oldValue) {
            alert("change:" + newValue);
        },
        blur: function (field) {
            alert("blur:" + field.getValue());
        }
    }
});

 

但这种方式并不支持所有的原生浏览器事件,比如给 Ext.form.TextField 组件通过上面的方式添加 mosuseover 事件处理函数是没有效果的。

还有一种通过 handler 属性给 Ext 按钮组件添加事件的方式,这种方式只针对Ext按钮组件,如下:

 

var button = new Ext.Button({
    id: 'button',
    text:'按钮',
    renderTo: Ext.getBody(),
    handler: function () {
        alert("Clicked!!!");
    }
});

 

移除事件处理函数

 

我们已经知道可通过un/removeListener移除某个事件处理函数。值得注意的事,对于原生浏览器事件,用Ext.fly获得元素的方式添加的事件处理函数必须用Ext.fly获得元素的方式移除,同理,Ext.get也是一样。但一般我们用Ext.fly而不用Ext.get获得元素的方式添加事件处理函数,原因Ext.fly更省内存。对于Ext组件事件,则必须通过Ext.getCmp获得组件的方式移除事件处理函数。如下代码所示:

 

var text = new Ext.form.TextField({
    id: "text", renderTo: Ext.getBody(),
    listeners: {
        change: function (field, n, o) {
            alert("new value : " + n);
        }
    }
});
//事件处理函数
var handlerFn = function (e) {
    alert("mouse over.");
};

//添加mouseover事件处理函数。
Ext.get("text").on("mouseover", handlerFn);
//移除mouseover事件指定引用的处理函数。
Ext.get("text").removeListener("mouseover", handlerFn);
//移除mouseover事件所有的处理函数。
Ext.get("text").removeListener("mouseover");
//用fly获得元素的方式不能移除mouseover处理函数,因为该处理函数是通过get获取元素添加的。
Ext.fly("text").removeListener("mouseover");
//同样,用getCmp获得组件的方式也不能移除mouseover处理函数。
Ext.getCmp("text").removeListener("mouseover");
//移除text元素所有原生浏览器事件的所有处理函数。
Ext.get("text").removeAllListeners();
//获得组件的方式移除change事件所有的处理函数。
Ext.getCmp("text").removeListener("change");

 

对事件的一些额外的控制

 

事件的额外控制包括让事件只被触发一次、延迟事件处理和控制多次触发事件的间隔等。通过on/addListener函数的第4个参数的属性来实现,让我们通过下面代码来看看常见的几个:

 

var button = new Ext.Button({
    id: 'button',
    text: '按钮',
    renderTo: Ext.getBody()
});
button.on("click",
    function () {
        var el = document.createElement("p");
        el.innerHTML = new Date().toLocaleTimeString();
        document.body.appendChild(el);
    }, this, {
        single: true,//只会执行一次单击事件。
        buffer: 1000, //间隔1秒响应,在响应前点击无效。
        delay: 1000,//从事件触发开始,1后才会执行处理函数。
        stopPropagattion: true,//事件不会向上传递(即停止事件冒泡)。
        preventDefault: true //停止事件默认操作。
        //...
    }
);

 

结束语

 

ExtJS的事件模型比较复杂,提供的事件处理函数也非常之多,本文短短篇幅不可能面面具到,只是把常用的做了简单介绍。本人用ExtJS也不久,不免有错差。
希望园友们不吝指教,多多交流,随手点个推荐,以助大家在ExtJS学习之路上快束进步。

  • 大小: 36.3 KB
  • 大小: 29.9 KB
分享到:
评论

相关推荐

    Ext-Gantt和相关js如ext-all.js ext-base

    `ext-base.js`是Ext JS的基础文件,包含框架的基本结构和核心功能,如类系统、事件系统和DOM操作。在一些情况下,如果项目对加载速度有较高要求,可以先加载`ext-base.js`,然后再按需加载其他组件,以实现按需加载...

    ext-base.js

    3. **事件系统**:EXT的事件模型是其交互性的重要组成部分,"ext-base.js"中定义了事件的注册、触发和解绑等操作,使得组件之间能够通过事件进行通信。 4. **DOM操作**:EXT对DOM操作进行了封装,提供了便利的方法...

    EXT-GWT(GXT) 2.2.4 JAVA API DOC chm 版

    8. **事件处理**:EXT-GWT提供了丰富的事件处理机制,包括组件间的事件监听和传播,使得开发者能够方便地响应用户操作。 9. **工具栏与菜单**:EXT-GWT提供工具栏和菜单组件,可以创建复杂的交互式菜单和快捷工具栏...

    搭建简单的EXT-GWT(GXT)的开发环境(四)ext-gwt(gxt)结合google map第三版开发

    4. **交互与事件处理**:EXT-GWT Map组件支持多种交互,例如点击地图触发事件。你可以通过监听`MapEvent`并处理它们来实现自定义功能。 5. **样式与主题**:EXT-GWT提供了多样的主题,你可以选择一个与你的应用风格...

    EXT-GWT(GXT)2.2.3 API DOC.zip

    EXT-GWT,全称为Ext GWT,是Sencha公司开发的一个强大的Java库,用于构建富互联网应用程序(RIA)。GXT是EXT-GWT的扩展,它提供了更多组件、样式和功能,使得开发者能够创建出与桌面应用相媲美的用户体验。GXT 2.2.3...

    ext-js3.2 中文API,例子,包全都有

    EXT-JS的API文档是理解和使用其功能的关键,中文版的API文档对于中文使用者来说更加友好,能够帮助开发者快速查找和理解各种类、方法、事件等。API文档详细介绍了EXT-JS3.2中的每一个组件、函数和配置选项,如Grid...

    ext-d3-pivot-d3-component.zip

    学习EXT-D3和Pivot-D3,开发者需要掌握EXT JS的基本知识,理解其组件体系和事件模型;同时,还需要熟悉D3.js的数据操作和绘图API。对于Pivot-D3,还需了解数据透视表的概念和操作方式。通过熟练掌握这些技术,开发者...

    ext-air-3.1.0和ext-core-3.1.0

    - **功能**:包括DOM操作、事件处理、动画效果、AJAX通信、拖放功能等基础组件,适用于那些不需要完整Ext JS库的轻量级项目。 - **优势**:代码体积小,加载速度快,适合对性能有较高要求的网站或应用。 - **API*...

    磁盘目录树(EXT-js)

    5. **事件处理**:EXT-js提供了丰富的事件机制,如`itemclick`、`itemcontextmenu`等,你可以根据需要绑定事件处理器,实现点击目录时打开、右键菜单时的上下文操作等。 6. **自定义图标**:通过设置TreeNode的`...

    gwt-ext-tree

    3. **事件处理(Event Handling)**:在 GWT-Ext-Tree 中,你可以监听并处理各种树形控件的事件,如节点点击、展开、折叠等。这些事件可以触发相应的业务逻辑,实现更丰富的交互功能。 4. **样式和主题(Styles and...

    Ext-js 2.2

    5. **事件驱动**:所有组件都支持事件监听和触发,使得用户交互和组件间的通信变得简单。 6. **表单处理**:Ext-js 2.2 包含强大的表单组件和表单处理功能,支持各种输入控件、验证和数据提交。 7. **图表组件**:...

    ext-4.0.0.jsb2.rar

    理解组件体系结构、事件处理、数据绑定以及如何使用布局和组件是入门的关键。 5. **最佳实践**:在实际开发中,需要注意遵循模块化原则,合理使用Ext JS的类系统,以及充分利用其强大的组件库。同时,性能优化是不...

    ext-5.1.1-trial

    标题中的"ext-5.1.1-trial"指的是EXTJS框架的5.1.1版本的试用版。EXTJS 5.1.1是该框架的一个重要迭代,包含了众多功能增强和性能优化,旨在提升用户体验和开发者的开发效率。 EXTJS的核心特性包括组件化UI设计、...

    ext-2.2.zip Oozie的web界面安装所需要的包

    它允许用户定义复杂的作业依赖关系,形成工作流,并且能够根据预设的时间间隔或事件触发作业执行。 "大数据"标签则暗示了Oozie在处理大规模数据时的角色。在大数据环境中,有效的作业管理和调度至关重要,因为这些...

    ext-4.0.0jar.src

    通过修改和扩展这些文件,开发者可以创建自定义的组件和应用程序,利用Ext JS强大的布局管理、数据绑定和事件处理能力。 此外,由于文件大小限制,API文档可能被分开上传,开发者需要查找并下载这些文档以获得完整...

    ext-gwt分页 鉴于网上关于ext-gwt的技术文章很少代码页很少本着开源的精神本人特地写了一个分页的组件供大家学习欢迎下载

    5. **处理分页事件**:当用户点击分页按钮时,paging toolbar会自动触发`load`事件,你可以监听这个事件,更新Store以加载新数据。 6. **服务器端处理**:服务器端需要根据接收到的分页参数返回相应范围的数据,...

    ext-4.1.1a

    8. **触摸支持**:随着移动设备的普及,4.1版本开始增加了对触摸事件的支持,4.1.1a可能进一步优化了在触屏设备上的表现。 9. **国际化**:此版本可能包含了对多语言的支持,方便开发面向全球用户的Web应用。 10. ...

    ext-1.0源码+部分中文解读

    EXT-1.0的事件系统是其响应用户交互和组件间通信的基础。组件可以监听并响应各种事件,如点击、改变等,通过事件处理器进行相应的处理。 6. **Ajax和JSON** EXT-1.0支持Ajax异步通信,使得页面可以在不刷新的情况下...

    ext-4.2.1-gpl.zip

    在使用ext-4.2.1时,开发者需要了解其核心概念,如组件模型、数据绑定、布局管理以及事件处理。他们还需要熟悉MVC(Model-View-Controller)设计模式,因为这是Ext JS推荐的开发方式。此外,了解如何配置和扩展组件...

    ext-4.2.6.rar

    - **触摸支持**:EXTJS 4.x支持触摸事件,可以在移动设备上提供良好的用户体验。 EXTJS 4.2.6虽然不是最新版本,但因其稳定性和广泛的应用,依然在很多项目中得到应用。开发者在使用时应关注其兼容性问题,尤其是与...

Global site tag (gtag.js) - Google Analytics