Ext框架基础_笔记_02
记录一下Ext的基础知识部分:
~~底层框架部分
~类的创建
Ext.define('demo.Demo',{
name:'Lingo',
hello:function(){
return 'Hello ' + this.name;
}
});
使用Ext.define来定义一个类,其中包含有两个字段。第一个字段是String类型,代表类名,这里是'demo.Demo';第二个字段是Object类型,后面{}括起来的部分都是,用来填写类的字段和函数。
(demo.Demo比起传统的方式建立类,摆脱了命名空间的束缚,对字段的切分和命名空间的创建都包在了框架身上)
想要使用申明的类创建对象可以:
var demo = new demo.Demo()
也许是版本的问题,new创建对象,我这里会报错,于是修改为:
(可能是和命名空间冲突了,换成demo1也可以使用new创建...)
var demo = Ext.create('demo.Demo'); console.log(demo.name); alert(demo.hello());
~对象的继承
Ext.define('demo.DemoWindow', {
extend: 'Ext.Window',
title: 'demo Header',
initComponent: function(){
Ext.apply(this, {
items: [{
html: 'panel1'
},{
html: 'panel2'
}]
});
this.callParent();
}
});
在类中添加extend关键字声明继承关系。上面继承了Ext自带的Window并进行了扩展,提供了头部的名称和两个子组件分别是panel1和panel2。
Ext.apply()函数将一批属性批量复制给当前对象;
this.callParent()函数实现对父类函数的快捷调用;
var demoWindow = Ext.create('demo.DemoWindow'); console.log(demoWindow.title); demoWindow.show();
~多重继承
Ext.define('demo.Demo', { name: 'Lingo', hello: function() { return 'Hello ' + this.name; } }); Ext.define('demo.DemoPanel', { extend: 'Ext.Window', mixins: ['demo.Demo'] });
Ext.define()遵行单继承。这里为了实现多继承的功能,使用mixins关键字。
mixins提出使用混入的方式实现了对多继承的支持。
var demoPanel = Ext.create('demo.DemoPanel'); console.log(demoPanel.name); console.log(demoPanel.hello()); demoPanel.show();
~自动代码补充
这里的补充是指Ext自动会根据配置自动生成对应的辅助功能属性,例如:
// 1. Ext.define('demo.DemoInstance', { config: { title: 'demo' } }); // 2. Ext.define('demo.DemoInstance', { title: 'demo', getTitle: function() { return this.title; }, setTitle: function(title) { this.title = this.applyTitle(title) || title; }, applyTitle: function(title) {} });
1. 和2. 是等价的。可以观察到,例子一仅仅定义了一个参数,Ext就自动补充了对应的setter、getter以及applyTitle()方法。
想要继续定制属性和设置规则可以重写applyTitle()函数来实现。
var demoInstance = Ext.create('demo.DemoInstance'); console.log(demoInstance.getTitle()); demoInstance.setTitle('demo2') console.log(demoInstance.getTitle());
~另外还有俩
Ext.define('demo.DemoObject',{
statics: {
//静态成员
},
contructor: function(){
//初始化操作
}
})
statics关键字可以设置静态成员(无需创建就可以直接调用的属性或者函数);
constructor关键字可以自定义构造函数,以进行一些初始化操作;
~~统一组件模型
在日常开发中,接触最多的还是各种组件和布局,so,后面的更加重要。
~Ext.Component
Ext.Component是Ext中所有可视组件的父组件;
组件最常用到的功能包含:
initComponent() | 初始化 |
render() | 渲染 |
show() | 显示 |
hide() | 隐藏 |
作为基类,Ext.Component本身不包含任何格式,我们需要在使用时为他指定渲染的html内容,通过html参数传入;
<script> Ext.onReady(function() { var box = new Ext.Component({ el: 'test', style: 'background-color:red;position:absolute;', pageX: 100, pageY: 50, width: 200, height: 150 }); box.render(); }); </script> <div id="test" style="background-color: antiquewhite;">我是div</div>
这行代码演示了如何使用Ext.Component在页面定义位置和大小:
~Ext.Panel
Ext.Panel直接继承Ext.Container。不同之处在于,Panel无需继承就可以直接使用。
floating | 设置浮动 |
shadow | 设置阴影 |
draggable | 可拖放的 |
collapsible | 可折叠的 |
var panel = new Ext.Panel({ el: 'test', title: '测试标题', floating: true, shadow: true, draggable: true, collapsible: true, html: '测试内容', pageX: 100, pageY: 50, width: 200, height: 150 }); panel.render();
~Ext.Container
Ext.Container也继承自Ext.Component,提供了两个参数:layout和items。
layout | 指定当前组件的布局 |
items | 指定当前组件中的所有子组件 |
xtype | 简化配置和延迟布局中组件的初始化 |
xtype属性用法举例:
new Ext.Viewport({ layout: 'border', defaults: { collapsible: true, //支持该区域展开和折叠 split: true, //支持用户拖放改变区域大小 bodyStyle: 'padding:15px' //内边距 }, items: [ new Ext.Panel({ region: 'north', height: 80, html: '我是北边' }), new Ext.Panel({ region: 'south', minSize: 75, maxSize: 250, height: 80, html: '我是南边' }), new Ext.Panel({ region: 'west', width: 150, html: '我是西边' }), new Ext.Panel({ region: 'east', width: 150, html: '我是东边' }), new Ext.Panel({ region: 'center', html: '我是中间' }) ] });
等价于:
new Ext.Viewport({ layout: 'border', defaults: { collapsible: true, //支持该区域展开和折叠 split: true, //支持用户拖放改变区域大小 bodyStyle: 'padding:15px' //内边距 }, items: [{ xtype: 'panel', region: 'north', height: 80, html: '我是北边' }, { region: 'south', minSize: 75, maxSize: 250, height: 80, html: '我是南边' }, { region: 'west', width: 150, html: '我是西边' }, { region: 'east', width: 150, html: '我是东边' }, { region: 'center', html: '我是中间' }] });
两种代码对比之下可以发现,使用xtype将会促成 延迟加载机制,所有子组件的生命周期都将会交给容器统一管理。对于没有设置xtype的组件,Ext会同意当作Ext.Panel使用,所以在使用Ext.Panel作为子组件时可以直接省略xtype参数。
如果想要制作一个可以对自身包含的子组件进行布局的组件,那么就需要继承Ext.Container,他是一切可布局组件的父类;
~~Ext事件机制
事件模型分为两种:自定义事件和浏览器事件;
~自定义事件
Ext遵循一种树状事件模型,所有继承了Ext.util.Observable类的控件都可以支持事件。可以为继承了Ext.util.Observable的对象定义一些事件,然后为这些事件配置监听器。当某个事件被触发的时候,Ext会自动调用对应的监听器,这就是Ext的事件模型。
1、创建Person类;
(这里太坑了,版本不同,影响很大,这里使用的是4.2版本,所以需要添加一行代码,手动调用父类的构造函数..)
//创建person类 Person = function(name) { this.name = name; this.addEvents('walk', "eat", "sleep"); this.superclass.constructor.apply(this, arguments); //手动初始化父类构造函数 } Ext.extend(Person, Ext.util.Observable, { info: function(event) { return this.name + 'is' + event + 'ing.'; } });
2、为person添加监听器
var person = new Person('Lingo'); console.log(person.name); //Lingo console.log(typeof(person)); //object //添加事件监听器 person.on('walk', function() { Ext.Msg.alert('event', person.name + "在走啊走啊。"); }); person.on('eat', function(breakfast, lunch, supper) { Ext.Msg.alert('event', person.name + "要吃" + breakfast + ", " + lunch + "和" + supper + "。 "); }); person.on('sleep', function(time) { Ext.Msg.alert('event', person.name + "从" + Ext.Date.format(time, "H") + "点开始睡觉啦。"); });
(on()是addListener()的简写形式)
3、触发person事件
//触发person事件 Ext.get('walk').on('click', function() { person.fireEvent('walk'); }); Ext.get('eat').on('click', function() { person.fireEvent('eat', '早餐', '中餐', '晚餐'); }); Ext.get('sleep').on('click', function() { person.fireEvent('sleep', new Date()); });
(使用fireEvent()会触发事件)
<button id="walk">walk</button> <button id="eat">eat</button> <button id="sleep">sleep</button>
~浏览器事件
浏览器事件就是传统意义上的鼠标单击、移动等事件,是由浏览器根据用户动作触发的,与页面元素紧密相关。Ext使用Ext.EventManager、Ext.EventObject和Ext.lib.Event对原生事件进行了封装,最后将一套统一的跨浏览器的事件通用接口展现给我们。
?HTML已经有了一套自己的事件绑定机制了,为什么还要重写一份呢??
!几乎每一个JS框架都会重写一份自己发事件绑定机制,原因很多,但是有一点很重要。那就是原生机制虽然简单但那时每次绑定事件只能绑定一个事件,如果同时绑定多个事件就会出现覆盖现象。但是,如果使用Ext绑定就不会出现覆盖问题,绑定的事件将会依次运行。
Ext.onReady(function() { var test = Ext.get('test'); test.on('click',function(){ alert("handle1"); }); test.on('click',function(){ alert("handle2"); }); });
这段代码首先通过Ext.get('test')获得id,然后使用on绑定两个click事件,时间会依次执行,不会被覆盖。
~Ext.EventObjectImpl
Ext.EventObjectImpl是对事件的封装,他将Ext自定义事件和浏览器事件结合到一起使用。首先,他封装了不同浏览器的事件处理函数,并为上层提供统一的功能接口。
getX()、getY() | 获取对应的x、y坐标 |
getXY() | 返回数组,getXY()[0]是x坐标,getXY()[1]是y坐标 |
getTarget() | 返回事件的目标元素 |
on()、un() | 绑定事件、事件清除 |
preventDefault() | 取消浏览器对当前事件所执行的默认操作 |
stopPropagation() | 停止事件传递 |
stopEvent() | 停止一个事件 |
getRelatedTarget() | 返回事件相关的HTML元素 |
(!书上给的是Ext.EventObjectImpl,不过经过查找4.2的文档没有发现这个,只看到了Ext.EventObject)
Ext.EventObjectImpl(Ext.EventObject)定义了一系列功能键,举个例子:
<script> Ext.onReady(function() { Ext.get('text').on('keypress', function(e) { if (e.charCode == Ext.EventObject.SPACE) { Ext.Msg.alert('info', '空格'); } }); }); </script> 空格检测<input id="text" type="text">
同样,除了键盘,Ext.EventObject对Ext.lib.Event扩展的部分是对鼠标事件和按键事件的增强,它可以判断ALT、CTRL、SHIFT等功能键是否被按下,也可以使用altKey、ctrlKey和shiftKey判断单独被按下,也可以使用hasModifier()判断是否所有功能键被按下。
、 Ext.EventObject提供了另一种有趣的功能函数getWheelDelta()它可以获得鼠标滚动论的delta值。下面的例子,通过监听mousewheel事件,在滚轮转动时动态修改了test这个div的宽度:
<script> Ext.onReady(function() { Ext.get(document.body).on('mousewheel', function(e) { var delta = e.getWheelDelta(); var test = Ext.get('test'); var width = test.getWidth(); test.setWidth(width + delta * 500, true); }); }); </script> <div id="test" style="background-color: antiquewhite;">我是div</div>
~Ext.util.Observable
Ext.util.Observable在Ext事件中地位举足轻重,位于Ext组件的顶端,提供了事件处理的最基本功能。要实现一个可以处理事件的Ext组件,最直接的方法就是直接继承Ext.util.Observable。
前面列举了addListener()/on()、removeListener/un()、addEvents()、fireEvent()这些函数的基本用法。下面是一些高级用法。
addListener()/on()用于事件注册,可以使用复合式参数,如下:
<script> Ext.onReady(function() { Ext.get('test').on('click', function() { Ext.Msg.alert("message", "Hello World"); }, this, { single: true, //只作用一次 delay: 2000, //延迟时间ms testId: 4 }); }); </script> <button id="test">点我</button>
点击id为test的按钮,触发事件
一共有四个参数,点击事件click,点击事件出发函数,作用域this,还有第四个就是复合参数了。
另外还有一个参数buffer,如下:
<script> Ext.onReady(function() { Ext.get('test').on('click', fn, this, { buffer: 1000, testId: 4 }); }); fn = function(e, el, args) { alert("handle1"); alert(args.testId); } </script> <button id="test">点我</button>
buffer和delay的区别就是,buffer会创建一个Ext.util.DelayTask对象,并把fn放入其中等待执行。在等待过程中,如果再次触发了事件,就会更新任务队列,这样就避免了fn的多次执行。
我们在复合函数中定义了一个testId:4,它会被fn函数的第三个参数传递到函数中,并可以被args.testId来获得这个参数的值。
除了复合参数,还可以使用on()一次定义多个事件监听器,如下:
<script> Ext.onReady(function() { Ext.get('test').on({ 'click': { fn: fn }, 'mouseover': { fn: fn, single: true, delay: 100 } }) }); var fn = function(e, el, args) { alert("handle1"); } </script> <button id="test">点我</button>
加上了single:true,可以使得mouseover只执行一次,之后就可以继续click事件。
Ext.util.Observable还有一个重要功能,那就是可以为某个事件添加拦截器,统一管理事件的触发。例如:

<script> Ext.onReady(function() { Ext.get('capture1').on('click', function() { Ext.util.Observable.capture(person, function() { alert('下次小心点'); return true; }); }, this, { single: true //只执行一次 }); Ext.get('capture2').on('click', function() { Ext.util.Observable.capture(person, function() { alert('Game Over'); return false; }); }); //创建person类 Person = function(name) { this.name = name; this.addEvents('walk', "eat", "sleep"); this.superclass.constructor.apply(this, arguments); //手动初始化父类构造函数 } Ext.extend(Person, Ext.util.Observable, { info: function(event) { return this.name + 'is' + event + 'ing.'; } }); var person = new Person('Lingo'); console.log(person.name); //Lingo console.log(typeof(person)); //object //添加事件监听器 person.on('walk', function() { Ext.Msg.alert('event', person.name + "在走啊走啊。"); }); person.on('eat', function(breakfast, lunch, supper) { Ext.Msg.alert('event', person.name + "要吃" + breakfast + ", " + lunch + "和" + supper + "。 "); }); person.on('sleep', function(time) { Ext.Msg.alert('event', person.name + "从" + Ext.Date.format(time, "H") + "点开始睡觉啦。"); }); //触发person事件 Ext.get('walk').on('click', function() { person.fireEvent('walk'); }); Ext.get('eat').on('click', function() { person.fireEvent('eat', '早餐', '中餐', '晚餐'); }); Ext.get('sleep').on('click', function() { person.fireEvent('sleep', new Date()); }); }); </script> <button id="capture1">留你半条命</button> <button id="capture2">一棒子打死</button> <button id="walk">walk</button> <button id="eat">eat</button> <button id="sleep">sleep</button>
点击capture1按钮的时候,拦截person的fireEvent()函数,弹出alert提示框,并返回true。也就是不会终止事件的进行。
点击capture2按钮的时候,拦截person的fireEvent()函数,同样弹出alert提示框,但是返回的是false,这样就会终止事件。
一个对象可以被设置多个capture拦截函数,这些拦截会变成一个处理链条,只要其中任何一个拦截函数返回false,就会终止处理过程。
有拦截就会有反拦截,releaseCapture()函数就是capture()函数的反过程,它会一次性清除fireEvent()上的所有拦截函数,不过我们无法通过它定位某一个想要删除的拦截函数。一旦执行,就是全部失效,
如果只想通过一次设置来暂停某一个对象中所有事件的发生,可以使用suspendEvents()函数(),如下:
Ext.get('suspendEvents').on('click', function() { person.suspendEvents(); }) Ext.get('resumeEvents').on('click', function() { person.resumeEvents(); })
<button id="suspendEvents">定身</button> <button id="resumeEvents">解放</button>
调用suspendEvents()之后,person中所有事件都会失效,只要再次调用resumeEvents()就会取消这个效果。
这两个事件函数可以帮助我们统一管理某一个对象的事件。
~Ext.EventManager
Ext.EventManager作为事件管理器,定义了一系列与事件处理相关的处理函数,常用的有onDocumentReady、onWindowResize和onTextResize,其中onDocumentReady就是常用到的Ext.onReady(),他会在页面文档渲染完毕之后但是还未下载的时候调用启动函数,也就是说,可以保证在onReady中的内容会在所有HTML元素都加载完成之后才执行,避免了找不到标签的情况,这个和有的人习惯把js下载最后的情况一致。
onWindowResize()的作用是监听浏览器窗口大小改变,会提醒我们何时浏览器大小发生了改变,以及改变后的大小,如下:
<script> Ext.EventManager.onWindowResize(function(width, height) { alert('width:' + width + ',height:' + height); }) </script>
这里就不需要加到onReady中,因为监听对象是window,页面一打开就存在了。其中只有两个参数,一个是width,一个是height。分别代表了窗口的宽和高。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类