深入浅出ExtJs(第2版)读书笔记(2)

第2章 EXT框架基础

2.1  Ext的事件和类

Text事件分为两种类型:自定义事件和浏览器事件

2.1.1    自定义事件

所有继承自Ext.util.Observable类的控件都可以支持事件。

下面通过继承Ext.util.Observable来实现一个支持事件的对象,实现过程如代码清单2-1所示。

程序的效果就是在浏览器上显示三个按钮,当你点击不同的按钮时,会触发不同的自定义事件。

代码清单2-1:完整的源代码Person.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML4.01 Transitional//EN">

<html>

 <head>

   <title>person.html</title>

      

    <metahttp-equiv="keywords"content="keyword1,keyword2,keyword3">

    <metahttp-equiv="description" content="this is my page">

    <metahttp-equiv="content-type" content="text/html;charset=UTF-8">

   

    <linkrel="stylesheet" type="text/css"href="scripts/resources/css/ext-all.css">

   <script type="text/javascript"src="scripts/adapter/ext/ext-base.js"></script>

   <script type="text/javascript"src="scripts/ext-all.js"></script>

       <scripttype="text/javascript">

              //Person类

              Person= function(name){

                     this.name=name;

                     this.addEvents('walk','eat','sleep');

              }

              Ext.extend(Person,Ext.util.Observable,{

                     info:function(event){

                            returnthis.name+' is '+event+'ing';

                     }

              })

             

              //添加事件监听器

              varperson=new Person('Lingo');

              person.on('eat',function(breakfast,lunch,supper){

                     Ext.Msg.alert('event',person.name+'要吃'+breakfast+','+lunch+'和'+supper);

              });

              person.on('walk',function(){

                     Ext.Msg.alert('event',person.name+'饭后百步走,活到99');

              });

              person.on('sleep',function(time){

                     Ext.Msg.alert('event',person.name+'从'+time.format('H')+'点开始睡觉了');

              });

             

             

       </script>

 </head>

 

 <body>

      

   <input type="button" id="btnWalk" value="散步" />

       <inputtype="button" id="btnEat" value="吃饭" />

       <inputtype="button" id="btnSleep" value="睡觉" />

       <script>

              //触发person的事件

              Ext.get('btnWalk ').on('click',function(){

                     person.fireEvent('walk');

              });

              Ext.get('btnEat ').on('click',function(){

                     person.fireEvent('eat','早餐','中餐','晚餐');

              });

              Ext.get('btnSleep ').on('click',function(){

                     person.fireEvent('sleep',newDate());

              });

       </script>

 </body>

</html>

以上代码首先实现了一个名为Person的对象,它有一个属性name。初始化时调用this.addEvents()函数定义了三个事件:walk、eat和sleep,然后让Person继承了Ext.util.Observable。(默然说话:那个info的定义并没在有程序里用到,我认为可以省略,不过我在我的代码引用info了,大家可以注意观察一下我是咋用的)

接下来我们创建了一个Person的实例,并为这个实例添加了对三个事件的监听器。on()就是addListener()的简写形式,第一个参数传递事件名称,第二个参数传递事件处理函数。

再接下来就是HTML的<body>部分,我们做了三个按钮(默然说话:纠结的三个按钮,原书上写得太含混,让我猜了好长时间,我在这里修改了一下三个按钮的名字,便于大家识别。)。

最后,又是一段Script代码,它们获得对应的按钮,并触发对应的事件,在这里,我们直接使用fireEvent()来完成,第一个参数是事件的名称,后面的参数可以是任意个,与你所定义的事件处理函数的参数一一对应。

Ext可以通过on()(即addListener的简写)来注册事件监听函数,也可以使用un()(即removeListener()的简写)来删除某个事件对应的监听函数。示例如下:

var fn=function{

       //此处省略5000行代码

}

person.on(‘fuck’,fn);//注册’fuck’事件

person.un(‘fuck’,fn);//删除’fuck’事件

 

2.1.2    浏览器事件

浏览器事件就是传统意义上的鼠标键盘事件,它们与页面元素紧密相关。Ext使用Ext.EventManager、Ext.EventObject和Ext.lib.Event对原生浏览器事件进行了封装。

2.1.3    Ext.lib.Event

Event中定义了以下几个主要的函数。

q getX()、getY()、getXY()获得发生的事件在页面中的坐标位置,getXY()返回的是一个数组。getXY()[0]就是x坐标,getXY()[1]就是y坐标。

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

