2012年8月15日 星期三

knockoutjs 9 observableArray的操作

Manipulating an observableArray


你可以使用javascript原生array的操作函式,但是KO除了有功用相同的函式外還提供了更有用的功能,因為:


  • 兼容主流瀏覽器  -
    例如
    indexOf不能在IE8和早期版本上使用,但KO自己的indexOf 可以在所有瀏覽器上使用。
  • 綁定UI自動更新  -
    在Array操作函數方面(例如push和splice),KO自己的方式可以自動觸發依賴跟踪,並且通知所有的訂閱者它的變化,然後讓UI界面也相應的自動更新。
  • 語法更方便  -
      調用KO的push方法,只需要這樣寫:

    myObservableArray.push(...)。    //這是KO的操作函式比,原生方法直覺多了。                                  myObservableArray().push(...)  //這是Javascript原生操作函式。
範例:

<!DOCTYPE html>
<html>
<head>
<title>observable array</title>
<meta charset="UTF-8"/>

<script src="../lib/knockout-2.1.0.js"></script>

<style>
body ,div ,ul{
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
}
.blockDiv{
width: 100%;
background-color: #DFF4E4;
padding: 5px 5px 5px 5px;
height: 300px;
}
ul{
width:100%;
list-style: none;
font-size: 10px;
}
li{
float:left;
width: 25px;
height: 25px;
}
</style>
</head>
<body>
<div class="blockDiv" data-bind="foreach:colors">
<ul>
<li data-bind="text:name"></li><li data-bind="style: {backgroundColor: value }" ></li>
</ul>
</div>
<div>
color<input id="nameInput" type="text"/>輸入色彩名稱</br>
value<input id="valueInput" type="text" />輸入RGB如00ff00</br>
<input id="addBtn" type="button" value="add Color"/>
<input id="removeBtn" type="button" value="remove Color"/>
<input id="removeAllBtn" type="button" value="remove All Color"/>
<input id="reverseBtn" type="button" value="reverse Color"/>
<input id="shiftBtn" type="button" value="移除陣列第一個項目"/>
<input id="unShiftBtn" type="button" value="加入一個項目到陣列開端"/>
</br>
</div>
<script>
(function (window, undefined) {
var $ = window.$,
ko = window.ko,
viewModels = window.viewModels || {};
viewModels.colorViewModel={
colors:ko.observableArray([
{name:'紅',value:'#FF0000'},
{name:'橙',value:'#FFA500'},
{name:'黃',value:'#EEEE00'},
{name:'綠',value:'#C0FF3E'},
{name:'藍',value:'#87CEFF'},
{name:'紫',value:'#8470FF'},
{name:'洋紅',value:'#E066FF'}
])
};

//
var colorVM = viewModels.colorViewModel; 
//加入項目按鈕參照
var addItemButton = document.getElementById('addBtn');

//移除最後一個項目按鈕參照
var removeButton = document.getElementById('removeBtn');

//移除全部按鈕的參照
var removeAllBtn = document.getElementById('removeAllBtn');

//反轉陣列按鈕參照
var reverseBtn = document.getElementById('reverseBtn');

//移除陣列第一個元素按鈕參照
var shiftBtn = document.getElementById('shiftBtn');

//插入元素到陣列最前端按鈕參照
var unShiftBtn = document.getElementById('unShiftBtn');

//輸入名稱input參照
var nameInput = document.getElementById('nameInput');
//輸入值input參照
var valueInput = document.getElementById('valueInput');
//初始化
var init = function(){
//加入按鈕被按下
addItemButton.onclick = function(){
if(nameInput.value && valueInput.value){
colorVM.colors.push( {name:nameInput.value,value: '#' + valueInput.value} );
};
};
//移除項目按鈕被按下
removeButton.onclick = function(){
//移除最後一個項目
colorVM.colors.pop();
};
//清空陣列
removeAllBtn.onclick = function(){
colorVM.colors.removeAll();
};
//反轉陣列
reverseBtn.onclick = function(){
colorVM.colors.reverse();
};
//移除陣列第一個元素
shiftBtn.onclick = function(){
colorVM.colors.shift();
};
//插入元素到陣列最前面
unShiftBtn.onclick = function(){
if(nameInput.value && valueInput.value){
colorVM.colors.unshift( {name:nameInput.value,value:'#' + valueInput.value} );
};
};
//啟動綁定
ko.applyBindings(viewModels.colorViewModel);
};
init();
})(window);
</script>
</body>
</html>



  • observableArray.push('Some new value')-
      加入一個元素到陣列最後端。
  • observableArray.pop()-
      移除陣列最後端的元素。
  • observableArray .unshift('Some new value') -
      插入一個元素到陣列最前端。
  • observableArray .shift()-
      移除陣列最前端的元素。
  • observableArray .reverse()-
      反轉陣列元素順序。
  • observableArray .sort()-
      排序陣列內容
