原版的:Understanding Widgets in Ext JS 5

在Ext JS 5,引入了新的“widgetcolumn”,支持在网格的单元格中放置组件。

同一时候,还在Ext JS 5引入了一种新的被称为“小部件”的轻量级组件。

在Ext JS 5中,已包括了几个小部件,在本文将告诉你怎样轻松的去打造自己的小部件。

为了说明当中的关键概念。在文中将创建一个简单的名为“ratings”的例如以下图所看到的的小部件:

入门

与经常使用的从Ext.Component派生的组件不同。小部件派生于新的基类Ext.Widget。并且,Ext.Widget的派生类差点儿全然是由配置系统来定义的(后面会谈到)。

Ext.Widget还要定义了DOM元素是怎样产生且怎样与DOM事件连接的。

渲染

对于小部件,首先要考虑的是怎样去定义它的DOM树,典型的方式是例如以下面代码哪样在类指定element属性来实现:

Ext.define('Ext.ux.rating.Picker', {
extend: 'Ext.Widget', //... element: {
cls: 'ux-rating-picker',
reference: 'element', children: [{
reference: 'innerEl',
cls: 'ux-rating-picker-inner', listeners: {
click: 'onClick',
mousemove: 'onMouseMove',
mouseenter: 'onMouseEnter',
mouseleave: 'onMouseLeave'
}, children: [{
reference: 'valueEl',
cls: 'ux-rating-picker-value'
},{
reference: 'trackerEl',
cls: 'ux-rating-picker-tracker'
}]
}]
}, //...
});

对象element是基于Ext.dom.Helper规范来创建DOM元素的,基本的新增功能是reference和listeners属性。

这些名字在视图控制器上已经司空见惯了。而他们在小部件上所要做的事情也相似。在Ext.Widget,全部元素的reference属性都会以名称作为属性值被缓存在小部件实例中(比如:element、innerEl等等)。

事件

在上述的element中。在innerEl对象中还定义了listeners对象。

这些监听会附加到从规范块产生的元素上。方法会依据名称在小部件类中寻找。比如:

Ext.define('Ext.ux.rating.Picker', {
extend: 'Ext.Widget', //... onClick: function (event) {
var value = this.valueFromEvent(event);
this.setValue(value);
}, onMouseEnter: function () {
this.element.addCls(this.overCls);
}, onMouseLeave: function () {
this.element.removeCls(this.overCls);
}, onMouseMove: function (event) {
var value = this.valueFromEvent(event);
this.setTrackingValue(value);
},

尽管这看起来有点相似编写传统的组件类。但比較明显的是缺少初始化代码和清理代码。Ext.Widget的构造函数会处理元素的创建、跟踪他们的引用并设置监听。

除了这些动作(和对应的销毁方法)外,Ext.Widget再没有额外的生命周期或相关开销。

作为替代方法,派生类可通过配置系统提供的config属性来定义它的行为。对于那些不了解配置系统的,下面将简介一下。

配置系统101

Ext JS的核心理念之中的一个就是“配置(config)”属性的概念。

他们从一開始就是Ext JS的一部分,而不单是在Ext JS 5(或Sencha Touch 2.x)才有。框架已经将这些属性的机制规范化。常见的配置是这样声明的:

Ext.define('Ext.ux.rating.Picker', {
//...
config: {
family: 'monospace'
}
//...
});

上述声明等同于下面的手写代码:

Ext.define('Ext.ux.rating.Picker', {
//... getFamily: function () {
return this._family;
}, setFamily: function (newValue) {
var oldValue = this._family; if (this.applyTitle) {
newValue = this.applyFamily(newValue, oldValue); // #1
if (newValue === undefined) {
return this;
}
} if (newValue !== oldValue) {
this._family = newValue; if (this.updateFamily) {
this.updateFamily(newValue, oldValue); // #2
}
} return this;
}, //...
});

这样的自己主动化处理主要有下面显著的长处:

  • 清晰:更少的代码。类更易读
  • 一致性:全部配置都有同样的行为
  • 灵活性:当实现正确时,配置属性能够在不论什么时候改变,而不是仅仅能在创建时改变(在Ext JS中很多旧的配置属性的常见的局限)

