所有在模块的代码顶部声明的常量在模块外都是不可见的,但你可能想使一些常量可见,比如CLASS_NAMES。此时,你只需在Y.Base.create的最后一个参数中,即声明静态成员的区域声明:CLASS_NAMES: CLASS_NAMES
这样这一对象及其包含的所有属性都可通过Y.MyWidget.CLASS_NAMES来访问。
我建议尽可能将widget的HTML字符串都调整好再执行Y.Node.create。因为在Javascript中,字符串操作的速度比DOM操作快很多。在Y.Node.create调用前做的越多,代码执行的速度就越快。
所有widget还都会用到的方法就是bindUI。你可以在这个函数创建元素绑定事件,例如你可以给上面TEMPLATE中的<input>绑定valueChange事件,使textbox中值和配置属性中的对应的值始终保持一致。代码和用户都有可能去修改input中的值。如果是来自内部代码的更新值,textbox要刷新以显示新值,如果改变来自用户输入则不用刷新。如不这样,就会陷入死循环:textbox的value属性发生改变,触发change事件,响应函数又改变textbox的值,这一改变又触发了change事件……让我们看看如何处理这一情况。我们在input上绑定自定义的valueChange事件,当然要先在模块的requires中加入event-valuechange模块。 this._eventHandles.push(this._inputEl.after(‘valueChange’, this._afterInputChange, this));
我们假设_inputEl对象指向textbox。事件响应函数如下: _afterInputChange: function (ev) { this.set(VALUE, ev.target.get(VALUE),{source:UI}); },
这里假设我们事先已定义了表示value和ui的常量VALUE和UI。我们简单的将配置属性中的值设置为input中的值,我还给函数加了第三个参数{source:UI}。set函数可以接受第三个参数,这个参数是一个object对象,它的属性可以加入attribute change事件的事件对象(event facade)中,由此就可以区别textbox的valueChange事件是来自内部代码还是用户输入。在bindUI中,我们可能已经这样设置了事件监听: this._eventHandles.push(this.after(‘valueChange’,this._afterValueChange));
这是一个监听value变化的事件监听,上一个例子也是对<input>的value的变化作监听。两个事件名称都一样,实际上,它们都是对一个叫做value的值的变化进行监听,但实际却不一样。通常,对属性变化的监听会放在initializer里,而此例涉及改变UI元素,所以把它放在bindUI中,也提醒我们这个事件响应涉及textbox。事件响应函数如下: _afterValueChange: function (ev) { if (ev.source === UI) { return; } this._inputEl.set(VALUE, ev.newVal); },
首先我们检查事件对象的source属性。如果事件来自UI,我们直接忽略。在这里,属性名UI和它的值都是任意的,你可以根据自己喜好定义。我在设定value的属性值时定义了UI和它的值,所以在这里我就可以访问UI这一属性,你也可以用其它的键值对。实际上,widget也提供了一个相同功能的常数Y.Widget.UI_SRC,只是名字有点长,所以我宁愿自己定义。
一个小技巧:你可以使用_set代替set来改变只读属性的值。_set方法本来是作为受保护方法,只能在类及其子类中访问的,但是javascript中对象成员都是公有的,所以_set实际上是个公共方法,外部也能访问。即使这样,我们还是会给只读属性声明readOnly:true,并且在API文档里也将这一属性标为只读。
最后一个实例方法是syncUI。前两个方法renderUI和bindUI会且仅会执行一次,但syncUI则至少被widget自身调用一次,你也可以在后面的程序中多次调用这个方法。syncUI的作用是根据对象的状态刷新其外观。对象的状态可能一直在变化, 界面也会跟着变化。不过,如何编写这个方法不能一概而论,要根据具体情况。对于简单的用户界面,syncUI可以在每次有变化发生时都重绘界面中的全部内容。而对于复杂的用户界面,重绘整个界面费时且会造成图像闪烁,所以你最好只重绘发生变化的部分,这样的话,你就需要将重绘不同部分的代码分别放在不同的函数中,syncUI会将每一部分只调用一次。还有,在先前的renderUI的例子中,我改变了textbox的值,而只有在syncUI执行之后,这一变化才能在屏幕上显示出来。
更常见的使用方法是给每个UI元素设置单独的重绘函数。这个函数会在初始化时被syncUI调用一次,之后会在配置属性的发生变化后,通过事件响应函数调用。例如 _valueUIRefresh: function (value) { this._inputEl.set(VALUE, value); }
这一函数和其它相似功能的重绘函数会在syncUI中被调用: syncUI: function () { this._valueUIRefresh(this.get(VALUE)); // other such refreshers },
在after事件响应函数中的代码如下: _afterValueChange: function (ev) { if (ev.source === UI) { return; } this._valueUIRefresh(ev.newVal); },
出处:Taobao.com UED Team
责任编辑:bluehearts
上一页 使用YUI 3开发Web应用的诀窍 [5] 下一页 使用YUI 3开发Web应用的诀窍 [7]
◎进入论坛网页制作、WEB标准化版块参加讨论,我还想发表评论。
|