现在主流的JS框架要数ExtJs和JQuery应用的比较广泛。JQuery属于轻量级的,一般做网站应用比较常见,可见块头小的优势。ExtJs比较庞大,它除了对基本的JS语法和HTML DOM操作方式的封装之外,还提供了一套强大的UI库。在企业级B/S解决方案应用上独占优势。就单说它在原生JS的封装,DOM操作方式封装方面也足以藐视JQuery。下面我就通过对比API,体现两种框架的异曲同工之处。我们已JQuery API为主线,来看看ExtJs是否有替代的方案。
注意一点:ExtJs4.0相对上一版本改动较大,本系列文章暂时只对ExtJs4.0及以上版本提供支持。
一、选择器
1.上下文选择器对比
JS对HTML节点的操作比较频繁。所以要经常定位和查询DOM元素。我们分别看看两种框架的实现
获取Id="div1"的DOM元素:
[JQuery]
1
|
$( "#div1" ); |
[ExtJs]
1
|
Ext.get( "div1" ); |
其实Ext.get("div1")与$("#div1")还是有区别的,前者只会获取匹配的第一个元素,后者是匹配的元素集合。ExtJs的等价用法如下:
[ExtJs]
1
|
Ext.select( "#div1" ); |
下面是一个完整的比较代码:
[ExtJs]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//Ext.Element类 :是ExtJs对dom对象的封装 //Ext.CompositeElement类:是ExtJs对dom对象集合的封装 //查询Id=div1的元素,返回第一个匹配元素的Ext.Element类型 //该方法只能查Id,不支持选择器 Ext.get( "div1" ); //功能同上 Ext.fly( "div1" ); //查询Id=div1的元素的dom对象 Ext.get( "div1" ).dom; //或者 Ext.getDom( "div1" ); //获取body元素的Ext.Element类型 Ext.getBody(); //返回当前HTML文档的Ext.Element类型 Ext.getDoc(); //查询Id=div1的元素,返回满足条件的集合Ext.CompositeElement类型 Ext.select( "#div1" ); //查询属性title=d1的div,返回满足条件的集合Ext.CompositeElement类型 Ext.select( "div[title='d1']" ); //查询属性title=d1的div,返回满足条件的dom节点集合 Ext.query( "div[title='d1']" ); |
2.选择器语法简介
JQuery选择器支持CSS3选择符,ExtJs同样也提供支持,除此之外还支持基本的XPath语法。下面分别讲解:
1)CSS3选择符
下面列举的命令是单个形式,都可以无限组合使用。
元素选择符:
- 任意元素
- E 一个标签为 E 的元素
- E F 所有 E 元素的分支元素中含有标签为 F 的元素
- E > F 或 E/F 所有 E 元素的直系子元素中含有标签为 F 的元素
- E + F 所有标签为 F 并紧随着标签为 E 的元素之后的元素
- E ~ F 所有标签为 F 并与标签为 E 的元素是侧边的元素
属性选择符:
@ 与引号的使用是可选的。例如:div[@foo='bar'] 也是一个有效的属性选择符。
- E[foo] 拥有一个名为 “foo” 的属性
- E[foo=bar] 拥有一个名为 “foo” 且值为 “bar” 的属性
- E[foo^=bar] 拥有一个名为 “foo” 且值以 “bar” 开头的属性
- E[foo$=bar] 拥有一个名为 “foo” 且值以 “bar” 结尾的属性 =bar] 拥有一个名为 “foo” 且值包含字串 “bar” 的属性
- E[foo%=2] 拥有一个名为 “foo” 且值能够被2整除的属性
- E[foo!=bar] 拥有一个名为 “foo” 且值不为 “bar” 的属性
伪类:
- E:first-child E 元素为其父元素的第一个子元素
- E:last-child E 元素为其父元素的最后一个子元素
- E:nth-child(n) E 元素为其父元素的第 n 个子元素(由1开始的个数)
- E:nth-child(odd) E 元素为其父元素的奇数个数的子元素
- E:nth-child(even) E 元素为其父元素的偶数个数的子元素
- E:only-child E 元素为其父元素的唯一子元素
- E:checked E 元素为拥有一个名为“checked”且值为“true”的元素(例如:单选框或复选框)
- E:first 结果集中第一个 E 元素
- E:last 结果集中最后一个 E 元素
- E:nth(n) 结果集中第 n 个 E 元素(由1开始的个数)
- E:odd :nth-child(odd) 的简写
- E:even :nth-child(even) 的简写
- E:contains(foo) E 元素的 innerHTML 属性中包含“foo”字串
- E:nodeValue(foo) E 元素包含一个 textNode 节点且 nodeValue 等于“foo”
- E:not(S) 一个与简单选择符 S 不匹配的 E 元素
- E:has(S) 一个包含与简单选择符 S 相匹配的分支元素的 E 元素
- E:next(S) 下一个侧边元素为与简单选择符 S 相匹配的 E 元素
- E:prev(S) 上一个侧边元素为与简单选择符 S 相匹配的 E 元素
CSS 值选择符:
- E{display=none} css 的“display”属性等于“none”
- E{display^=none} css 的“display”属性以“none”开始
- E{display$=none} css 的“display”属性以“none”结尾 =none} css 的“display”属性包含字串“none”
- E{display%=2} css 的“display”属性能够被2整除
- E{display!=none} css 的“display”属性不等于“none”
2)XPath语法
下面通过几个例子来说明:
/html/body/div/div :从根目录开始找,找到正文的第二层全部DIV。
div/div :在全文匹配DIV元素,并获取包含子DIV的全部子DIV集合。
3.Ext.get和Ext.fly的区别:
通俗点讲,他们的作用都是一样的,都是获取元素。但是前者每次调用都会生成一个Ext.Element对象,开辟新的内存空间,而后者共享了一个公用的内存空间,每次调用都会覆盖前一次的信息。由于Ext.Element 比较庞大,后者的好处是可以节省资源。如果你获取的Ext.Element 不需要长期保持重复调用,用后者较为合理。下面通过一个例子来体现他们的区别:
1
2
3
4
5
6
7
8
9
10
11
|
//这样更新的是div1 var div1 = Ext.get( "div1" ); Ext.get( "div2" ); div1.update( "我想更新div1" ); //将get替换成fly后.... //更新的却是div2 var div1 = Ext.fly( "div1" ); Ext.fly( "div2" ); div1.update( "我想更新div1" ); |
我们发现,再次调用Ext.fly后,更新的是DIV2,而再次调用Ext.get不会影响更新的元素。
二、属性
注意:CSS类操作的几个方法相对于早期版本有变化之前是:e.addClass("c2")
[JQuery]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
var e = $( "div[title=t1]" ); //返回第一个匹配元素的title属性 alert(e.attr( "title" )); //设置第一个匹配元素的title属性 e.attr( "title" , "newTitle" ); //移除第一个匹配元素的title属性 e.removeAttr( "title" ); //CSS类 //给第一个匹配元素添加c2样式 e.addClass( "c2" ); //移除 e.removeClass( "c1" ); //轮回 e.toggleClass( "c2" ); //检查c2样式是否存在 e.hasClass( "c2" ); //Html //获取Html e.html(); //更新Html e.html( "<b>更新后的Html</b>" ); //值 e.val(); e.val(150); |
[ExtJs]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
var e = Ext.select( "div[title=t1]" ); //属性 //返回第一个匹配元素的title属性 alert(e.first().getAttribute( "title" )); //设置第一个匹配元素的title属性 e.first().set({ "title" : "newTitle" }); //CSS类 //给第一个匹配元素添加c2样式 e.addCls( "c2" ); //移除 e.removeCls( "c1" ); //轮回 e.toggleCls( "c2" ); //检查c2样式是否存在 e.hasCls( "c2" ); //Html //获取Html e.first().dom.innerHTML; //更新Html e.first().update( "<b>更新后的Html</b>" ); //值 e = Ext.get( "text1" ); e.getValue(); e.set({ value: 150 }); |
四、筛选
[JQuery]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
var e = $( ".c1" ); //过滤 //获取匹配的第二个元素 e.eq(1); //再次筛选,属性title=t1的div e.filter( "div[title=t1]" ); //父节点Id=div1时返回true e.parent().is( "#div1" ); //查找 //获取集合中第一个,最后一个: e.first(); e.last(); //前一个,后一个: e.prev(); e.next(); //子节点第一个,最后一个: var e2 = $( "#div1" ); e2.children().first(); e2.children().last(); |
[ExtJs]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
var e = Ext.select( ".c1" ); //过滤 //获取匹配的第二个元素 e.item(1); //再次筛选,属性title=t1的div,集合中不满足条件的元素自动移去 e.filter( "div[title=t1]" ); e = Ext.select( ".c1" ); //父节点Id=div1时返回true e.first().parent().is( "#div1" ); //查找 //获取集合中第一个,最后一个: e.first(); e.last(); //单个元素的前一个,匹配选择器的后一个: e.item(1).next( "div[title=t2]" ); e.item(1).prev(); var e2 = Ext.get( "div1" ); //获取子节点的第一个,最后一个: e2.first(); e2.last(); |
五、文档处理
[JQuery]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//插入 var e = $( "div .c1" ); //e元素结束之前插入 e.first().append( "<b>新内容</b>" ); //e元素开始之后插入 e.first().prepend( "<b>新内容</b>" ); //e元素开始之前插入 e.first().before( "<b>新内容</b>" ); //e元素结束之后插入 e.first().after( "<b>新内容</b>" ); //包裹 e.eq(2).wrap( "<p></p>" ); e.eq(2).unwrap(); //替换 e.eq(2).replaceWith( "<b>被替换的</b>" ); //删除 e.eq(3).remove(); //清空标签内的html e.eq(0).empty(); |
[ExtJs]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
var e = Ext.select( "div .c1" ); //插入 //分别在相对于文档e的四个位置插入html: e.first().insertHtml( "afterBegin" , "<b>新内容</b>" ); e.first().insertHtml( "beforeEnd" , "<b>新内容</b>" ); e.first().insertHtml( "beforeBegin" , "<b>新内容</b>" ); e.first().insertHtml( "afterEnd" , "<b>新内容</b>" ); //包裹 e.wrap({ tag: 'p' }); //用text1替换集合第五个元素 e.replaceElement(4, "text1" , true ); //替换用当前元素去替换掉div2标签 e.first().replace( "div2" , true ); //删除 e.first().remove(); //移除集合中第三个元素 e.removeElement(2, true ); |
六、CSS
[JQuery]
1
2
3
4
5
6
7
8
9
|
var e = $( "div1" ); //设置样式 e.css( "width" , "550px" ); e.css( "position" , "absolute" ); //设置高度 e.height(100); //获取宽度 e.width(); |
[ExtJs]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
var e = Ext.get( "div1" ); //设置样式 e.setStyle( "width" , "550px" ); e.applyStyles({ height: "500px" , color: "red" , position: "absolute" }); //设置高度,带动画效果 e.setHeight(100, true ); //设置定位 e.setLeft( "50px" ); e.setTop( "10px" ); e.setLeftTop( "100px" , "50px" ); //设置尺寸 e.setSize( "100px" , "200px" ); //设置xy坐标 e.setXY([10, 10]); //获取宽度 e.getWidth(); //获取坐标 e.getXY(); |
七、事件
[JQuery]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
var e = $( "#div1" ); //事件绑定 //给元素绑定click事件: var clickhandler = function () { alert( "click事件被触发!" ); }; e.bind( "click" , clickhandler); //模拟click事件: e.trigger( "click" ); //解除绑定click事件 e.unbind( "click" , clickhandler); //事件切换 e.hover( function () { e.css( "background-color" , "Red" ); }, function () { e.css( "background-color" , "Aqua" ); }); |
[ExtJs]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
var e = Ext.get( "div1" ); //事件绑定 //给元素绑定click事件: var clickhandler = function () { Ext.Msg.alert( "消息" , "click事件被触发!" ); }; e.on( "click" , clickhandler); //解除绑定click事件 e.un( "click" , clickhandler); //事件切换 e.hover( function () { e.setStyle( "background-color" , "Red" ); }, function () { e.setStyle( "background-color" , "Aqua" ); }); |