更多的操作方式請參考官方文件說明

knockoutjs 8 observableArray

knockoutjs observableArray
  • observableArray是對於Array裡的項目做觀察,而非對其項目裡的屬性作觀察。
  • 他類似Flex的collectionChange,只對Array裡的項目數量變動時作用。
  • 若是你想對屬性觀察,就必須對Array內的屬性下observable。
測試範例:
<!DOCTYPE html>
<html>
<head>
<title>observable array</title>
<meta charset="UTF-8"/>
<script src="../lib/knockout-2.1.0.js"></script>
<style>
.mySpan{
display: block;
float:left;
width: 80px;
}
</style>
</head>
<body>
<div data-bind="foreach:fish" id="fishElement">
    <span data-bind="text:name" class="mySpan"></span>NT <span data-bind="text:price"></span>
    </br>
</div>
<div>
    name<input id="nameInput" type="text"/>
    </br>
    price<input id="priceInput" type="text"/>
    </br>
    <input id="addBtn" type="button" value="add"/>
    <input id="removeBtn" type="button" value="remove"/>
    </br></br></br>
    要改變的名子:<input id="newName" type="text"/></br>
    第一個項目目前name屬性值:<input id="firstItemNowName" type="text" disabled="true"/></br>
    <input id="changedProperty" type="button" value="測試改變第一個項目的name屬性"/>
</div>
<script>
(function (window, undefined) {
var $ = window.$,
ko = window.ko,
viewModels = window.viewModels || {};

viewModels.fishViewModel={
fish:ko.observableArray([
{name:'七星鱸魚',price:250},
{name:"密點石斑",price:400},
{name:"鱈魚",price:400},
{name:"黑鮪魚",price:1000},
{name:"香魚",price:50}
])
};
//加入項目按鈕參照
var addItemButton = document.getElementById('addBtn');
//移除項目按鈕參照
var removeButton = document.getElementById('removeBtn');
//更改屬性按鈕參照
var changedPropertyButton = document.getElementById('changedProperty');

var firstItemNowNameTextInput = document.getElementById('firstItemNowName');
var newNameTextInput = document.getElementById('newName');


var init = function(){
  //加入按鈕被按下
  addItemButton.onclick = function(){
var name = document.getElementById('nameInput').value;
var price = document.getElementById('priceInput').value;
if(name && price){
                          //利用knockoutjs提供的陣列操作函式加入一個fish item
                          viewModels.fishViewModel.fish.push({name:name,price:price});
                        };
                            };
  
  //移除項目按鈕被按下
   removeButton.onclick = function(){
       //移除最後一個項目
                  viewModels.fishViewModel.fish.pop();
  };

//啟動綁定
ko.applyBindings(viewModels.fishViewModel, document.getElementById('fishElement'));

//取回第一次的值呈現
firstItemNowNameTextInput.value = viewModels.fishViewModel.fish()[0].name;

//改變第一個項目的name屬性
changedPropertyButton.onclick = function(){
    var newName = newNameTextInput.value;
    if(newName && viewModels.fishViewModel.fish() &&
                            viewModels.fishViewModel.fish().length > 0){
firstItem = viewModels.fishViewModel.fish()[0];
firstItem.name = newName;
firstItemNowNameTextInput.value =
                                        viewModels.fishViewModel.fish()[0].name;
//window.alert(firstItem.name);
}
};
};
init();
})(window);
</script>
</body>
</html>

note:observableArray只對array內的項目數量變動作觀察,對於其內屬性若需要需對屬性個別加上observable。