js中的dataset問題
昨天刷了IFE的任務,第十六個任務,任務詳情是這樣的:
任務描述
參考以下示例程式碼,使用者輸入城市名稱和空氣質量指數後,點選“確認新增”按鈕後,就會將使用者的輸入在進行驗證後,新增到下面的表格中,新增一行進行顯示
使用者輸入的城市名必須為中英文字元,空氣質量指數必須為整數
使用者輸入的城市名字和空氣質量指數需要進行前後去空格及空字元處理(trim)
使用者輸入不合規格時,需要給出提示(允許用alert,也可以自行定義提示方式)
使用者可以點選表格列中的“刪除”按鈕,刪掉那一行的資料。
<!DOCTYPE>
<html>
<head>
<meta charset="utf-8">
<title>IFE JavaScript Task 01</title>
<script src="task.js"></script>
</head>
<body>
<div>
<label>城市名稱:<input id="aqi-city-input" type="text"></label><br>
<label>空氣質量指數:<input id="aqi-value-input" type="text"></label><br>
<button id="add-btn">確認新增</button>
</div>
<table id="aqi-table">
<!--
<tr>
<td>城市</td><td>空氣質量</td><td>操作</td>
</tr>
<tr>
<td>北京</td><td>90</td><td><button>刪除</button></td>
</tr>
<tr>
<td>北京</td><td>90</td><td><button>刪除</button></td>
</tr>
-->
</table>
</body>
</html>
js程式碼:
/**
* aqiData,儲存使用者輸入的空氣指數資料
* 示例格式:
* aqiData = {
* "北京": 90,
* "上海": 40
* };
*/
var aqiData = {};
/**
* 從使用者輸入中獲取資料,向aqiData中增加一條資料
* 然後渲染aqi-list列表,增加新增的資料
*/
function addAqiData() {
}
/**
* 渲染aqi-table表格
*/
function renderAqiList() {
}
/**
* 點選add-btn時的處理邏輯
* 獲取使用者輸入,更新資料,並進行頁面呈現的更新
*/
function addBtnHandle() {
addAqiData();
renderAqiList();
}
/**
* 點選各個刪除按鈕的時候的處理邏輯
* 獲取哪個城市資料被刪,刪除資料,更新表格顯示
*/
function delBtnHandle() {
// do sth.
renderAqiList();
}
function init() {
// 在這下面給add-btn繫結一個點選事件,點選時觸發addBtnHandle函式
// 想辦法給aqi-table中的所有刪除按鈕繫結事件,觸發delBtnHandle函式
}
init();
從任務描述來看,就是用js操控html中的表格和表單實現增加和刪除的功能。沒動手寫之前自己大概過了一下思路,就是遍歷陣列的屬性,然後innerHTML重新整理頁面,不過因為要考慮到後面的刪除功能,所以在渲染表格的時候考慮用appendChild.tr和td,那麼在刪除的時候就可以用removeChild。不過覺得程式碼量會比較多,很麻煩,所以去看了一下別人組提交的程式碼,然後發現有一個隊伍用的是dataset的方法,刪除就實現的特別簡單,程式碼精簡。真的很棒,(這就是差距啊!!!!!!)服氣!然後去google了一下dataset的用法和坑。
DataSet是ADO.NET的中心概念。可以把DataSet當成記憶體中的資料庫,DataSet是不依賴於資料庫的獨立資料集合。所謂獨立,就是說,即使斷開資料鏈路,或者關閉資料庫,DataSet依然是可用的,DataSet在內部是用XML來描述資料的,由於XML是一種與平臺無關、與語言無關的資料描述語言,而且可以描述複雜關係的資料,比如父子關係的資料,所以DataSet實際上可以容納具有複雜關係的資料,而且不再依賴於資料庫鏈路。
1.html5自定義屬性及基礎
html5中我們可以使用data-字首設定我們需要的自定義屬性,來進行一些資料的存放,例如我們要在一個文字按鈕上存放相應的id:
<a href="javascript:;" data-id="2312">測試</a>
這裡的data-字首就被稱為data屬性,其可以通過指令碼進行定義,也可以應用css屬性選擇器進行樣式設定.數量不受限制,在控制和渲染資料的時候提供了非常強大的控制.
下面是元素應用data屬性的一個例子:
<div id="day-meal-expense" data-drink="tea" data-food="noodle" data-meal="lunch">$18.3</div>
要想獲取某個屬性的值,可以像下面這樣使用dataset物件:
var expenseday=document.getElementById('day-meal-expense');
var typeOfDrink=expenseday.dataset.drink;
console.log(typeOfDrink);//tea
console.log(expenseday.dataset.food);//noodle
console.log(expenseday.dataset.meal);//lunch
如果瀏覽器支援dataset,則會彈出註釋內容,如果瀏覽器不支援dataset則會報錯,無法獲取屬性drink/food/meal的值:物件為null或未定義(如IE9版本).
data屬性基本上所有的瀏覽器都是支援的,但是dataset物件支援的就比較特殊了,目前僅在Opera 11.1+,Chrome 9+下可以通過javascript,使用dataset訪問你自定義的data屬性.至於其他瀏覽器,FireFox 6+(未出)以及Safari 6+(未出)會支援dataset物件,至於IE瀏覽器,目前看來還是遙遙無期的趨勢.
需要注意的是帶邊字元連線的名稱在使用的時候需要命名駝峰化,即大小寫組合書寫,這與應用元素的style物件類似,dom.style.borderColor.例如,上面的例子中現有如下data屬性,data-meal-time,則我們要獲取相應的值可以使用:expenseday.dataset.mealTime.
2. 為何要使用dataset
如果使用傳統的方法獲取屬性值應該會類似下面:
var typeOfDrink=document.getElementById('day-meal-expense').getAttribute('data-drink');
現在,如果我們要獲得多個自定義的屬性值,就要用下面N行程式碼來實現了:
var attrs=expenseday.attributes, expense={},i,j;
for (i=0,j=attrs.length;i<j;i++){
if(attrs[i].name.substring(0,5)=='data-'){
expense[attrs[i].name.substring(5)]=attrs[i].value;
}
}
而使用dataset屬性,我們根本不需要任何迴圈去獲取你想要的那個值,直接一行秒殺:
expense=document.getElementById('day-meal-expense').dataset;
dataset並不是典型意義上的JavaScript物件,而是個DOMStringMap物件,DOMStringMap是HTML5一種新的含有多個名-值對的互動變數.
3. dataset的操作:
可以像下面這樣操作名-值對:
charInput=[];
for(var item in expenseday){
charInput.push(expenseday[item]);
}
上面這幾千程式碼的作用是讓所有的自定義屬性塞到一個數組中.
如果你想刪除一個data屬性,可以這麼做:
delete expenseday.dataset.meal;
console.log(expenseday.dataset.meal)//undefined
如果你想給元素新增一個屬性,可以這麼做:
expenseday.dataset.dessert='icecream';
console.log(expenseday.dataset.dessert);//icecream
4.跟getAttribute相比的速度
同樣是獲取屬性值,使用dataset操作data要比使用getAttribute稍微慢些.
但是,如果我們只是處理少量的data資料,這種速度上的差異造成的影響是基本上沒有的.反而,我們應該看到,使用dataset操作自適應屬性要比其他類似getAttribute的形式要少很多讓人頭疼的麻煩,並且更具有可讀性.因此,權衡來看,操作自定義屬性,dataset操作是上選.
5.什麼地方使用dataset
每次你使用自定義data屬性的時候,使用dataset去獲取名-值對就是個不錯的選擇.考慮到現在很多瀏覽器還是把dataset當作不認識的外星生物看待,所以,在實際使用的時候,有必要進行一下特徵檢測,看看是否支援dataset,類似下面的使用:
if(expenseday.dataset){
expenseday.dataset.dessert='icecream';
}else{
expenseday.setAttribute('data-dessert','icecream');
}
注意:如果你的應用程式會頻繁更新data屬性,建議使用JavaScript物件進行資料管理,而不是每次都經由data屬性進行更新.
看完了相關介紹,然後再來解決這個問題就很簡單了,在新增button的時候為其增加一個屬性data-city:’”+city+”’,
item.innerHTML += "<tr><td>" + city + "</td><td>" + aqiData[city] + "</td><td><button data-city ='"+city+"'>刪除</button></td></tr>";
之後在點選刪除按鈕的時候呼叫的函式:
function delHandle(){
delete aqiData[city];
//表格重新整理
給表格裡面的button繫結刪除事件:
document.getElementBIId("aqi-table").addEventListener("cilck,function(event){
if(event.target.nodeName.toLowerCase ==='button')
delHandle.call(null,event.target.dataset.city);
)
學習到了新技能~!