首先看一段代码 :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <title>composite 测试</title> <script type='text/javascript' src='ext-base.js'></script> <script type='text/javascript' src='ext-core.js'></script> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> </ul> <script type='text/javascript'> Ext.onReady(function(){ var tests=[]; Ext.select('ul li').each(function(el,this_,index_i) { var ob=el; //或者 //ob=this_.item(index_i); tests.push(ob); }); for(var i=0;i<tests.length;i++) { alert(tests[i].dom.innerHTML); } }) ; </script> </body> </html>
我们期望输出 1 2 3,可实际上输出 3 3 3,总可以看出得到的全部对象实际上是一个 Ext.Element 对象。
即Ext 默认在遍历 对象集合时用了 flyweight, 返回组合对象为Ext.CompositeElementLite
(select 参数第二个 ,默认为false,各个子节点共用一个 Ext.Element.Flyweight)
From Extjs:
Ext.Element.select = function(selector, unique, root){ var els; if(typeof selector == "string"){ els = Ext.Element.selectorFunction(selector, root); }else if(selector.length !== undefined){ els = selector; }else{ throw "Invalid selector"; } return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els); };
若要强制不要进行共享ext对象,则要构造一个全新的 Ext对象,即可得的解决方法
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <title>composite 测试</title> <script type='text/javascript' src='ext-base.js'></script> <script type='text/javascript' src='ext-core.js'></script> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> </ul> <script type='text/javascript'> Ext.onReady(function(){ var tests=[]; Ext.select('ul li').each(function(el,this_,index_i) { //强制不要共享了,构造一个自己的ext 对象 var ob=Ext.get(el.dom) tests.push(ob); }); for(var i=0;i<tests.length;i++) { alert(tests[i].dom.innerHTML); } }) ; </script> </body> </html>
由此可见,在应用 ext CompositeLite 时 ,要么 在 each 中一次性解决当前问题 ,要么 构造新的对象 后期处理,特别是在 each 中 要进行事件处理的 ,要特别小心,最好 构造新的对象 添加事件listener ,见如下 代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <title>composite 测试</title> <script type='text/javascript' src='ext-base.js'></script> <script type='text/javascript' src='ext-core.js'></script> <style type='text/css'> li { border :2px solid green; margin:30px; cursor:pointer; } </style> </head> <body> <ul> <li>clicke me 1</li> <li>clicke me 2</li> <li>clicke me 3</li> </ul> <script type='text/javascript'> Ext.onReady(function(){ var tests=[]; //强制不共享 Ext.select('ul li',true).each(function(el,this_,index_i) { el.on('click' ,function() { alert(el.dom.innerHTML); }); }); //手动不共享 Ext.select('ul li').each(function(el,this_,index_i) { //正确 var ob=Ext.get(el.dom); //错误1 //var ob=el; //或 错误2 //var ob=this_.item(index_i); ob.on('click' ,function() { alert(ob.dom.innerHTML); }); }); }) ; </script> </body> </html>
注:select ( String selector
, [Boolean unique
] ) : CompositeElement/CompositeElementLite
selector
: String
unique
: Boolean
CompositeElement/CompositeElementLite
unique ,所以 子节点共用了一个 Ext.Element.Flyweight ,若要为每个子元素都给一个
Ext.Element,则要调用
addListener : function(eventName, fn, scope, options){ Ext.EventManager.on(this.dom, eventName, fn, scope || this, options); return this; },
// fixes scope with flyweight addListener : function(eventName, handler, scope, opt){ var els = this.elements, len = els.length, i, e; for(i = 0; i<len; i++) { e = els[i]; if(e) { Ext.EventManager.on(e, eventName, handler, scope || e, opt); } } return this; },
Ext.select("a").on("click",function(){console.log(this);}); Ext.select("a",true).on("click",function(){console.log(this);});
Ext.select("a").on("click",function(){var el=Ext.fly(this);console.log(el);});