q preventDefault()函数用于取消浏览器对当前事件所执行的默认操作。例如,在自定义右键菜单时就需要使用这个函数,防止单击鼠标右键时弹出浏览器自身的右键菜单。

q stopPropagation()函数的作用是停止事件传递,这是与浏览器中HTML元素事件的传递机制相关的。内层的HTML元素触发的事件会传递给外层的HTML元素,调用stopPropagation()函数会中断这个传递过程。

q stopEvent()可以停止一个事件,它调用了preventDefault()和stopPropagation()两个函数。

q onAvailable()函数有3个参数:id,fn和scope。它的作用是当id对应的HTML元素可用时执行fn。

q resolveTextNode()函数会返回事件相关的HTML元素。它先尝试获得e.relatedTarget。如果不存在,就通过e.type来判断事件类型。如果是’mouseout’,就返回e.toElement;如果是’mouseover’就返回e.fromElement。

2.1.4    Ext.util.Observable

Ext.util.Observable在Ext事件模型体系中有举足轻重的地位,位于Ext组件的顶端,为Ext组件提供处理事件的最基本功能。下面主要讨论一下与事件有关的高级功能。

首先,当注册事件时,可以使用复合式参数,如下面的代码所示。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML4.01 Transitional//EN">

<html>

 <head>

   <title>Ext.util.Observable复合式参数的使用</title>

      

    <metahttp-equiv="keywords"content="keyword1,keyword2,keyword3">

    <metahttp-equiv="description" content="this is my page">

    <metahttp-equiv="content-type" content="text/html;charset=UTF-8">

   

    <linkrel="stylesheet" type="text/css"href="scripts/resources/css/ext-all.css">

   <script type="text/javascript"src="scripts/adapter/ext/ext-base.js"></script>

   <script type="text/javascript"src="scripts/ext-all.js"></script>

       <scripttype="text/javascript">

              //fn函数我定义在这里

              varfn=fungion(e,el,args){

                     alert('函数被调用');

                     alert(args.testId);

              }

       </script>

 </head>

 

 <body>

      

       <!--这里是测试按钮 -->

   <input type="button" id="test" value="测试" />

      

       <scripttype="text/javascript">

              Ext.get('test').on('click',fn,this,{

                     single:true,//这个函数是否仅执行一次,true表示仅执行一次

                     delay:500,//延迟500ms

                     testId:4//自定义参数,此处仅作为一个演示

              });

       </script>

      

 </body>

</html>

这个示例的运行结果是,在第一次单击test按钮时,会弹出一个alert框,里面写着“函数被调用了”,接着又弹出一个alert框,里面写着“4”(默然说话:fn里就是这样写的)。这些和我们平时写事件函数没什么区别,但有两件事情不太一样,第一件是,第一个alert框的弹出会出现延迟0.5秒,第二件是,你再点那个测试按钮,对话框不会再弹出来了。这一切都是由第四个参数造成的。

single:true表示这个事件处理函数只执行一次;delay:500表示函数会在事件发生之后500毫秒被执行。而testId:4则是第二个alert框中显示的4的由来。

在实际程序中,我们可能需要给事件处理函数传入一些参数,那么形如testId:4这样的参数就很有用处了。它会被fn函数的第三个参数传递到函数中,然后直接通过形如args.testId的方式来获得传入的值。(默然说话:前两个参数是什么?第一个参数是Ext.EventObject对象,第二个参数好象是事件源,由于没有找到确实的文字描述,暂时不作定论)

另外,我们也可以使用on()定义多个事件监听器,如下面代码所示:

Ext.get('test2').on({

       'click':{

              fn:fn

       },

       'mouseover':{

              fn:fn,

              single:true,

              delay:1000,

              testId:5

       }

});

Ext.util.Observable还有一个重要的功能,就是可以为某个事件设置拦截器,统一管理方法的触发。我们使用capture()和releaseCapture()来实现这个功能。

我们在Person的示例中使用capture()函数拦截事件的触发,完整代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML4.01 Transitional//EN">

