MVVM frame in the angular is good, but so all-inclusive framework, learning difficulty is not low, to start at least have a two-week bar. and Knockoutjs focus on data binding, only a day or two can be put into use, learning costs not too low! At a time when the front-end has evolved so rapidly, learning costs are a factor to be considered. Many times in fact, our project is not so complex, and do not need a universal framework, more need the opposite is simple and convenient tools.
Before Knockoutjs
Suppose we make an order system, we need to display the price of the commodity, and then we can calculate the total price according to the number of input and show it. The use of native code is also easy to achieve, the effect:
The code is as follows:
<!--HTML code--> price
: <span id= ' price ' ></span><br/> Account
: <input type= ' text "id=" account "value=" "placeholder=" Please enter quantity/><br/>
sum: <span id= "sum" ></span>
//js Code
var pricenode = document.getElementById (' price '),
accountnode = document.getElementById (' account '),
Sumnode = document.getElementById (' Sum '), price
= m, account = one
,
sum = Price * account;
Class
pricenode.innertext = Price;
Accountnode.value = account;
sumnode.textcontent = sum;
Monitor the user input
accountnode.addeventlistener (' KeyDown ') of the View layer, function (e) {
window.settimeout (function () { Account
= Accountnode.value;
sum = Price * account;
sumnode.textcontent = sum;
},10);
Well, it's pretty simple! Oh, yes, we once showed 50 items, at the same time there are 10 types of such display, as well as buy 5 boxes Okamoto send a fried dough sticks such a variety of promotions ...
So, you know the problem with the native implementation:
• With the increase in UI and data interaction, the amount of code grows rapidly and is difficult to maintain
• The naming of ID or class is difficult to manage based on DOM queries
• High code coupling, difficult to reuse
Knockoutjs Introduction
Knockoutjs (KO) is to solve the above problems appear, he is a lightweight MVVM library, focusing on the implementation of data and view binding, does not provide UI classes and routing functions, very quickly. At the same time, because Ko has been out for some years, is already a more mature framework. In doing some dynamic display more pages, Ko is undoubtedly a better choice. About MVVM landlord will not say more, a picture to cover:
Ko is based on 3 core features (official website introduction):
1. Observable objects and dependency tracking (observables and dependency tracking): The use of observable objects to establish an implicit chain of relationships between model data for data conversion and binding.
2. Declarative binding (declarative bindings): Easily bind model data to DOM elements with simple, readable syntax.
3. Template (Templating): built-in template engine, quickly write complex UI presentation for your model data.
Use Ko is very simple, directly to the official website (http://knockoutjs.com/index.html) Download and the introduction can be <script>.
Observable objects
Use Ko to rewrite the above example (custom price, which is also one of my childhood wishes):
The code is like this:
<!--HTML code-->
<div id= "One" > Price
: <input type= "text" data-bind= "Value:price" placeholder = "Please input unit price"/><br/> Account
: <input type= "text" data-bind= "Value:account" placeholder= "Please enter Number"/>< br/>
sum: <span data-bind= "Text:sum" ></span>
</div>
//JS Code
var ViewModel = function (P, a) {
//set to observable object and initialize
This.price = ko.observable (p) with parameter p, A;
This.account = Ko.observable (a);
When calling the KO function, this is passed in, otherwise when the ko.purecomputed internal code is executed, this is the Ko,ko.price () error.
this.sum = ko.purecomputed (function () {
//Because the observable object is a function object, use price () to read the current value.
//Set Value use Price (NewValue) to support chained writing: This.price. Account (3) return
this.price () * This.account ();
}, this);
};
var vm = new ViewModel (135);
Apply the binding, the binding starts to take effect
1 First look at the HTML code:
You can see a key-value pair with a data-bind = "Xx:oo" added to each tag. This is KO's binding syntax, what does Xxoo represent? (Xxoo?) Landlord is still a child ah ... From the example can see XX as the label attribute, can be text, value, class, checked and other tag properties, in fact, can also be click, focus, load and other DOM events. OO looks like a variable, actually not a variable, but a function object, and executing the function (with a ()) can get the appropriate binding value. By Xxoo, you can bind the attributes or events of an element to a function object in JS (Xxoo is responsible for each other), which is the declarative binding of KO. The definition of a binding is actually an observer pattern, except that it is a two-way binding in which the Publisher and subscriber subscribe to each other's messages, which is MVVM's two-way binding. The result of Ko two-way binding is that one side of the change can automatically update the other side, that is, through the ViewModel data and performance layer tightly bound together. The binding effect is similar to the following:
2) and look at the JS code:
You can see that a ViewModel object is defined in JS that operates on OO that is bound to HTML in the object. There are two main operations here: Ko.observable () and ko.purecomputed ().
ko.observable (P): see the name of the meaning, this is the method of setting observable objects, the incoming parameter p is the initialization of the value, where the parameter can be a basic data type, can also be a JSON object. Being set to observable objects means that the system will observe this value all the time. Whether the p in the ViewModel or the P of the bound object changes will cause the Refresh event to be updated to the latest status of all the places used for this value. Obviously, observable objects are more performance-consuming, so don't set them as observable objects for values that do not require dynamic changes, such as prices, or you need to put them in a viewmodel for centralized initialization.
• Note: ko.observable (p) Returns an observable object that is a function object, so reading observable objects requires the use of price (); Similarly, setting observable objects requires the way of price (NewValue). The more intimate is that when setting support chain style: Viewmodel.price. Account (10).
ko.purecomputed () is the so-called dependency tracking, here is the unit price * Quantity equals the total price, note that this can not be directly used This.sum = This.price () * This.account (); To specify SUM, This type of writing does not dynamically refresh the bound object, but dynamically changes the sum variable, but it requires additional actions to refresh the bound object. Therefore, the binding value associated with the calculation is set with the KO calculation function. Of course, the return is also a function object. In addition, KO has a computed function that can be used to set up, but it is recommended to use the pure method to improve performance.
• Note the wording here: ko.purecomputed (FN, this), that is, the FN binding to the ViewModel scope, is in fact JS in the call/apply. Because this is Ko object when performing the KO internal function, this is required to be passed through the above method in order to get the scope of the ViewModel object. Of course, you can also save ViewModel objects outside of the KO function, and then use that to invoke the ViewModel object inside the KO function. Like this:
var that = this;
This.sum = ko.purecomputed (function () {return
that.price () * That.account ();
Once you have defined the ViewModel constructor, you instantiate a ViewModel object and then use Ko.applybindings () to make the binding take effect, and don't omit this step.
Use KO's page simple mode:
<!--HTML code-->
<span data-bind= "Text:bindtext" ></span>
//JS Code
var viewModel = {
bindtext:ko.observable (' InitValue ')
};
Summed up is: HTML in the use of data-bind= "Xx:oo" declaration binding, JS set up ViewModel and set observable objects, the last application binding.
An observable array of objects
Then look at the use of the object array can be observed, in KO can not be like JS array and variable mix, for the array object to use Ko.observablearray ([...,...]) This form, in the same way, the array element can be either a basic type or a JSON object. An array of observable objects in Ko has a series of array manipulation methods, such as slice (), sort (), push (), the effect is the same as the original JS array operation method, only the changes through the Ko method will notify subscribers to refresh the interface, but the JS method will not refresh the interface. Here is a simple example:
<!--HTML code-->
<select data-bind= "options:list" ></select>
//JS Code
var vm = {
//List:ko.observableArray ()
list:ko.observableArray ([' Luffy ', ' Zoro ', ' Sanji '])
};
Key point: KO monitors the state of the array, not the state of the element itself. In other words, when the array state changes (add and subtract elements) will trigger the KO event caused the binding object to refresh, but the internal elements of the array changes (such as: value changes) is not monitored can not trigger KO event. For example:
Using native methods in the console to change the Luffy dynamically to Lucy will not refresh the UI page, and the array operation using KO to change the array will immediately refresh the page, it is noteworthy that in the refresh, the previous changes will be refreshed (Luffy > Lucy). That is to say, in fact, the variables in JS memory have been changed, but there is still a lack of a refreshing dom action. As you can see here, the way to read the array is vm.list () [0], because the list is also a function object, and performing the return value is the list content we want. Similarly, the array of observable objects can be reset in the same way as vm.list (["Sister", "sister", "sister"]), and the UI can be refreshed immediately.
If changes to the array elements need to be dynamically reflected on the UI, you need to set the array elements as observable, and then use the KO method to change the array element values. Note that the method of using KO is list () [0] ("Lucy")!
There are two types of methods for manipulating observable object arrays: Pop, push, shift, unshift, reverse, sort, splice, which is the same as the usage and effect of JS native method, and no longer repeat.
Some other methods are not in JS, mainly in the following several:
Remove (Someitem)--Deletes all element items that are equal to Someitem and returns them as an array, meaning that you cannot directly list.remove (0) to delete the first item, but rather to use List.remove (list () [0 ] This form is to be deleted. In summary, the incoming parameter must be the value of the element item, either in the form of list () [0] or as a string of values (such as "Luffy").
Remove (function (item) {return Item.age < 18;})--Deletes all element items with the Age property less than 18 and returns them as an array, a usage that is no different from the usual array high-order functions. The item is passed in as a parameter of a high-order function, and when you traverse the array, the higher-order function returns the value with the truth and the item is deleted, otherwise it goes to the next item.
RemoveAll ([' Chad ', 132, undefined])--Deletes all elements that are equal to ' Chad ' or 123 or undefined and returns them as an array.
RemoveAll ()--Deletes all items and returns as an array.
Tip: When dealing with observable objects, if the number of objects and the interaction is frequent, each change will immediately refresh the performance is very consuming, this time you can use the extension myobservablearray.extend ({ratelimit:1000}) to set the delay refresh. For example, when inserting an element into an array of observable objects, you can set a cycle time of 1000ms, allowing all operations within 1000ms to be concentrated in a single refresh, avoiding the performance degradation caused by frequent manipulation of the DOM.
Summarize
This article briefly introduces the most important concepts in Knockoutjs: Observable objects (arrays). An observable object is essentially a function object, which is recommended by dynamically refreshing the UI presentation when an object can be observed through the KO method. At the same time, you can also use the native JS method to manipulate observable objects, but the native method does not refresh the UI display, it needs to wait until the next refresh event will be flushed to the UI.