Ext js 提供了一個簡便的方法來處理DOM。我們可以創建節點, 修改樣式,添加事件監聽器,和創建漂亮的動畫。而且可以不用管各瀏覽器的兼容性。
用來處理DOM節點的類爲Ext.dom.Element類。這個類是包裝了html原生節點,並且提供了許多的方法和實用工具來操作節點。
直接操作DOM被認爲是一個非常差的實踐,在index文件中,不應該有任何DOM 標記,我們在這裏的舉的例子,只是爲了說明DOM操作的原理
獲得元素
Ext.get
Ext.get方法,它封裝在Ext.dom.Element類中, 用來根據ID查找DOM元素,並返回一個Ext.Element元素
// by id
var el = Ext.get("my-div");
// by DOM element reference
var el = Ext.get(myDivElement);
<!doctype html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<title>Extjs - Loader</title>
<link rel="stylesheet" type="text/css" href="../ext-5.1.1/build/
packages/ext-theme-neptune/build/resources/ext-theme-neptune-all.css">
<script src="../ext-5.1.1/ext-all.js"></script>
<script src="../ext-5.1.1/build/packages/ext-theme-neptune/build/exttheme-
neptune.js"></script>
<script type="text/javascript">
Ext.onReady(function(){
var mymainDiv = Ext.get('main');
var mysecondDiv = Ext.dom.Element.get('second');
});
</script>
</head>
<body style="padding:10px">
<div id="main"></div>
<div id="second"></div>
</body>
</html>
通常我們獲得一個元素是使用 Ext.get, 這是Ext.dom.Element.get的一個快捷方式
注意,我們不需要使用CSS選擇器那樣,傳入#
返回的兩個元素,都是Ext.dom.Element的實例,然後可以使用setStyle方法,設置它的樣式
div.setStyle({
width: "100px",
height: "100px",
border: "2px solid #444",
margin: "80px auto",
backgroundColor: "#ccc"
});
//添加和刪除樣式
div.addCls("x-testing x-box-component");
div.removeCls("x-testing");
還有一些其它操作元素的方法,比如動畫
div.fadeOut()
.fadeIn({
duration:3000
});
var el = Ext.get("my-div");
// no animation
el.setWidth(100);
// default animation
/*
Option Default Description
--------- -------- ---------------------------------------------
duration 350 The duration of the animation in milliseconds
easing easeOut The easing method
callback none A function to execute when the anim completes
scope this The scope (this) of the callback function
*/
el.setWidth(100, true);
//custom animate
// Element animation options object
var opt = {
duration: 1000,
easing: 'elasticIn',
callback: this.foo,
scope: this
};
// animation with some options set
el.setWidth(100, opt);
選擇子元素
Ext.dom.Element的實例可以通過css選擇器選擇子孫節點, 這裏有三個方法
* query
* selectNode
* select
這三個方法都可以接收有效的CSS選擇器,應爲它們的底層都是Javascript的querySelectorAll, 它們之前的不同在於,返回的類型
可以能過以下的代碼,返回一個HTMLELement實例的數組
element.query('.foo');
也可以通過設置 asDom參數爲false, 則返回的類型爲Ext.dom.Element
element.query('.foo', false);
如果想得到第一個匹配的HTMLElement,則使用selectNode方法
element.selectNode('.foo');
同樣,如果想返回的Ext.dom.Element, 設置asDom爲false.
element.selectNode('.foo', false);
select方法用於返回類型爲CompositeElementLite 或者CompositeElement. 它們都是元素的集合類型,可以將Ext.dom.Element的方法應用於組中。兩者的不同在於CompositeElementLite是一個HTMLElement的實例,而CompositeElement是一個Ext.dom.Element類型集合。
//CompositeElementLite
element.select('.foo');
//CompositeElement
element.select('.foo', true);
對於query方法,也可以不用應用在Ext.dom.Element上,比如,查找在document下的,選擇器爲’.foo’的HTMLElements數組,可以簡單的它document對像包裝爲Ext.dom.Element實例。
Ext.fly(document).query('.foo');
Ext.query
Ext JS允許我們查找某一類的DOM節點,查找引擎支持CSS3選擇器,或者路徑xpath選擇器. 它返回找到的elements組成的數組(HTMLElement[] 或者 Ext.dom.Element[]),如果沒有找到,則返回一個空的數組。
負責的這個類爲Ext.dom.Query類。這個類包含了許多用於搜索的方法.
Ext.dom.Query 是一個單例類,所以我們不需要創建一個新的實例用來查找 DOM元素
在下面的代碼中,myCustomComponent.getEl().dom作爲上下文搜索的根節點。Ext.query將在這個根節點下查找,並且返回一個包含類爲’oddRow’
var someNodes = Ext.query('.oddRow',
myCustomComponent.getEl().dom); //.dom表示獲得HTMLElement
Ext.select
CSS/XPath選擇器,返回單個的CompositeElement, CompositeElement表示一個elements的集合.
CompositeElement包含filter, iterate 以及集體類的方法
var rows = Ext.select('div.row'); ////Matches all divs with class row
rows.setWidth(100);
//也可以在單行中使用
Ext.select('div.row').setWidth(100);
通過逗號分隔,我們可以使用多個選擇器
Ext.select('div.row, span.title'); //Matches all divs with class row and all spans with class title
默認情況下, select方法是查找整個DOM樹。我們可以給它指定一個根元素,只查找這個元素下,符合條件的元素
//先查找ID爲myEl的元素
Ext.get('myEl').select('div.row');
//也可以使用以下的方法
Ext.select('div.row', true, 'myEl');
查找一個class爲.row, 並且屬性中表含了title=bar的div, 並且返回找到的第一個子元素
Ext.select('div.row[title=bar]:first')
Ext.ComponentQuery
允許你通過ID, xtype, 和屬性查找一個組件。你可以在全局(Ext.ComponentManager)或者指定的根組件(Ext.container.Container)中查找
http://docs.sencha.com/extjs/6.0.2-classic/Ext.ComponentQuery.html
以下的代碼,是根據xtype,返回所有的button組件.
Ext.ComponentQuery.query('button');
根據ID查找
Ext.ComponentQuery.query('#foo');
以下的代碼,返回xtype的類型爲button, title爲my button的元素
Ext.ComponentQuery.query("button[title='my button']");;
//or
parent.query('textfield[title=my button]');
也可以嵌套選擇器
Ext.ComponentQuery.query('formpanel numberfield'); // form頁板下的numberfield
以下的代碼,返回匹配元素的第一個子直接子元素,如果沒有找到,返回null
parent.child('button[itemId=save]');
同樣,我們也可以使用nextNode, up, down, previousSibling等方法.
Ext.fly()
fly ( dom , named ) ,它包裝一個dom元素爲Ext.dom.Element,但不會保存這個元素的引用,適用於對一個元素的一次操作,後續不在使用,可以提高整個程序的效率.
<input type = 'text' id = 'studentName'>
Ext.fly('studentName').set({'value' : 'John'});
創建元素
var myDiv1 = Ext.get('div1');
myDiv1.createChild('Child from a string');
myDiv1.createChild('<div>Element from a string</div>');
以上都是通過字符串的作爲參數,將字符串以innerHTML的方式,傳遞給myDiv1. 這種方式不簡維護代碼和管理,Extjs爲我們提供了配置對像的方式
createChild ( config , [insertBefore] , [returnDom] ) : Ext.dom.Element / HTMLElement
通過傳遞的DomHelper創建一個元素,如果有傳遞insertBefore, 則將新創建的元素在它之前插入,否則爲元素的末尾。
* config: Object
DomHelper元素配置對像,如果沒有指定tag(e.g., {tag: ‘input’}), 則自動生成div.
* insertBefore: HTMLElement(optional)
指定插入元素在insertBefore這個元素之前
* returnDom: Boolean(optional)
如果爲true, 則返回Dom節點,而不是Element. 默認爲false;
通過代碼說明
myDiv1.createChild({
tag : 'div',
html : 'Child from a config object'
});
如果想要插入嵌套標籤,可以如下
myDiv1.createChild({
tag : 'div',
id : 'nestedDiv',
style : 'border: 1px dashed; padding: 5px;',
children : {
tag : 'div',
html : '...a nested div',
style : 'color: #EE0000; border: 1px solid'
}
});
如果想在第一行位置插入
//insertFirst ( el , [returnDom] ) : Ext.dom.Element / HTMLElement
myDiv1.insertFirst({
tag : 'div',
html : 'Child inserted as node 0 of myDiv1'
});
指定位置插入
myDiv1.createChild({
tag : 'div',
id : 'removeMeLater',
html : 'Child inserted as node 2 of myDiv1'
}, myDiv1.dom.childNodes[3]);
Removing child nodes
刪除一個元素,要比添加一個元素簡單,只需要先找到這個元素,在調用它的remove方法。爲了說明,我們先創建段HTML:
<div id='div1' class="myDiv">
<div id='child1'>Child 1</div>
<div class='child2'>Child 2</div>
<div class='child3'>Child 3</div>
<div id='child4'>Child 4 </div>
<div>Child 5</div>
</div>
刪除第一個元素
var myDiv1 = Ext.get('div1');
var firstChild = myDiv1.down('div:first-child');
firstChild.remove();
在上面的代碼中 down ( selector , [returnDom] ) : HTMLElement / Ext.dom.Element 會根據css選擇器(選擇器不應該包含id), 會在父元素的子孫元素查找。
也可以刪除最後一個元素
var myDiv1 = Ext.get('div1');
var lastChild = myDiv1.down('div:last-child');
lastChild.remove();
Using templates and XTemplates
Ext.Template類是一個非常強大的核心工具,允許你以佔位符的方式創建一個多級的DOM。一旦創建完成,你可以多次重覆使用。傳遞給模板的數據通過佔位符填充, 大部分 UI widget都使用了模板,比如grid panel, data view, and ComboBox
使用template
首先我們創建一個簡單的template
var myTpl = Ext.create('Ext.Template' , "<div>Hello {0}.</div>");
myTpl.append(document.body, ['Marjan']); //target: document.body
myTpl.append(document.body, ['Michael']);
myTpl.append(document.body, ['Sebastian']);
在這個例子中,我們先創建了個 Ext.Template, 並且傳遞一個帶有佔位符({})的div字符串. 在這個例子中,我們的佔位符爲一個數字,並傳遞的值爲一個數組。Template 也可以解構一個對像,如下所示
var myTpl = Ext.create('Ext.Template', [
'<div style="background-color: {color}; margin: 10px;">',
'<b> Name :</b> {name}<br />',
'<b> Age :</b> {age}<br />',
'<b> DOB :</b> {dob}<br />',
'</div>'
]);
myTpl.compile();
myTpl.append(document.body,{
color : "#E9E9FF",
name : 'John Smith',
age : 20,
dob : '10/20/89'
});
myTpl.append(document.body,{
color : "#FFE9E9",
name : 'Naomi White',
age : 25,
dob : '03/17/84'
});
在第一步,我們創建的模塊不在是一個長字符串,而是一個數組,利用美觀。在第二步的編譯,可以消除正則表達式的開發,提高模塊合併數據的速度。在這兩段代碼裏,我們其實不用編譯,因爲只有針對大型的Application才能體現它的效果。
對於template,我們使用了兩種不同的html結構。但如果你要填充的是一個對像數組? 比如,Ajax請求,返回了一個數據對像數組, 然後你需要爲這個數組的每一個數據對像應用一個template,一種方法是使用 for loop或者Ext.each方法,在調用我們上面的template.
另一種是使用XTemplates代替,會使得代碼更加清晰。
Looping with XTemplates
XTemplates可以被用於單個的數據對像,但它更易於處理數據對像數據。XTemplate 繼承於Template, 並且提供了更多的方法。 如下所示
var tplData = [{
color : "#FFE9E9",
name : 'Naomi White',
age : 25,
dob : '03/17/84',
cars : ['Jetta', 'Camry', 'S2000']
},{
color : "#E9E9FF",
name : 'John Smith',
age : 20,
dob : '10/20/89',
cars : ['Civic', 'Accord', 'Camry']
}];
var myTpl = Ext.create('Ext.XTemplate', [
'<tpl for=".">',
'<div style="background-color: {color}; margin: 10px;">',
'<b> Name :</b> {name}<br />',
'<b> Age :</b> {age}<br />',
'<b> DOB :</b> {dob}<br />',
'</div>',
'</tpl>'
]);
myTpl.compile();
myTpl.append(document.body, tplData);
在XTemplate初始化時,我們使用了一個自定義的tpl標籤, 並且設置了for屬性, 值爲”.”. tpl標籤類似於邏輯或者行爲標籤,它有兩個值,for and if, 它改變XTemplate生產html代碼段的方式。 “.” 表示遍歷傳遞給XTemplate的數組。
Advanced XTemplate usage
var myTpl = Ext.create('Ext.XTemplate', [
'<tpl for=".">',
'<div style="background-color: {color}; margin: 10px;">',
'<b> Name :</b> {name}<br />',
'<b> Age :</b> {age}<br />',
'<b> DOB :</b> {dob}<br />',
'<b> Cars : </b>',
'<tpl for="cars">',
'{.}',
'<tpl if="this.isCamry(values)">',
'<b> (same car)</b>',
'</tpl>',
'{[ (xindex < xcount) ? ", " : "" ]}',
'</tpl>',
'<br />',
'</div>',
'</tpl>',
{
isCamry : function(car) {
return car === 'Camry';
}
}
]);
myTpl.compile();
myTpl.append(document.body, tplData);
在遍歷cars循環內,我們使用字符串 “{.}”, 它表示當前cars數組的當前值。在這裏爲car的名字。
this.isCamry定義在整個XTemplate的最後,它通過一個對像的方式,會傳遞給XTemplate的構造函數。這就是爲什麼我們可以在if條件語句中調用this.isCamery。
在XTemplate中的 {[…JS code …]}被解析爲通用的Javascript代碼。它可以訪問XTemplate中的本地變量,在這裏,xindex表示當前的循環值, xcount表示數組長度。