<html>

 <head>

   <title>person.html</title>

      

    <metahttp-equiv="keywords" content="keyword1,keyword2,keyword3">

    <metahttp-equiv="description" content="this is my page">

    <metahttp-equiv="content-type" content="text/html;charset=UTF-8">

   

    <linkrel="stylesheet" type="text/css"href="../scripts/resources/css/ext-all.css">

   <script type="text/javascript"src="../scripts/adapter/ext/ext-base.js"></script>

   <script type="text/javascript"src="../scripts/ext-all.js"></script>

       <scripttype="text/javascript">

              //Person类

              Person= function(name){

                     this.name=name;

                     this.addEvents('walk','eat','sleep');

              }

              Ext.extend(Person,Ext.util.Observable,{

                     info:function(event){

                            returnthis.name+' is '+event+'ing';

                     }

              })

             

              //添加事件监听器

              varperson=new Person('Lingo');

              person.on('eat',function(breakfast,lunch,supper){

                     Ext.Msg.alert('event',person.name+'要吃'+breakfast+','+lunch+'和'+supper);

              });

              person.on('walk',function(){

                     Ext.Msg.alert('event',person.name+'饭后百步走,活到99');

              });

              person.on('sleep',function(time){

                     Ext.Msg.alert('event',person.name+'从'+time.format('H')+'开始睡觉了');

              });

 

             

       </script>

 </head>

 

 <body>

   <input id="walk" type="button" value="散步" />

   <input id="sleep" type="button" value="睡觉" />

   <input id="eat" type="button" value="吃饭" />

   <input id="capture" type="button" value="启动拦截" />

   

   <script type="text/javascript">

                //触发person的事件

                     Ext.get('walk').on('click',function(){

                            person.fireEvent('walk');

                     });

                    

                     Ext.get('sleep').on('click',function(){

                            person.fireEvent('walk');

                     });

                    

                     Ext.get('eat').on('click',function(){

                            person.fireEvent('eat');

                     });

 

                     //拦截器的添加

                     Ext.get('capture').on('click',function(){

                            Ext.util.Observable.capture(person,function(){

                                   alert('捕获1');

                                   returntrue;

                            });

                     });

   </script>

 </body>

</html>

上面的代码就是在Person代码的基础上添加了一个按钮“启动拦截”,和一段拦截的事件处理函数。其作用就是当你点击“启动拦截”按钮之后,你会看到所有Person事件代码运行之前,会先弹出一个“捕获1”的警告框,之后才是原来的事件处理函数代码的执行。这个拦截代码如下:

Ext.get('capture').on('click',function(){

       Ext.util.Observable.capture(person,function(){

              alert('捕获1');

              returntrue;

       });

});

大家看到函数最后返回了一个true。如果这个拦截函数最后返回false,那将会终止所有的事件代码的执行。

releaseCapture()函数是capture()函数的反向操作,它会一次性清除所有的拦截函数。

suspendEvents()可以暂停某个对象中所有事件的发生,而resumeEvents()可以恢复某个对象中被暂停的事件。它们可以帮助我们统一管理某一对象的事件。

2.1.5    Ext.EventManager

作为事件管理器,Ext.EventManager定义了一系列事件的处理函数,其中最常用的当属onDocumentReady、onWindowResize和onTextResize。其中onDocumentReady就是我们经常见到的Ext.onReady(),它会在页面文档渲染完毕但图片等还未下载时调用启动函数。

Ext.onReady()可以有效避免由于网页元素尚未完全加载完毕而出现“’null’为空或不是对象”的错误(我们前面几个例子,都是把事件监听代码放在了对应元素后面,就是这个原因),使用Ext.onReady()就可以把启动时要运行的代码放在网页的开头了。

onWindowResize()的作用是监听浏览器窗口的大小改变,它会提醒我们浏览器窗口的大小在何时发生了改变,改变后的大小是多少。

onTextResize()会在<body>标签中添加一个包含测试文字的div标签,然后监听测试文字的大小。如果测试文字的大小发生改变,就执行监听函数,并发送给监听函数两个参数,第一个是改变前的文字大小,第二个是改变的的文字大小。

需要注意的是,因为onTextResize()需要操作标签,所以这个事件只能写在Ext.onReady()中,否则有可能会出现错误。下面是完整的演示代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML4.01 Transitional//EN">

