1. Introduction
This series of articles has introduced Bootstrap. For details, please check this article: "Bootstrap Introduction Tutorial". Since in recent projects, the front-end is made by Asp.net MVC + KnockoutJs + Bootstrap. So I started writing this series again. Today, let’s take a look at the MVVM framework of the web front-end - KnockoutJs.
2. What is KnockoutJs?
Anyone who is engaged in .NET development should know that the MVVM framework is integrated in WPF, so KnockoutJs is also an MVVM framework for web development. To put it simply, the benefits of MVVM are separated from the page display code, so that front-end projects can be better maintained.
Before, when we wrote web pages, JS code and Html code were mixed together, and the code was filled with a large number of DOM objects. This code structure is very confusing. With the MVVM framework, you can split the JS code and Html code, and the data operation part is simpler. You only need to bind to the corresponding tag attributes to display through the corresponding syntax (data-bind), thereby speeding up development speed.
KnockoutJs is such an MVVM framework. In fact, instead of calling its framework, it should be a MVVM class library. Because it does not have the MVVM framework, it is a relatively "heavy" concept, which should include features such as routing. However, there is no KnockoutJS. In comparison, AngularJS should be called an MVVM framework more appropriate.
The main functions implemented by KnockoutJS are as follows:
Declarative Bindings: Use simple syntax to associate model data to DOM elements. That is, the "data-bind" syntax
Dependency Tracking: Establish relationships between model data for transformation and joint data. For example, the total price of a product is the sum of the prices of each product item. At this time, the total price of the product and the product items can be used to establish a relationship using the dependency tracking function. That is, it is derived from the sum of the total prices of each commodity item. This relationship is done by the computed function in KnockoutJs.
Automatic UI Refresh: When your model state changes, the UI interface will be automatically updated. This is done by the observable function.
Templating: Quickly write complex nestable UIs for your model data. Similar to the concept of templates in WPF.
Next, we use specific examples to quickly grasp the use of KnockoutJs.
3. Declarative binding
Let's see how to use the data-bind syntax in KnockoutJS to bind model data to DOM elements.
1. One-way binding
<!DOCTYPE html><html><head> <meta name="viewport" content="width=device-width" /> <title>Demo1-one-way binding</title> <script type="text/javascript" src="/uploads/rs/376/pbcx3e1z/knockout-3.4.0.js"></script></head> <body> <!--one-way binding--> <div> <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> </div> <!--This script should be placed in the corresponding JS file in the actual project, and then referenced in the html through the Script tag--> <!--JS code is the business logic part, which separates the business logic from the Html code, making the View code more concise, so that it is easy to maintain in the later stage--> <script type="text/javascript"> function ViewModel() { this.firstName = "Tommy"; this.lastName = "Li"; } ko.applyBindings(new ViewModel()); </script> </body></html>2. The above example only completes the one-way binding operation. That is, in the example above you will find that when changing the value in the input tag and leaving the focus, the above value will not be updated. In fact, the automatic update function in KnockoutJS will not be automatically added, and the corresponding function needs to be supported. This function is the observable function. Let’s take a look at the example of two-way binding:
<!DOCTYPE html><html><head> <meta name="viewport" content="width=device-width" /> <title>Demo2-Bi-directional binding</title> <script type="text/javascript" src="/uploads/rs/376/pbcx3e1z/knockout-3.4.0.js"></script></head><body> <!--Bi-directional binding--> <div> <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> </div> <script type="text/javascript"> function ViewModel() { this.firstName = ko.observable("Tommy"); this.lastName = ko.observable("Li"); } ko.applyBindings(new ViewModel()); </script></body></html>4. Reliance on tracking
Next, let's see how to use the computed function in KO to complete dependency tracking. The implementation code of the specific example is as follows:
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Demo3-Dependency Tracking</title> <script type="text/javascript" src="/uploads/rs/376/pbcx3e1z/knockout-3.4.0.js"></script></head><body> <!--Bidirectional binding--> <div> <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">LastName To Upper</button> </div> <script type="text/javascript"> function ViewModel() { this.firstName = ko.observable("Tommy"); this.lastName = ko.observable("Li"); // Depend on tracking this.fullName = ko.computed(function () { return this.firstName() + " " + this.lastName(); },this); // Change the value of observable through code this.capitalizeLastName = function() { this.lastName(this.lastName().toUpperCase()); }; } ko.applyBindings(new ViewModel()); </script></body></html>Next, let's take a look at an example of using declarative binding and dependency to track complex points. The specific example code is as follows:
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Demo4-list binding</title> <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/376/pbcx3e1z/knockout-3.4.0.js"></script></head><body> <table> <thead> <tr> <td>Name</td> <td>Amount</td> <td>Price</td> </tr> </thead> <tbody data-bind="foreach: items"> <tr> <td data-bind="text: product.name"></td> <td><select data-bind="options:[1,2,3,4,5,6],value: amount"></select></td> <td data-bind="text: subTotal"></td> <td><a href="#" data-bind="click: $root.remove">Remove</a></td> </tbor> </table> <h3>Order Price: <span data-bind="text: price"></span></h3> <button data-bind="click: addComputer">Add a Computer</button> <script type="text/javascript"> var products = [{ name: "Learnighard Study Notes", price: 49 }, { name: "Xiaomi Note", price: 999 }, { name: "Macro notebook", price: 4999 }]; // Order class function Order() { var self = this; this.items = ko.observableArray([ new Item(products[0], 1), new Item(products[1],2) ]); // Total order price this.price = ko.computed(function() { var p = 0; for (var i = 0; i < self.items().length; i++) { var item = self.items()[i]; p += item.product.price * item.amount(); } return p; }, self); this.remove = function(item) { self.items.remove(item); }; this.addComputer = function () { self.items.push(new Item(products[2], 1)); }; } // Line item class function Item(product, amount) { var self = this; this.product = product; this.amount = ko.observable(amount); // Total line item price this.subTotal = ko.computed(function() { return self.amount() * self.product.price; }, self); } ko.applyBindings(new Order()); </script></body></html>V. Template
After reading the above examples, you should actually feel that it is very easy to get started with KO (the abbreviation of KnockoutJS). Because its syntax is very easy to understand, let’s take a look at the use of templates in KO.
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Demo5-Template binding</title> <script type="text/javascript" src="/uploads/rs/376/pbcx3e1z/knockout-3.4.0.js"></script></head> <body> <!--Template binding, the content of the div is the tag in the personTemplate template--> <!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- <p>Name: <strong data-bind="text: name"></strong></p> <p>Age: <strong data-bind="text: age"></strong></p> </div>--> <div data-bind="template:'personTemplate'"></div> <script id="personTemplate" type="text/html"> <p>Name: <strong data-bind="text: name"></strong></p> <p>Age: <strong data-bind="text: age"></strong></p> </script> <script type="text/javascript"> var ViewModel = { name: ko.observable('Tommy'), age: ko.observable(28), makeOlder: function() { this.age(this.age() + 1); } }; ko.applyBindings(ViewModel); </script> </body></html> <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Demo6-Template Binding</title> <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/376/pbcx3e1z/knockout-3.4.0.js"></script></head> <body> <h2>Participants</h2> Here are the participants: <div data-bind="template: { name: 'persontemplate', foreach: people }"></div> <script type="text/html" id="persontemplate"> <h3 data-bind="text: name"></h3> <p>Age: <span data-bind="text: age"></span></p> </script> <script type="text/javascript"> function MyViewModel() { this.people = [ { name: 'Tommy', age: 27 }, { name: 'Frank', age: 33 } ]; } ko.applyBindings(new MyViewModel()); </script> </body></html>For more information about using templates, please refer to the official documentation: http://knockoutjs.com/documentation/template-binding.html. This article only lists the use of templates in 2.
6. Summary
At this point, the content of KnockoutJs' quick start is over. We will continue to introduce KO content to you in the next article. The content of the next article will introduce how to use KO to make an actual project. Don't miss it.