五个小例子,来自Knockout JS官方网站。
//tutorial 1 //following codes uses to demonstrate observable values and target bound ways especially method bound <!-- This is a *view* - HTML markup that defines the appearance of your UI --> <p>First name: <strong data-bind="text: firstName"></strong></p> <p>Last name: <strong data-bind="text: lastName"></strong></p> <p>First name: <input data-bind="value: firstName" /></p> <p>Last name: <input data-bind="value: lastName" /></p> <p>Full name: <strong data-bind="text: fullName"></strong></p> <button data-bind="click: capitalizeLastName">Go caps</button> // This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI function AppViewModel() { this.firstName = ko.observable("Bert"); this.lastName = ko.observable("Bertington"); this.fullName = ko.computed(function() { return this.firstName() + " " + this.lastName(); }, this); this.capitalizeLastName = function() { var currentVal = this.lastName(); // Read the current value this.lastName(currentVal.toUpperCase()); // Write back a modified value }; } // Activates knockout.js ko.applyBindings(new AppViewModel()); //tutorial 2 //this demo shows how to use observable array to bind html elements and how to define model <h2>Your seat reservations (<span data-bind="text: seats().length"></span>)</h2> <table> <thead><tr> <th>Passenger name</th><th>Meal</th><th>Surcharge</th><th></th> </tr></thead> <tbody data-bind="foreach: seats"> <tr> <td><input data-bind="value: name" /></td> <td><select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select></td> <td data-bind="text: formattedPrice"></td> <td><a href="#" data-bind="click: $root.removeSeat">Remove</a></td> </tr> </tbody> </table> <button data-bind="click: addSeat, enable: seats().length < 5">Reserve another seat</button> <h3 data-bind="visible: totalSurcharge() > 0"> Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span> </h3> // Class to represent a row in the seat reservations grid function SeatReservation(name, initialMeal) { var self = this; self.name = name; self.meal = ko.observable(initialMeal); self.formattedPrice = ko.computed(function() { var price = self.meal().price; return price ? "$" + price.toFixed(2) : "None"; }); } // Overall viewmodel for this screen, along with initial state function ReservationsViewModel() { var self = this; // Non-editable catalog data - would come from the server self.availableMeals = [ { mealName: "Standard (sandwich)", price: 0 }, { mealName: "Premium (lobster)", price: 34.95 }, { mealName: "Ultimate (whole zebra)", price: 290 } ]; // Editable data self.seats = ko.observableArray([ new SeatReservation("Steve", self.availableMeals[0]), new SeatReservation("Bert", self.availableMeals[0]) ]); // Computed data self.totalSurcharge = ko.computed(function() { var total = 0; for (var i = 0; i < self.seats().length; i++) total += self.seats()[i].meal().price; return total; }); // Operations self.addSeat = function() { self.seats.push(new SeatReservation("", self.availableMeals[0])); } self.removeSeat = function(seat) { self.seats.remove(seat) } } ko.applyBindings(new ReservationsViewModel()); //tutorial 3 //this demo shows how to use ajax to get data and update observable arrary <script src="/scripts/lib/sammy.js" type="text/javascript"></script> <!-- Folders --> <ul class="folders" data-bind="foreach: folders"> <li data-bind="text: $data, css: { selected: $data == $root.chosenFolderId() }, click: $root.goToFolder"></li> </ul> <!-- Mails grid --> <table class="mails" data-bind="with: chosenFolderData"> <thead><tr><th>From</th><th>To</th><th>Subject</th><th>Date</th></tr></thead> <tbody data-bind="foreach: mails"> <tr data-bind="click: $root.goToMail"> <td data-bind="text: from"></td> <td data-bind="text: to"></td> <td data-bind="text: subject"></td> <td data-bind="text: date"></td> </tr> </tbody> </table> <!-- Chosen mail --> <div class="viewMail" data-bind="with: chosenMailData"> <div class="mailInfo"> <h1 data-bind="text: subject"></h1> <p><label>From</label>: <span data-bind="text: from"></span></p> <p><label>To</label>: <span data-bind="text: to"></span></p> <p><label>Date</label>: <span data-bind="text: date"></span></p> </div> <p class="message" data-bind="html: messageContent" /> </div> function WebmailViewModel() { // Data var self = this; self.folders = ['Inbox', 'Archive', 'Sent', 'Spam']; self.chosenFolderId = ko.observable(); self.chosenFolderData = ko.observable(); self.chosenMailData = ko.observable(); // Behaviours self.goToFolder = function(folder) { location.hash = folder }; self.goToMail = function(mail) { location.hash = mail.folder + '/' + mail.id }; // Client-side routes Sammy(function() { this.get('#:folder', function() { self.chosenFolderId(this.params.folder); self.chosenMailData(null); $.get("/mail", { folder: this.params.folder }, self.chosenFolderData); }); this.get('#:folder/:mailId', function() { self.chosenFolderId(this.params.folder); self.chosenFolderData(null); $.get("/mail", { mailId: this.params.mailId }, self.chosenMailData); }); this.get('', function() { this.app.runRoute('get', '#Inbox') }); }).run(); }; ko.applyBindings(new WebmailViewModel()); //tutorial 4 // shows how to define custom binding target <h3 data-bind="text: question"></h3> <p>Please distribute <b data-bind="text: pointsBudget"></b> points between the following options.</p> <table> <thead><tr><th>Option</th><th>Importance</th></tr></thead> <tbody data-bind="foreach: answers"> <tr> <td data-bind="text: answerText"></td> <td data-bind="starRating: points"></td> </tr> </tbody> </table> <h3 data-bind="fadeVisible: pointsUsed() > pointsBudget">You've used too many points! Please remove some.</h3> <p>You've got <b data-bind="text: pointsBudget - pointsUsed()"></b> points left to use.</p> <button data-bind="jqButton: { enable: pointsUsed() <= pointsBudget }, click: save">Finished</button> // ---------------------------------------------------------------------------- // Reusable bindings - ideally kept in a separate file ko.bindingHandlers.fadeVisible = { init: function(element, valueAccessor) { // Start visible/invisible according to initial value var shouldDisplay = valueAccessor(); $(element).toggle(shouldDisplay); }, update: function(element, valueAccessor) { // On update, fade in/out var shouldDisplay = valueAccessor(); shouldDisplay ? $(element).fadeIn() : $(element).fadeOut(); } }; ko.bindingHandlers.jqButton = { init: function(element) { $(element).button(); // Turns the element into a jQuery UI button }, update: function(element, valueAccessor) { var currentValue = valueAccessor(); // Here we just update the "disabled" state, but you could update other properties too $(element).button("option", "disabled", currentValue.enable === false); } }; ko.bindingHandlers.starRating = { init: function(element, valueAccessor) { $(element).addClass("starRating"); for (var i = 0; i < 5; i++) $("<span>").appendTo(element); // Handle mouse events on the stars $("span", element).each(function(index) { $(this).hover( function() { $(this).prevAll().add(this).addClass("hoverChosen") }, function() { $(this).prevAll().add(this).removeClass("hoverChosen") } ).click(function() { var observable = valueAccessor(); // Get the associated observable observable(index+1); // Write the new rating to it }); }); }, update: function(element, valueAccessor) { // Give the first x stars the "chosen" class, where x <= rating var observable = valueAccessor(); $("span", element).each(function(index) { $(this).toggleClass("chosen", index < observable()); }); } }; // ---------------------------------------------------------------------------- // Page viewmodel function Answer(text) { this.answerText = text; this.points = ko.observable(1); } function SurveyViewModel(question, pointsBudget, answers) { this.question = question; this.pointsBudget = pointsBudget; this.answers = $.map(answers, function(text) { return new Answer(text) }); this.save = function() { alert('To do') }; this.pointsUsed = ko.computed(function() { var total = 0; for (var i = 0; i < this.answers.length; i++) total += this.answers[i].points(); return total; }, this); } ko.applyBindings(new SurveyViewModel("Which factors affect your technology choices?", 10, [ "Functionality, compatibility, pricing - all that boring stuff", "How often it is mentioned on Hacker News", "Number of gradients/dropshadows on project homepage", "Totally believable testimonials on project homepage" ])); //tutorial 5 //shows how to communicate with server side and how to delete items using deleted flag <h3>Tasks</h3> <form data-bind="submit: addTask"> Add task: <input data-bind="value: newTaskText" placeholder="What needs to be done?" /> <button type="submit">Add</button> </form> <ul data-bind="foreach: tasks, visible: tasks().length > 0"> <li> <input type="checkbox" data-bind="checked: isDone" /> <input data-bind="value: title, disable: isDone" /> <a href="#" data-bind="click: $parent.removeTask">Delete</a> </li> </ul> You have <b data-bind="text: incompleteTasks().length"> </b> incomplete task(s) <span data-bind="visible: incompleteTasks().length == 0"> - it's beer time!</span> <button data-bind="click: save">Save</button> function Task(data) { this.title = ko.observable(data.title); this.isDone = ko.observable(data.isDone); } function TaskListViewModel() { // Data var self = this; self.tasks = ko.observableArray([]); self.newTaskText = ko.observable(); self.incompleteTasks = ko.computed(function() { return ko.utils.arrayFilter(self.tasks(), function(task) { return !task.isDone() && !task._destroy }); }); // Operations self.addTask = function() { self.tasks.push(new Task({ title: this.newTaskText() })); self.newTaskText(""); }; self.removeTask = function(task) { self.tasks.destroy(task) }; self.save = function() { $.ajax("/tasks", { data: ko.toJSON({ tasks: self.tasks }), type: "post", contentType: "application/json", success: function(result) { alert(result) } }); }; // Load initial state from server, convert it to Task instances, then populate self.tasks $.getJSON("/tasks", function(allData) { var mappedTasks = $.map(allData, function(item) { return new Task(item) }); self.tasks(mappedTasks); }); } ko.applyBindings(new TaskListViewModel());