<html>

 <head>

   <title>event_manager.html</title>

      

    <metahttp-equiv="keywords"content="keyword1,keyword2,keyword3">

    <metahttp-equiv="description" content="this is my page">

    <metahttp-equiv="content-type" content="text/html;charset=UTF-8">

    <linkrel="stylesheet" type="text/css"href="../scripts/resources/css/ext-all.css">

   <script type="text/javascript" src="../scripts/adapter/ext/ext-base.js"></script>

   <script type="text/javascript"src="../scripts/ext-all.js"></script>

   <!--<link rel="stylesheet" type="text/css"href="./styles.css">-->

      

       <scripttype="text/javascript">

             

              Ext.onReady(function(){

                     Ext.Msg.alert('消息',Ext.get('test'));

 

                     Ext.EventManager.onTextResize(function(oldSize,newSize){

                            alert('oldSize:'+oldSize+',newSize:'+newSize);

                     });

              });

 

              Ext.EventManager.onWindowResize(function(width,height){

                     alert('width:'+width+',height:'+height);

              });

             

       </script>

 </head>

 

 <body>

   <button id="test" >test</button>

 </body>

</html>

2.1.6    Ext.EventObject

Ext.EventObject是对事件的封装,它将EXT自定义事件和浏览器事件结合在一起使用。此外,它还提供了丰富的辅助工具函数,帮助我们获得事件相关的信息。

Ext.EventObject定义了一系列的功能按键,处理按键事件时不用再去硬背ASCII码(默然说话:但是要硬背英语单词,呵呵~我早就背得ASCII了,现在又要让我去记单词,烦!)

名称

ASCII码

名称

ASCII码

BACKSPACE

8

PAGEDOWN

34

TAB

9

END

35

RETURN

13

HOME

36

ENTER

13

LEFT

37

SHIFT

16

UP

38

CONTROL

17

RIGHT

39

ESC

27

DOWN

40

SPACE

32

DELETE

46

PAGEUP

33

F5

116

下面的代码监听一个文本框,如果按了空格,就会弹alert:(默然说话:从这里开始,我不再贴完整代码了,请参考前面完整代码的模式,来补全后面的代码,让程序正常运行,这对大家也是一个锻炼,有助于大家更深刻的理解代码的含义,对吧?)

Ext.get('event_object_test').on('keypress',function(e){

          if(e.keyCode==Ext.EventObject.SPACE){//书上使用e.charCode,经实测在IE下不可行

               Ext.Msg.alert('info','你按了空格');

          }

        });

如果我们想得到原始的浏览器事件,可以通过Ext.EventObject的browserEvent来获得。

另外,Ext.EventObject也有getPageX(),getPageY()、getPageXY()、getTarget()和getRelatedTarget()方法,这些方法实际上都是通过调用Ext.lib.Event实现的。

Ext.EventObject还有altKey、ctrlKey和shiftKey用来判断是否有功能键被按下,也可以使用hasModifier()判断是否有功能键被按下。这个功能一般要与其他的按键状态相配合,用于判断组合按键的情况。

Ext.EventObject提供的另一个有趣的功能函数名称为getWheelDelta(),可以获得鼠标滚轮的delta值。在下面的示例中,我们监听了mousewheel事件,在滚轮转动时动态修改了上面例子中文本框的宽度,这样又给我们提供了一种提升用户体验的方法,如下面的代码所示(默然说话:很爽哦,不信你试试?)。

       Ext.get(document.body).on('mousewheel',function(e){

           var delta=e.getWheelDelta();

           var test=Ext.get('event_object_test');

           width=test.getWidth();

           test.setWidth(width+delta*500,true);

        });

2.2  Ext的核心组件

2.2.1    Ext.Component

Ext.Component是Ext中所有组件的基类,它的所有子类都自动享有标准Ext组件的生命周期,包括创建、渲染和销毁。它们也自动支持了标准的隐藏/显示以及启用/禁用等操作。

在Ext组件树中,每个组件都对应一个xtype属性,在Ext中可以通过xtype属性直接指定在某处使用的组件。(默然说话:Ext组件树可以参看书上23页的图2-3)

所有的组件都允许在Ext.Container及其子类中进行延迟渲染(lazy render),也可以把组件注册到Ext.ComponentMgr中,这样就可以在任何地方使用Ext.getCmp()函数直接根据id获得对应的组件。

所有可视化的组件都是Ext.Component的子类,这样我们就能把它们放到layout中进行布局管理。

表2-2  基本组件

xtype

组件名称

描述

box

Ext.BoxComponent

具有边框属性的组件

button

Ext.Button

按钮

colorpalette

Ext.ColorPalette

调色板

component

Ext.Component

组件

container

Ext.Container

容器

cycle

Ext.CycleButton

