Tutorial:RelayEvents (Chinese) (Legacy)
This version of our Learning Center is unmaintained.
This article may be out-of-date or contain incorrect information.
Please visit the new Sencha Learning Center for up-to-date material.
From Sencha - Learn
| Summary: 创建自定义的事件,然后透过RelayEvents与其他组件发生联系。 |
| Author: MikeB(译者:Frank Cheung) |
| Published: 4 March 2009 |
| Ext Version: 2.2.0+ |
Languages: English Chinese
|
Contents |
引言
我曾看到过一种现象,就是时下讨论着组件间如何交流通迅的人并不在少数,还有怎么使用这个relayEvents()函数。
没错,我也存在过相类似的问题。我现在终于明白,relayEvents()函数用在什么地方了,这是我写好一个程序后的收获。
现在不算太难搞了,可以说迎刃而解,也知道怎么把它运用起来。
--译注:以下一段内容皆因时间上的关系,而且为参考内容,因此不作翻译--
So first, a brief explaination of the simple application I put together for this tutorial. My final application is much more complex than this tutorial but I've simplified things down quite a bit while still having something here which other developers might find useful.
I have an application where I have a window containing a two pane border layout. The layout has a left, Navigation panel using a tree component, and a right content panel (which is simply an Ext.Panel component).
When the user clicks on a branch or a node in the tree I want to see something happen in the content panel. But rather than having the tree component know anything about the content panel, I want the tree to fire a custom event which is then intercepted by the window which contains both the tree and the panel. The window, knowing about both the Navigation Tree and the Content Panel will take the information passed up from the event in the Tree Panel and process it to put information in the Content Panel.
So let's first take a look at the HTML code for the application (you can take and drop this entire block of code in the "Examples" directory and it should work perfectly fine).
代码解析
网页
网页文件本身是比较清晰直观的,如果你试过例子中的文件那么便能迅速了解这份JavaScript文件。接着以下三份文件将会作简单地说明:
- wcc.tree.js
- wcc.app.js
- relayEvents.js
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>Relay Events</title> <link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" /> <!-- GC --> <!-- LIBS --> <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script> <!-- ENDLIBS --> <script type="text/javascript" src="../../ext-all.js"></script> <script type="text/javascript" src="wcc.tree.js"></script> <script type="text/javascript" src="wcc.app.js"></script> <script type="text/javascript" src="relayEvents.js"></script> <!-- Common Styles for the examples --> <link rel="stylesheet" type="text/css" href="../shared/examples.css" /> </head> <body> <script type="text/javascript" src="../shared/examples.js"> </script><!-- EXAMPLES --> <h1>Ext.relayEvents</h1> <button id="theBtn">Run</button> <p>这是没有经过混淆的文件便于阅读: <ul style="margin-left:100px;"> <li><a href="wcc.tree.js">wcc.tree.js</a></li> <li><a href="wcc.app.js">wcc.app.js</a></li> <li><a href="relayEvents.js">relayEvents.js</a></li> </ul> </p> </body> </html>
自定义TreePanel
第一份文件(wcc.tree.js),是我自定义标准树TreePanel的扩展。另一种方式,将配置项作为参数传入的方式TreePanel,但是我没有使用这种方式,而是在我的程序中扩展后,周而复始地不断使用,简单地创建一个新扩展,不断实现化它就可以反复地使用。
我新建了一个treeLoader对象,使得采用“GET”的http请求进行通信,然后将onclick处理函数分配在每一个新建的节点上。
每个不同的节点或分支点击后都会触发自定义的事件“clickLeaf”或“clickBranch”,执行onclick处理函数。
/** * 自定义的Tree,进行一些典型的设置,还有把TreeSorter对象新添加的事件加入到该组件中。 */ Ext.ns("wcc"); // 建立属于自己部分的命名空间 wcc.tree = Ext.extend(Ext.tree.TreePanel, { initComponent: function() { // 开始配置组件! this.rootID = this.rootID ? this.rootID : Ext.id(); Ext.apply(this, { // 默认的配置项 animate:true, autoScroll:true, enableDD:true, containerScroll: true, // 定义tree loader loader: new Ext.tree.TreeLoader( { url : this.url, requestMethod : "GET", createNode : function( attr ) { // 哪一种要触发的事件类型? var NodeEvent = attr.leaf ? "clickLeaf" : "clickBranch"; attr.listeners = { click : function( obj, evt, scope) { // 触发自定义的事件 this.ownerTree.fireEvent(NodeEvent, this, attr, attr.text); } }; // 执行原来的方法 return Ext.tree.TreeLoader.prototype.createNode.call(this, attr); } }), root : new Ext.tree.AsyncTreeNode({ text: this.rootID, id : this.rootID, expanded : true, draggable : false }) }); wcc.tree.superclass.initComponent.apply(this, arguments); new Ext.tree.TreeSorter(this, {folderSort:true}); // 单击树节点时就会触发这两个新事件 this.addEvents( 'clickLeaf', 'clickBranch'); } }); Ext.reg('wccTree', wcc.tree);
以下代码才是真正的自定义过程:
this.ownerTree.fireEvent(NodeEvent, this, attr, attr.text);
this.ownerTree代表wcc.tree的实例,触发刚才设置的事件,看看是“clickLeaf”还是“clickBranch”。
刚才这一行:
this.addEvents( 'clickLeaf', 'clickBranch' );
就是执行这里定义好的扩展事件。
Application Class
ok现在我们已经弄好一个TreePanel,并为将来的事件预留了相应的位置,接下来我们干什么好呢?
嗯我们看看qcc.app.js文件内的application class(我把涉及的类都封装在这个application中)。
强调一次这里没啥特别的地方,我尝试在“wcc”的命名空间中创建新类,里面的私有变量和方法可为不同的面板和窗体所服务。
wcc.app = function() { // 私有的变量…… var win; var button; // 私有的方法…… var buildApp = function( cfg ) { // 这是公有的配置 var dfltCfgParams = { split : true, collapsible : true, margins : "3 0 3 3", cmargins : "3 3 3 3" }; // 设置导航树的配置项参数 var treeParams = Ext.apply( { region : "west", width : 200, frame : true, title : "Navigation" }, cfg ); // 创建树面板 var tree = new wcc.tree( Ext.apply( treeParams, dfltCfgParams ) ); // 创建content面板 var content = new Ext.Panel(Ext.apply({ title : "Content", region : "center", frame : true }, dfltCfgParams )); // 创建一个border layout风格的窗体,有tree和content面板 win = new Ext.Window({ title : 'Layout Window', closable : true, width : 600, height : 350, plain : true, layout : 'border', items : [ tree, content ] }); // 关联tree的自定义事件“clickLeaf”和“clickBranch” win.relayEvents(tree, ['clickLeaf', 'clickBranch']); // 提供TreePanel对象的自定义处理函数。 // 例子中没有特别出彩的地方不过你可以加入更多 win.on( { 'clickLeaf' : function (nodeObj, nodeAttr, nodeText) { console.log("Window - NodeClick - " + nodeText); content.body.update("Hello World... Loading Text from Leaf: " + nodeObj.id); }, 'clickBranch' : function(nodeObj, nodeAttr, nodeText) { console.log("Window - BranchClick - " + nodeText); content.body.update("Hello World... Loading Text from Branch: " + nodeObj.id); }, scope : this }); }; // Public部分 return { myTree : {}, root : {}, // 实际上我想把写好的类规范好以便调试和归档,但现在不是“产品的代码” name : "wcc:App", desc : "Generic App Class in private Namespace", init : function(cfg) { this.curFunc = this.name + ".init()"; button = Ext.get("theBtn"); button.on("click" , function() { buildApp( cfg ); win.show(button); }); } }; // 返回公有部分(Public) }();
再说一下这里关键的一行:
win.relayEvents(tree, ['clickLeaf', 'clickBranch']);
告诉这里的窗体可以中断并接着处理由Tree组件传入的“clickLeaf”和“clickBranch”事件。
最终一步
最后,这些代码就大功告成啦……
Ext.onReady( function() { console.log("App running..."); wcc.app.init({ url : "getNodes.php", rootID : "examples" // 此处为要显示的目录名称 }); }, wcc.app, true); console.log("程序可以跑起来了……");
注意我是从别的TreePanel例子弄来的"getNodes.php"。
这样透过relayEvents()方法就可以简单而且灵活地事件编程,各组件之间的消息事件通信,和整个程序的层次结构、复杂的对象关系带来莫大的好处。
这是关于该帖子的连接[1],那里也有源文件下载(包括getNodes.php)的还是没有压缩的直接放进你的测试目录吧。

Chinese