YUI3学习(九)---组件框架之 Widget
?
Widget部件类是YUI3所有部件的基础类。它在Base的基础上提供了以下几个核心的基础功能:
1,在Base的init和destroy时刻,添加render生命周期管理。
2,抽象的渲染相关方法,促进一致的MVC模式访问。
3,统一的部件属性设置方法。
4,一致的标记生成支持。
5,一致的css样式名称生成支持。
6,内建的渐进增强支持。
提示:3.1.0版本后的widget组件,其默认的css前缀命名由‘yui-’变为‘yui3-’。以此避免在同一程序中YUI2和YUI3的css类名冲突。
?
1.Widget提供哪些功能
1.1Widget类的结构和职责
?
Widget类作为创建YUI3部件的基础类。通常通过继承它来创建其他的Widget。Widget基类继承自Base。因此它提供了同样的属性管理、事件及插件支持等功能。
此外,Widget还增加了以下核心功能:
基础属性
Widget定义了 一组基础属性,每个Widget实例都可以使用。如boundingBox、contentBox、width、height、visible、focused、disabled等。
渲染阶段
Widget在Base类的init和destroy过程基础上增加了render方法和事件。
抽象渲染方法
Widget定义了一些抽象的渲染相关方法:renderUI,bindUI,syncUI。为Widget子类的渲染提供了统一的入口。
渐进增强
Widget在初始化过程中,提供了一致的渐进增强入口。它还提供了一种方法,以隐藏渐进增强标签,避免无样式内容的闪动。
本地化字符
Widget的strings属性支持字符串本地化。当与internationalization功能使用时,可以将需要本地化的字符串与核心代码分离。
?
1.2Widget的基本属性
Widget为YUI3所有部件类提供了一组共同的属性。下表所示
?
boundingBoxWidget的最外边框node,可以设定部件的尺寸和位置,也可作为装饰皮肤的容器。contentBox内容容器;也是建立look and feel 的node。srcNodeDom中已经存在的node,默认会解析为contentBoxtabIndex见名知意,应用于boundingBoxfocused标记boundingBox是否获取焦点,boundingBox 会被赋予 [focused]的css样式disabled标记boundingBox是否失效,boundingBox会被赋予[disabled]的css样式visible标记boundingBox是否可见,boundingBox会被赋予[hidden]的css样式heightboundingBox高,带单位字符串或数值,数值的单位取决于widget的DEF_UNIT定义widthboundingBox宽,带单位字符串或数值,数值的单位取决于widget的DEF_UNIT定义strings可用作部件外观的字符集合,可支持字符本地化?
1.3渲染相关方法
?
Widget在init和destroy阶段增加render方法提供渲染阶段的支持。render方法作为渲染部件的入口,通过添加/修改DOM节点来构建自己的UI并且设置监听来激活UI。
有了这个渲染阶段,widget就可以将状态和逻辑与UI展现相分离。这种分离使widget的状态可以在它显示或渲染到页面前安全的修改和查询。
此外,分离关注点的方式也将代码分为操作widget状态变化及处理widget相关业务逻辑的方法与修改DOM结构的方法。这样的设计也使自定义功能和关注点测试变得容易。
?
生命周期方法init、destroy、render
与init和destroy一样,render方法在Widget中是不能重载的(final)。具体的渲染逻辑实现委托给了Widget实现的renderer方法。下面分别介绍这三个方法。
init(继承自Base的方法)
init方法从上到下(Base fist,subClass last)遍历widget的类层次,将每个类的ATTRS静态属性配置给实例,然后调用类的initializer方法。
init方法触发init事件,可以在事件监听器中阻止初始化过程。
destroy(继承自Base的方法)
从下到上(subClass first,Base last)遍历widget的类层次,调用每个类的destructor方法。
destroy方法触发destroy事件,可以在事件监听器中阻止销毁过程。
render
与遍历widget类层次结构调用initializer和destructor不同,render只调用Widget实例对象的renderer方法。
render方法接收‘parentNode’参数,该参数是Dom文档中已经存在的节点。当widget渲染后,会被添加进该节点内。
如果widget的contentBox或boundingBox不是已经存在于document中的节点,并且‘parentNode’参数未设置,那么widget将作为document中body节点的第一个子元素插入到文档中。
render方法会触发render事件,可以在事件监听器中阻止渲染过程。在widget实例创建后,调用render()方法开始渲染。
?
Widget的renderer方法
Widget提供了一个renderer方法的实现,在多数情况下不需要重写该实现。源码如下:
?
1,boundingBox
?widget的最外层容器,其功能性大于视觉性。
?默认class名称:yui3-widgetname, 如果部件继承了多个widget基类,那么class 包含所有的widget名称。
?Widget实例的状态也会直接体现在class中,当状态隐藏或无效时,class名称中会添加 yui3-[widgetname]-hidden/disabled;
?Widget的位置及宽高属性会直接应用boundingBox的宽高及位置属性上。
?不要试图在boundingBox上应用视觉样式,它仅仅定义css的布局和定位样式。
2,contentBox
是boundingBox的child节点;widget会在contentBox中添加节点来创建UI和内容。
?也定义了默认的class名称:yui3-[widgetname]-content .
?视觉样式可以应用在contentBox上。如 border、padding、background-color 等。
?在构造中指定srcNode属性定义contentBox。
为什么采用双层容器盒子模型?
1,boundingBox担当所有装饰元素的容器,包含所有装饰contentBox的其他元素。比如:用以实现圆角、阴影、衬垫等装饰元素,作为content box的兄弟元素,当他们和content box有同一个父元素时,对他们的定位、大小的设定会更方便。
2,为widget和插件提供了一致的访问结构,便于编写可复用的装饰器或插件。
3,利用一个没有border和padding的box,便于提供一致的widget宽高量算模型。(跨浏览器,在不同盒子模型下有一致的宽高)
?
1.6类名和css
为了给所有的widget提供一致的class样式名称,Widget类提供基于ClassNameManager类的两个方法,依靠widget的NAME属性来定义class名称。
Y.ClassNameManager.getClassName(args*)、 Widget.getClassName(args*)及this.getClassName(args*)
生成上节中提到的class 样式名:yui3-widgetname-arg1-arg2…(widgetname为widget的NAME属性的小写形式)
Widget的状态基本都有对应的css渲染其状态样式,可以通过这个方法返回某个状态下的class名称。Widget避免使用属性控制像visible、disabled和focused的样式,而是通过如下的的class名标记boundingBox来实现:
visibleyui3-[widgetname]-hidden
disabledyui3-[widgetname]-disabled
focusedyui3-[widgetname]-focused
?
?
首先定义构成widget的属性(ATTRS静态属性),这些属性构成了公布给程序的状态和API方法。
然后根据上面介绍的职责分类分别实现initializer、destructor、renderUI、bindUI和syncUI方法以及其他的API相关方法。
Extending The Widget Class这个例子教你如何一步一步实现一个数值选择器widget。 ? ?
此外,YUI提供了自定义Widget开发模版文件,可以作为开发自定义Widget的基础。
?
2.1插件和扩展
除了创建Widget子类来实现自定义Widget,YUI3还提供了两种重用代码的机制:基于Base的Plugins和Extensions。
将Widget的功能打包成扩展或插件,就可以在多个类中扩展(extension)或在多个实例中插入(plugin)。
?
插件还是扩展?
在Widget开发中总会遇到相关功能和特性是以插件形式存在还是以扩展形式存在?开发者需要根据Widget的用意来考虑如何设计。
插件和扩展提供了一个创建小模块功能的机制,这些小功能可以添加到widget的核心实现中。它们的差异如下:
Extensions---基于类级别
1,扩展提供的功能在类级别中使用。
2,扩展是基于扩展功能创建新的widget类。
3,如果新的功能是类所必须的,就应该存在于扩展中。
4,WidgetParent,WidgetChild,WidgetPosition和WidgetStack是YUI3提供了扩展开发的良好示例。
? 例如,一个Tree部件需要实现父/子结构支持,而Menu部件也同样需要,我们想重用父/子结构支持而不能通过强制它们都实现共同的基类,另外,父子结构功能支持对它们来说是必须的。
5,扩展通过使用Base.build方法(或Base.create,Base.mix)合并类。
?
Plugins---基于对象实例级别
1,插件在实例层次为对象提供额外的特性。
2,开发者使用插件为对象应用额外特性。
3,如果新的功能不是必须的,那应该使用插件。
4,YUI3提供的Animation和IO插件是插件开发和使用的良好示例。
? ? 不需要把Animation和IO的功能写到具体的类中。
5,使用实例对象的plug方法来应用插件。
?
2.2Widget扩展
当你准备基于YUI3开发Widget时,可以使用Base.build来扩展框架提供的以下几个打包好的扩展模块。
?
widget-position添加XY 定位功能widget-position-align添加具有对齐和xy定位功能widget-position-constrain添加具有位置限制的功能widget-stack添加堆叠(zIndex)功能widget-stdmod添加标准模型(head body footer)支持widget-parent添加构件包含子构件并提供管理和选取的功能widget-child添加允许作为构件子构件的功能支持?
其中widget-parent和widget-child扩展,允许开发者创建嵌套的Widget类,值得详细介绍一下:
widget-parent
支持widget部件作为容器包含、管理和选取子widget。
1,提供了一个统一的方法来创建父子关系
?
var tabview = new Y.TabView({ children: [{ label: 'foo', content: '<p>foo content</p>' }, { label: 'bar', content: '<p>bar content</p>' }]});?
?
widget-child
支持将widget添加进widget-parent中。与widget-parent共同使用,允许你建立类父子结构。
与widget-parent一样,widget-chlid也提供了一致的接口方法,支持子类与子类、子类与父类的交互。
如:child.next();child.previous();child.ancestor();
YUI3官方示例提供了如下扩展例子可作为开发参考
使用 Extensions: Building Custom Widget Classes ?
扩展Widget-Position, Widget-Stack: A Simple Tooltip Widget ?
扩展Widget-Parent, Widget-Child: A Heirarchical ListBox Widget ?
?
此外,还可以参考YUI3 框架中基于扩展实现的Widget
Overlay
Uses widget-position, widget-position-align, widget-position-constrain, widget-stack, widget-stdmod
TabView
Uses widget-parent, widget-child
YUI官方给出了实现扩展的模板文件:http://developer.yahoo.com/yui/3/base/assets/myextension.js.txt
?
?
2.3Widget插件
YUI3在3.1.0版后提供了几个widget插件。并且提供了几个代码示例描述如何创建自定义插件。
Widget Animation Plugin (api documentation)?
Widget (and Node) Drag/Drop Plugin (api documentation) ??
Creating Widget Plugins (example) ??
Creating An Overlay IO Plugin (example) ? ?
Creating An Overlay Animation Plugin (example)?
?
此外,YUI Gallery中也有不少的widget插件,如 Modal Overlay Plugin 和Widget IO Plugin
?
YUI官方给出了定义插件的模板文件:http://developer.yahoo.com/yui/3/plugin/assets/myplugin.js.txt
?
1 楼 shabumaiev 2012-03-01 LZ 你真牛X!给自己加油!!