循环按钮

dataview

Ext.DataView

数据显示视图

datepicker

Ext.DatePicker

日期选择面板

editor

Ext.Editor

编辑器

editorgrid

Ext.grid.EditorGridPanel

可编辑的表格

grid

Ext.grid.GridPanel

表格

paging

Ext.PagingToolbar

分页工具条

panel

Ext.Panel

面板(可进行子布局)

progress

Ext.ProgressBar

进度条

splitbutton

Ext.SplitButton

可下拉的按钮

tabpanel

Ext.TabPanel

选项面板

treepanel

Ext.tree.TreePanel

viewport

Ext.ViewPort

视图

window

Ext.Window

窗口

表2-3  工具条组件

xtype

组件名称

描述

toolbar

Ext.Toolbar

工具条

tbfill

Ext.Toolbar.Fill

右对齐填充’->’

tbitem

Ext.Toolbar.Item

工具条项目

tbseparator

Ext.Toolbar.Separator

工具条分隔符’-’

tbspacer

Ext.Toolbar.Spacer

工具条空白

tbtext

Ext.Toolbar.TextItem

工具条文本项

表2-4  表单组件

xtype

组件名称

描述

form

Ext.FormPanel

表单面板

checkbox

Ext.form.Checkbox

多选框

combo

Ext.form.ComboBox

下拉列表

datefield

Ext.form.DateField

日期选择项

field

Ext.form.Field

输入框

fieldset

Ext.form.FieldSet

hidden

Ext.form.Hidden

表单隐藏域

htmleditor

Ext.form.HtmlEditor

HTML编辑器

numberfield

Ext.form.NumberField

数字编辑器

radio

Ext.form.Radio

单选框

textarea

Ext.form.TextArea

区域文本框

textfield

Ext.form.TextField

表单文本框

timefield

Ext.form.TimeField

时间录入项

trigger

Ext.form.TriggerField

触发录入项

2.2.2    Ext.BoxComponent

可以使用pageX、pageY、x、y为Ext.BoxComponent指定具体的坐标,也使用width和height为Ext.BoxComponent指定长度和宽度,或者使用autoHeight和autoWidth让Ext.BoxComponent根据自身内容自动调整长度和高度。

下面的代码在网页里画了一个红色的框框:

  <body>

      <div id="test"></div>

   <script type="text/javascript">

    var box=new Ext.BoxComponent({

          el:'test',//一个div的id名字

          style:'background-color:red;position:absolute;',//样式表

          pageX:100,//left的值

          pageY:50,//top的值

          width:200,

          height:150

        });

       box.render();

   </script>

 </body>

2.2.3    Ext.Container

Ext.Container继承自Ext.BoxComponent,它提供了两个重要的参数layout和items。layout参数指定当前组件使用何种布局,items参数中包含的是当前组件中的所有子组件。

所有的容器组件(如各种面板)都是Ext.Container的子类。

2.2.4    Ext.Panel

Ext.Panel是Ext中经常用到的一个组件,它直接继承自Ext.Container。我们可以使用title参数定义它的标题,使用tbar和bbar设置上下位置的工具条,使用collapseFirst、collapsed、collapsedClst和collapsible设置与面板折叠相关的配置。除此之外,还可以使用floating和shadow设置浮动阴影效果,使用HTML直接设置面板内容。

现在我们来设置一个包含浮动阴影的、可拖放、可折叠、设置了大小、位置、标题和内容的Ext.Panel:

<body>

      <div id="test"></div>

   <script type="text/javascript">

        var panel=new Ext.Panel({

           el:'test',

           title:'这是标题',

           floating:true,

           shadow:true,

           draggable:true,

           collapsible:true,

           html:'<h1>这是面板内容</h1>',

           pageX:500,

           pageY:50,

           width:200,

           height:150

        });

       panel.render();

   </script>

 </body>

2.2.5    Ext.TabPanel

 <body>

      <div id="test"></div>

      <div id="test2"></div>

   <script type="text/javascript">

        vartabs=new Ext.TabPanel({

           renderTo:document.body,

           height:100

        });

 

       tabs.add({

           title:'标题1',

           html:'内容1',

           closable:true

        });

        tabs.add({

           id:Ext.id(),

           title:'标题2',

           html:'内容2',

           closable:true

        });

 

       tabs.activate(0);

   </script>

 </body>

2.3  小结


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

默然说话

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值