开发者能够为不论什么属性提供两个关键的。也是可选的方法。如family,则为applyFamily和updateFamily(上面代码中的#1和#2处)。

这些方法差点儿总是会比重写而不是get或set方法。

应用方法(applier)

应用方法执行开发者去将接收值转换为存储的实际值。对于很多应用方法来说,这可能意味着基于接收到的配置对象来创建一些类的实例,又或者可能是应用方法在有一个地方标准化内部表示形式以避免在全部使用该属性的地方对它进行检查。

更新方法(updater)

当配置属性的值发生了改变,就会调用更新方法。更新方法的作用就是将旧值转换为新值。

initConfig——把它捎上

最后要说的是,要将一个类增加熬配置系统中。就必须在某个点调用initConfig方法。在Ext.Widget,它会在构造函数中执行。方法initConfig会接收config对象并会处理它的每个属性以便这些在类中的声明能适当的去调用set、apply和update方法。

该方法还提供了一个“适时(just in time)”的设置机制来解决配置属性之间的顺序问题,比如,假设一个配置属性的更新方法须要还有一个配置属性的值。它就要调用还有一个配置属性的get方法。在底层。initConfig会依据所请求属性之前返回的结果正确依照顺序调用set/apply/update方法。

使用cachedConfig进行优化

对于小部件,在有些时候须要很多配置来维护DOM。

因为不论什么给定的小部件实例不太可能重写全部的默认配置值。假设能够将这些要处理的默认值缓存起来。是最理想只是了。对于这些配置,能够对类进行下面改动:

Ext.define('Ext.panel.Panel', {
//...
cachedConfig: {
family: 'monospace'
}
//...
});

在大多数情况。这些配置与经常使用的配置是一样的。只是,在缓存这些配置的时候。配置系统会在类创建第一个实例的时候执行一些额外处理。

第一次实例化

在第一个实例的配置对象处理之前,配置系统仅仅会从类的默认值进行初始化。该处理会调用各种apply和update方法。这反过来会依据元素规范更新DOM元素最初的生成。

考虑下family配置,它带有下面更新方法:

updateFamily: function (family) {
this.element.setStyle('fontFamily', "'" + family + "'");
},

全部的更新方法有助于为小部件设置DOM的默认状态。

一旦配置被设置为他们的默认值。就会调用afterCachedConfig方法。该方法,仅仅会在第一次实例化的时候才起作用。Ext.Widget会深度克隆所得到的DOM树(使用cloneNode(true)DOM API)。

第二个实例(及以后)

在创建同样的小部件类的还有一个实例的时候。Ext.Widget会使用缓存的DOM树克隆并深度克隆它来创建性能的小部件DOM树。这可避免又一次处理元素规范和执行默认值的更新方法的开销。假设配置的更新方法书写正确,该处理过程非常大程度上是透明的。

当然。Ext.Widget在复制DOM树后,还有一些工作须要去做,比如检索元素的引用、封装监听并将不论什么非默认值的配置属性设置到实例。

只是,这时的开销就直接与赋予实例的配置值的数量有关而不是类的配置属性了。

重用,循环

下面来研究下怎样创建并初始化一个单一的小部件,有几个重要的概念是与在widgetcolumn中使用小部件有关的。

因为限制创建的实例一直是重点,因而缓冲渲染是关键。使用该方法。网格将渲染比记录少得多的小部件。并须要在行移出滚动区域“之后”且新行渲染“之前”循环使用。

当这些转变发生时,widgetcolumn将会将DOM中的小部件移动到新行,通过dataIndex从对应的记录读取字段数据并调用小部件的setConfig来设置它的defaultBind属性,这将会调用apply和update方法,因而,仅仅要编码正确。小部件如今就能够被又一次配置来显示新的字段值。

在当前演示样例的小部件,因为它仅仅表示一个可编辑的值,因而须要在updateValue方法做检查以了解小部件是否已经使用在网格单元格:

column = me.getWidgetColumn && me.getWidgetColumn();
record = column && me.getWidgetRecord && me.getWidgetRecord();
if (record && column.dataIndex) {
record.set(column.dataIndex, value);
}

方法getWidgetColumn和getWidgetRecord通过widgetcolumn被放置到小部件上,因此它知道它在网格中的上下文(context)。

小结

尽管大部分小部件的讨论与网格有关。但小部件也可用于传统部件的不论什么地方。

评分小部件作为迷你小部件引入Ext JS 5已经成为事实。

下面是演示样例应用程序的主面板截图。显示了它的items数组中的4个实例。

假设对上面的看起来非常熟悉,预计是你已经了解了Sencha Touch的模式。尽管这些是Ext JS 5的扩展,Ext.Widget本质上是最初在Sencha Touch中的Ext.AbstractComponent的最后版本号。

因此。你会使用小部件来取代组件?在很多方面,编写小部件是比编写组件简单。假设纯粹仅仅使用CSS来处理布局需求,尤其如此。

另外,随着我们继续将Sencha移动和桌面框架结合在一起。小部件在未来将会有跨界的可能。

能够在这里找到新的小部件的完整代码和演示样例。享受它并让我们知道你的想法。

作者:Don Griffin
Don Griffin is a member of the Ext JS core team. He was an Ext JS user for 2 years before joining Sencha and has over 20 years of software engineering experience on a broad range of platforms. His experience includes designing web application front-ends and back-ends, native GUI applications, network protocols and device drivers. Don’s passion is to build world class products that people love to use.

【翻译】要理解Ext JS 5小工具的更多相关文章

  1. 【翻译】了解Ext JS 5的小部件

    原文:Understanding Widgets in Ext JS 5 在Ext JS 5,引入了新的"widgetcolumn",支持在网格的单元格中放置组件.同时,还在Ext ...

  2. 【翻译】为Ext JS和Sencha Touch开发人员准备的应用程序监测(App Inspector)

    和其他的Sencha开发人员一样,我会花费大约半天的时间在我喜欢的IDE工具上编写JavaScript,而另一半时间则是在浏览器上测试和调试我的应用程序.在过去几年,每一个主要的浏览器都已大为改善.现 ...

  3. 撸一个JS正则小工具

    写完正则在浏览器上检测自己写得对不对实在是不方便,于是就撸了一个JS正则小demo出来. demo demo展示 项目地址 代码部分 首先把布局样式先写好. <!DOCTYPE html> ...

  4. 【翻译】Sencha Ext JS 5公布

    原文:Announcing Sencha Ext JS 5 简单介绍 我代表Sencha和整个Ext JS团队,非常自豪的宣布,在今天,Sencha Ext JS 5公布了.Ext JS 5已经迈出了 ...

  5. 【翻译】使用Ext JS设计响应式应用程序

    原文:Designing Responsive Applications with Ext JS 在当今这个时代,用户都希望Web应用程序无论在形状还是大小上,既能在桌面电脑,也能在移动设备上使用.使 ...

  6. 【翻译】Sencha Ext JS 5发布

    原文:Announcing Sencha Ext JS 5 简介 我代表Sencha和整个Ext JS团队,很自豪的宣布,在今天,Sencha Ext JS 5发布了.Ext JS 5已经迈出了一大步 ...

  7. 【翻译】对于Ext JS 5,你准备好了吗?

    原文:Are You Ready for Ext JS 5? Ext JS 5:准备升级 对于Ext JS 5加入Sencha的大家庭,我们感到非常高兴!作为一个主要版本,在Ext JS 5引入了一堆 ...

  8. 【翻译】在Ext JS集成第三方库

    原文地址:http://www.sencha.com/blog/integrating-ext-js-with-3rd-party-libraries/ 作者:Kevin Kazmierczak Ke ...

  9. 【翻译】在Ext JS应用程序中使用自定义图标

    原文:Using Custom Icons in Your Ext JS App 作者:Lee BoonstraLee is a technical trainer at Sencha. She's ...

随机推荐

  1. 国内国外MD5在线解密站点

    -http://www.cmd5.com/english.aspx (457,354,352,282) - http://www.md5crack.com - http://www.hashcheck ...

  2. poj1679(最小生成树)

    传送门:The Unique MST 题意:判断最小生成树是否唯一. 分析:先求出原图的最小生成树,然后枚举删掉最小生成树的边,重做kruskal,看新的值和原值是否一样,一样的话最小生成树不唯一. ...

  3. [置顶] JQuery实战总结三 标签页效果图实现

    在浏览网站时我们会看到当我们鼠标移到多个选项卡上时,不同的选项卡会出现自己对应的界面的要求,在同一个界面上表达了尽量多的信息.大大额提高了空间的利用率.界面的切换效果也是不错的哦,这次自己可以实现啦. ...

  4. 基于.net开发chrome核心浏览器【一】

    原文:基于.net开发chrome核心浏览器[一] 说明: 这是本系列的第一篇文章,我会尽快发后续的文章. 源起 1.加快葬送IE6浏览器的进程 世界上使用IE6浏览器最多的地方在中国 中国使用IE6 ...

  5. WPF换肤之五:创建漂亮的窗体

    原文:WPF换肤之五:创建漂亮的窗体 换肤效果 经过了前面四章的讲解,我们终于知道了如何拖拉窗体使之改变大小,也知道了如何处理鼠标事件,同时,也知道了如何利用更好的编写方式来编写一个方便实用和维护的换 ...

  6. Matlab hermite

    保形分段三次hermite插值 % 这是MATLAB里面的pchip.m文件.这里把它的凝视改写成汉语,主要是想弄清楚它是怎么计算在节点处的导数的. function v = pchip(x,y,xx ...

  7. uvalive4327(单调队列优化)

    这题我有闪过是用单调队列优化的想法,也想过有左右两边各烧一遍. 但是不敢确定,搜了题解,发现真的是用单调队列,然后写了好久,调了好久下标应该怎么变化才过的. dp[i][j] 表示走到第i行,第j个竖 ...

  8. Oracle错误——ORA-03113:在通信信道文件的末尾 解决方案

    起源 今天跟往常一样,登陆PL/SQL,确登陆失败,出现一个错误"ORA-01034"和"ORA-27101"如图: 然后就就通过命令提示符去登陆Oracle, ...

  9. erlang如何有效地监视大量的并发连接

    阅读erlang一些开源web框架RabbitMQ.Ranch,他们使用多个进程在同一时间accept一socket.以这样的方式,使socketport监控共享很多其他的机会调度工作,但,在erla ...

  10. xml和json选择奖

    xml&json战争,一般能够分离两个对立阵营.党的手感json足够强大以便能够替代xml.有一方感觉json滑稽丑陋,绝对没有和xml赛可能. 为了避免"拉仇恨"(我不是 ...