一织阳、sort深入
這次我們要完成一個(gè)表格排序的案例咳短,那說到排序填帽,最終肯定是歸結(jié)于數(shù)組的排序。對(duì)于數(shù)組的排序咙好,我們最先想到的肯定是sort方法篡腌,所以我們深入了解一下sort。
1.1勾效、基本排序
定義數(shù)組:
var ary = [22, 3, 14, 12, 23, 1, 48];
在mdn中對(duì)sort的定義如下:
arr.sort(compareFunction)
compareFunction:可選嘹悼。用來指定按某種順序進(jìn)行排列的函數(shù)。如果省略层宫,元素按照轉(zhuǎn)換為的字符串的諸個(gè)字符的Unicode位點(diǎn)進(jìn)行排序杨伙。
從mdn的描述中可以看出,如果沒有指定一個(gè)函數(shù)作為參數(shù)萌腿,那么只能比較10以內(nèi)的數(shù)字缀台,所以一般都會(huì)指定一個(gè)函數(shù)作為參數(shù)。
在compareFunction中可以傳入兩個(gè)參數(shù)假定為a哮奇、b,這兩個(gè)參數(shù)即為待比較多兩個(gè)數(shù):
- a:每一次執(zhí)行匿名函數(shù)的時(shí)候睛约,找到的數(shù)組中的當(dāng)前項(xiàng)鼎俘;
- b:當(dāng)前項(xiàng)的后一項(xiàng)
compareFunction的返回值則為一個(gè)數(shù)字,如果返回值大于0辩涝,則讓a和b交換一下位置贸伐,如果返回值小于等于0,原來的位置不動(dòng)怔揩。
在本例中:
如果:
return a - b
捉邢,表示升序排序脯丝,如果a大于b,返回值大于0伏伐,a和b交換位置宠进,輸出的結(jié)果為:[1, 3, 12, 14, 22, 23, 48]
。如果:
return b - a
藐翎,表示降序排序材蹬,如果b大于a,返回值大于0吝镣,a和b交換位置堤器,輸出的結(jié)果為:[48, 23, 22, 14, 12, 3, 1]
。
1.2末贾、對(duì)象數(shù)組(二維數(shù)組)排序
定義對(duì)象數(shù)組:
var ary = [
{name: 'iceman', age: 25},
{name: 'mengzhe', age: 13},
{name: 'shoushou', age: 107},
{name: 'jiajia', age: 256}
];
對(duì)象數(shù)組的排序闸溃,正常情況都是要求根據(jù)某個(gè)值為數(shù)字的屬性來排序,在本例中拱撵,我們要求以年齡來排序辉川。
sort方法的參數(shù)compareFunction的參數(shù)中兩個(gè)參數(shù),并一定就一定是要數(shù)字裕膀,這兩個(gè)參數(shù)是數(shù)組中的某一項(xiàng)员串,注意是數(shù)組中的某一項(xiàng)哦!也就是說在對(duì)象數(shù)組中昼扛,這兩個(gè)參數(shù)代表的是一個(gè)對(duì)象寸齐。在得到了這個(gè)結(jié)論之后,我們就可以根據(jù)通過對(duì)象的屬性來排序了:
ary.sort(function (a, b) {
return parseFloat(a.age) - parseFloat(b.age);
});
console.log(ary);
二抄谐、json
現(xiàn)在與服務(wù)端的交互中一般都是使用json渺鹦,應(yīng)該基本被使用xml了,我是做Android開發(fā)的蛹含,在我開始做Android的時(shí)候就是使用json毅厚,所以json也是現(xiàn)在主流的一種數(shù)據(jù)交互格式。浦箱。
可能很多人會(huì)將json歸結(jié)于一種新的數(shù)據(jù)類型吸耿,其實(shí)并不是這樣的,json只是一種特殊的數(shù)據(jù)格式酷窥,歸根結(jié)底json還是對(duì)象數(shù)據(jù)類型的咽安。比如,
普通格式的對(duì)象如下:
var obj = {name:'iceman' , age:7};
json格式對(duì)象如下:
var jsonObj = {"name":"iceman" , "age":7};
相對(duì)于普通格式的對(duì)象來說蓬推,json對(duì)象只是把屬性名用雙引號(hào)包起來了妆棒。
在window瀏覽器對(duì)象中,提供了一個(gè)叫做JSON的屬性(window.JSON),它里面提供了兩個(gè)方法:
- JSON.parse :把JSON格式的字符串糕珊,轉(zhuǎn)換為JSON格式的對(duì)象动分;
- JSON.stringify :把JSON格式的對(duì)象,轉(zhuǎn)換為JSON格式的字符串红选;
var jsonObj = {"name":"iceman" , "age":7};
var jsonStr = JSON.stringify(jsonObj); // --> 字符串
console.log(jsonStr);
var str = '{"name":"iceman" , "age":7}';
console.log(JSON.parse(str));
注意: 在IE6~7中澜公,window下沒有JSON屬性,所以parse和stringify方法都不存在了纠脾,那么這時(shí)候要把JSON格式的字符串轉(zhuǎn)換為JSON格式的對(duì)象可以使用eval方法:
var str = '{"name":"iceman" , "age":7}';
eval("(" + str + ")");
使用eval裝好JSON格式的對(duì)象玛瘸,一定要手動(dòng)加一個(gè)小括號(hào)。
二苟蹈、數(shù)據(jù)綁定
2.1糊渊、準(zhǔn)備JSON格式的數(shù)據(jù)
var ary = [
{
"title": "11111",
"desc": "aaaaaaaa"
},
{
"title": "22222",
"desc": "bbbbbbbb"
}
......
];
2.2、頁面結(jié)構(gòu)
<ul id="ul1">
<li>原來就有的慧脱,這里有鼠標(biāo)的移入移出事件</li>
</ul>
body, ul, li {margin: 0; padding: 0; list-style: none;}
#ul1 {margin: 10px auto; padding: 10px; width: 300px; border:1px solid #008000; }
#ul1 li {position: relative; padding-left: 28px; height:35px; line-height: 35px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
#ul1 li span { display: block; position: absolute; top: 6px; left: 0; width: 21px; height: 21px; line-height: 20px; text-align: center; border: 1px solid #ccc; font-size: 12px; border-radius: 50%; }
尋找元素以及添加移入移出事件:
var oUl = document.getElementById('ul1');
var oLis = oUl.getElementsByTagName('li');
for (var i = 0; i < oLis.length; i++) {
oLis[i].onmouseover = function () {
this.style.backgroundColor = 'pink';
};
oLis[i].onmouseout = function () {
this.style.backgroundColor = '';
};
}
2.3渺绒、DOM深入:重繪與回流
回流(也叫重排):當(dāng)頁面中的HTML結(jié)構(gòu)發(fā)生改變(增加、刪除元素菱鸥、位置發(fā)生改變...)宗兼,瀏覽器都需要重新計(jì)算一遍最新的DOM結(jié)構(gòu),重新對(duì)當(dāng)前的頁面進(jìn)行渲染氮采;
重繪:某一個(gè)元素的部分樣式發(fā)生改變了(背景顏色殷绍、字號(hào)等),瀏覽器只需要重新渲染當(dāng)前頁面即可鹊漠;
2.4主到、動(dòng)態(tài)創(chuàng)建節(jié)點(diǎn)再追加到頁面的方式實(shí)現(xiàn)數(shù)據(jù)綁定
for (var i = 0; i < ary.length; i++) {
var cur = ary[i];
var oLi = document.createElement('li');
oLi.innerHTML = '<span>' + i + '</span>' + cur.title + '---' + cur.desc;
oUl.appendChild(oLi);
}
優(yōu)勢(shì): 把需要?jiǎng)討B(tài)綁定的內(nèi)容一個(gè)個(gè)追加到頁面中,對(duì)原來的元素沒有任何的影響躯概;
缺點(diǎn):每當(dāng)創(chuàng)建一個(gè)li登钥,就添加到頁面中,會(huì)引發(fā)一次DOM回流最后引發(fā)回流的次數(shù)過多娶靡,影響性能牧牢。
2.5、字符串拼接的方式實(shí)現(xiàn)數(shù)據(jù)綁定
var str = "";
for (var i = 0; i < ary.length; i++) {
var cur = ary[i];
str += '<li>';
str += '<span>' + i + '</span>';
str += cur.title;
str += '</li>'
}
oUl.innerHTML += str;
首先循環(huán)需要綁定的數(shù)據(jù)姿锭,然后把需要?jiǎng)討B(tài)綁定的標(biāo)簽以字符串的方式拼接到一起塔鳍,拼接完成最后統(tǒng)一添加到頁面中。
拼接完成的整體還是字符串呻此,最后把字符串統(tǒng)一的添加到頁面中轮纫,瀏覽器還需要把字符串渲染成最新的標(biāo)簽。
字符串拼接綁定數(shù)據(jù)趾诗,使以后工作中最常用的一種綁定數(shù)據(jù)的方式,因?yàn)樗心0逡娴臄?shù)據(jù)綁定(jade、kTemplate....)以及所有的框架(angular.js恃泪、backbone.js....)的原理都是字符串拼接郑兴,所以說你可能沒有自己直接使用字符串拼接,但是在使用引擎以及框架的過程已經(jīng)用到了贝乎。
** 優(yōu)勢(shì):** 事先把內(nèi)容拼接好情连,最后統(tǒng)一添加到頁面中,只引發(fā)一次回流览效;
缺點(diǎn): 把新拼接的字符串添加到#ul1中却舀,原有的三個(gè)li的鼠標(biāo)滑過效果都消失了(原來標(biāo)簽綁定的事件都消失了)。
2.6锤灿、文檔碎片的方式實(shí)現(xiàn)數(shù)據(jù)綁定
var frg = document.createDocumentFragment(); // 創(chuàng)建一個(gè)文檔碎片挽拔,相當(dāng)于臨時(shí)創(chuàng)建了一個(gè)容器
for (var i = 0; i < ary.length; i++) {
var cur = ary[i];
var oLi = document.createElement('li');
oLi.innerHTML = '<span>' + i + '</span>' + cur.title;
frg.appendChild(oLi);
}
oUl.appendChild(frg);
frg = null;
這種方式解決了以上的問題,但是實(shí)際開發(fā)中用的很少但校。
三螃诅、表格排序
<ul id="ul1">
<li>98</li>
<li>99</li>
<li>96</li>
<li>95</li>
<li>90</li>
</ul>
var utils = {
listToArray:function (likeAry) {
var ary = [];
try {
ary = Array.prototype.slice.call(likeAry);
} catch (e) {
for (var i = 0; i < likeAry.length; i++) {
ary[ary.length] = likeAry[i];
}
}
return ary;
}
};
var oUl = document.getElementById('ul1');
var oLis = oUl.getElementsByTagName('li');
// 1、先把元素集合類數(shù)組轉(zhuǎn)換為數(shù)組
var ary = utils.listToArray(oLis);
// 2状囱、給數(shù)組進(jìn)行排序:按照每一個(gè)li中的內(nèi)容大小進(jìn)行排序
ary.sort(function (a, b) {
return parseFloat(a.innerHTML) - parseFloat(b.innerHTML);
});
// 3术裸、按照ary中存儲(chǔ)的最新順序,依次的把對(duì)應(yīng)的li添加到頁面當(dāng)中
var frg = document.createDocumentFragment();
for (var i = 0; i < ary.length; i++) {
var obj = ary[i];
frg.appendChild(obj);
}
oUl.appendChild(frg);
frg = null;
DOM映射機(jī)制:頁面中的標(biāo)簽和JavaScript中獲取到的元素對(duì)象或者元素集合是緊緊綁定在一起的亭枷,也中的HTML結(jié)構(gòu)改變了袭艺,JS中不需要重新獲取,集合里面的內(nèi)容也會(huì)跟著自動(dòng)改變叨粘。
var oUl = document.getElementById('ul1');
var oLis = oUl.getElementsByTagName('li');
console.log(oLis.length); // 5
var oLi = document.createElement('li');
oUl.appendChild(oLi);
console.log(oLis.length); // 6猾编,沒有重新的獲取,但是oLis這個(gè)集合中的長(zhǎng)度和內(nèi)容會(huì)自動(dòng)跟著發(fā)生改變
個(gè)人公眾號(hào)(icemanFE):分享更多的前端技術(shù)和生活感悟