新聞中心
1 Contacts editor
這個(gè)例子和微軟為演示jQuery Data Linking Proposal例子提供的例子一樣的提供的,我們可以看看Knockout實(shí)現(xiàn)是難了還是容易了。

代碼量的多少不重要(盡快Knockout 的實(shí)現(xiàn)很簡潔),重要的看起來是否容易理解且可讀。查看HTML源代碼,看看如何實(shí)現(xiàn)的view model以及綁定的。
代碼: View
Contacts
代碼: View model
var viewModel = {
contacts: new ko.observableArray([
{ firstName: "Danny", lastName: "LaRusso", phones: [
{ type: "Mobile", number: "(555) 121-2121" },
{ type: "Home", number: "(555) 123-4567"}]
},
{ firstName: "Sensei", lastName: "Miyagi", phones: [
{ type: "Mobile", number: "(555) 444-2222" },
{ type: "Home", number: "(555) 999-1212"}]
}
]),
addContact: function () {
viewModel.contacts.push({ firstName: "", lastName: "", phones: [] });
},
removeContact: function (contact) {
viewModel.contacts.remove(contact);
},
addPhone: function (contact) {
contact.phones.push({ type: "", number: "" });
viewModel.contacts.valueHasMutated();
},
removePhone: function (contact, phone) {
ko.utils.arrayRemoveItem(contact.phones, phone);
viewModel.contacts.valueHasMutated();
},
save: function () {
viewModel.lastSavedJson(JSON.stringify(viewModel.contacts(), null, 2));
},
lastSavedJson: new ko.observable("")
};
ko.applyBindings(viewModel);2 Editable grid
該例是使用“foreach”綁定為數(shù)組里的每一項(xiàng)來render到 template上。好處(相對于模板內(nèi)部使用for循環(huán))是當(dāng)你添加或者刪除item項(xiàng)的時(shí)候,Knockout不需要重新render – 只需要render新的item項(xiàng)。就是說UI上其它控件的狀態(tài)(比如驗(yàn)證狀態(tài))不會丟失。
如何一步一步構(gòu)建這個(gè)例子并集成ASP.NET MVC,請參閱此貼。
代碼: View
代碼: View model
var viewModel = {
gifts: ko.observableArray([
{ name: "Tall Hat", price: "39.95" },
{ name: "Long Cloak", price: "120.00" }
]),
addGift: function () {
this.gifts.push({ name: "", price: "" });
},
removeGift: function (gift) {
this.gifts.remove(gift);
},
save: function (form) {
alert("Could now transmit to server: " + ko.utils.stringifyJson(this.gifts));
// To transmit to server, write this: ko.utils.postJson($("form")[0], this.gifts);
}
};
ko.applyBindings(viewModel);
$("form").validate({ submitHandler: function () { viewModel.save() } });3 Shopping cart screen
這個(gè)例子展示的是依賴監(jiān)控屬性(dependent observable)怎么樣鏈在一起。每個(gè)cart對象都有一個(gè)dependentObservable對象去計(jì)算自己的subtotal,這些又被一個(gè)進(jìn)一步的dependentObservable對象依賴計(jì)算總的價(jià)格。當(dāng)改變數(shù)據(jù)的時(shí)候,整個(gè)鏈上的依賴監(jiān)控屬性都會改變,所有相關(guān)的UI元素也會被更新。
這個(gè)例子也展示了如何創(chuàng)建聯(lián)動的下拉菜單。
代碼: View
Category
Product
Price
Quantity
Subtotal
Total value:
代碼: View model
function formatCurrency(value) { return "$" + value.toFixed(2); }
var cartLine = function () {
this.category = ko.observable();
this.product = ko.observable();
this.quantity = ko.observable(1);
this.subtotal = ko.dependentObservable(function () {
return this.product() ? this.product().price * parseInt("0" + this.quantity(), 10) : 0;
} .bind(this));
// Whenever the category changes, reset the product selection
this.category.subscribe(function () { this.product(undefined); } .bind(this));
};
var cart = function () {
// Stores an array of lines, and from these, can work out the grandTotal
this.lines = ko.observableArray([new cartLine()]); // Put one line in by default
this.grandTotal = ko.dependentObservable(function () {
var total = 0;
for (var i = 0; i < this.lines().length; i++)
total += this.lines()[i].subtotal();
return total;
} .bind(this));
// Operations
this.addLine = function () { this.lines.push(new cartLine()) };
this.removeLine = function (line) { this.lines.remove(line) };
this.save = function () {
var dataToSave = $.map(this.lines(), function (line) {
return line.product() ? { productName: line.product().name, quantity: line.quantity()} : undefined
});
alert("Could now send this to server: " + JSON.stringify(dataToSave));
};
};
var cartViewModel = new cart();
ko.applyBindings(cartViewModel, document.getElementById("cartEditor"));4 Twitter client
這是一個(gè)復(fù)雜的例子,展示了幾乎所有Knockout特性來構(gòu)建一個(gè)富客戶端。
用戶數(shù)據(jù)存在一個(gè)JavaScript模型里,通過模板來展示。就是說我們可以通過清理用戶列表里的數(shù)據(jù)來達(dá)到隱藏用戶信息的目的,而不需要手動去隱藏DOM元素。
按鈕將根據(jù)他們是否可操作來自動變成enabled或disabled狀態(tài)。例如,有一個(gè)叫hasUnsavedChanges的依賴監(jiān)控屬性(dependentObservable)控制這“Save”按鈕的enabled狀態(tài)。
可以非常方便地從外部JSON服務(wù)獲取數(shù)據(jù),并集成到view model里,然后顯示在頁面上。
代碼: View
Loading...
Currently viewing
user(s):
代碼: View model
// The view model holds all the state we're working with. It also has methods that can edit it, and it uses
// dependentObservables to compute more state in terms of the underlying data
// --
// The view (i.e., the HTML UI) binds to this using data-bind attributes, so it always stays up-to-date with
// the view model, even though the view model does not know or care about any view that binds to it
var viewModel = {
savedLists: ko.observableArray([
{ name: "Celebrities", userNames: ['JohnCleese', 'MCHammer', 'StephenFry', 'algore', 'StevenSanderson'] },
{ name: "Microsoft people", userNames: ['BillGates', 'shanselman', 'haacked', 'ScottGu'] },
{ name: "Tech pundits", userNames: ['Scobleizer', 'LeoLaporte', 'techcrunch', 'BoingBoing', 'timoreilly', 'codinghorror'] }
]),
editingList: {
name: ko.observable("Tech pundits"),
userNames: ko.observableArray()
},
userNameToAdd: ko.observable(""),
currentTweets: ko.observableArray([])
};
viewModel.findSavedList = function (name) {
var lists = this.savedLists();
for (var i = 0; i < lists.length; i++)
if (lists[i].name === name)
return lists[i];
};
// Methods
viewModel.addUser = function () {
if (this.userNameToAdd() && this.userNameToAddIsValid()) {
this.editingList.userNames.push(this.userNameToAdd());
this.userNameToAdd("");
}
}
viewModel.saveChanges = function () {
var saveAs = prompt("Save as", this.editingList.name());
if (saveAs) {
var dataToSave = this.editingList.userNames().slice(0);
var existingSavedList = this.findSavedList(saveAs);
if (existingSavedList)
existingSavedList.userNames = dataToSave; // Overwrite existing list
else
this.savedLists.push({ name: saveAs, userNames: dataToSave }); // Add new list
this.editingList.name(saveAs);
}
}
viewModel.deleteList = function () {
var nameToDelete = this.editingList.name();
var savedListsExceptOneToDelete = $.grep(this.savedLists(), function (list) { return list.name != nameToDelete });
this.editingList.name(savedListsExceptOneToDelete.length == 0 ? null : savedListsExceptOneToDelete[0].name);
this.savedLists(savedListsExceptOneToDelete);
};
ko.dependentObservable(function () {
// Observe viewModel.editingList.name(), so when it changes (i.e., user selects a different list) we know to copy the saved list into the editing list
var savedList = viewModel.findSavedList(viewModel.editingList.name());
if (savedList) {
var userNamesCopy = savedList.userNames.slice(0);
viewModel.editingList.userNames(userNamesCopy);
} else
viewModel.editingList.userNames([]);
});
viewModel.hasUnsavedChanges = ko.dependentObservable(function () {
if (!this.editingList.name())
return this.editingList.userNames().length > 0;
var savedData = this.findSavedList(this.editingList.name()).userNames;
var editingData = this.editingList.userNames();
return savedData.join("|") != editingData.join("|");
}, viewModel);
viewModel.userNameToAddIsValid = ko.dependentObservable(function () {
return (this.userNameToAdd() == "") || (this.userNameToAdd().match(/^\s*[a-zA-Z0-9_]{1,15}\s*$/) != null);
}, viewModel);
// The active user tweets are (asynchronously) computed from editingList.userNames
ko.dependentObservable(function () {
twitterApi.getTweetsForUsers(this.editingList.userNames(), function (data) { viewModel.currentTweets(data) })
}, viewModel);
ko.applyBindings(viewModel);
// Using jQuery for Ajax loading indicator - nothing to do with Knockout
$(".loadingIndicator").ajaxStart(function () { $(this).fadeIn(); })
.ajaxComplete(function () { $(this).fadeOut(); }); 新聞標(biāo)題:創(chuàng)新互聯(lián)Knockout教程:第九章:高級應(yīng)用舉例
文章地址:http://m.5511xx.com/article/dhsosjs.html


咨詢
建站咨詢
