In the previous Knockoutjs learning series (I) ko's first experience article, it was mentioned that the data-bind = "XX:OO" binding method in ko can not only bind text, value, etc., but also bind visible, style and other appearance attributes, click, textInput and other events, and even control program flow. Various fancy bundles will definitely satisfy your fantasy.
The following briefly talks about the use of various bindings, which are mainly divided into three types: representation, process and interaction according to the bound properties.
Performance attributes
The binding attributes of the presentation class include visible, text, html, css, style, and attr. Except for the class that css represents css, everything else is easy to understand. Of course, the naming in style should be consistent with js, and it should be removed - changed to camel naming, as shown below:
<!--HTML code--><div data-bind="visible: shouldShowMessage">You will see this message only when "shouldShowMessage" holds a true value.</div><div>Today's message is: <span data-bind="text: myMessage"></span></div><div data-bind="html: details"></div><div data-bind="css: { profitWarning: currentProfit() < 0 }">CSS class binding test</div><div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }">CSS style binding test</div><a data-bind="attr: { href: url, title: urltitle }">Report</a> // js codevar viewModel = { shouldShowMessage: ko.observable(true), // Message initially visiblemyMessage: ko.observable(), // Initially blankdetails: ko.observable(), // Initially blankcurrentProfit: ko.observable(150000), // Positive value, so initially we don't apply the "profitWarning" classcurrentProfit: ko.observable(150000), // Positive value, so initially blackurl: ko.observable("year-end.html"),urltitle: ko.observable("Report including final year-end statistics")};ko.applyBindings(viewModel); // apply bindsThe effect is like this:
As mentioned in the previous article, in addition to the individual attributes of XXOO, you can also pass JSON objects, that is, you can combine binding attributes, such as:
<!--HTML code--><div data-bind="{visible: shouldShowMessage, text: myMessage, css: { profitWarning: currentProfit() < 0 }}">You will see this message only when "shouldShowMessage" holds a true value.</div>Of course the effect is like this:
The setting of the presentation class is relatively simple. One thing to note is that many presentation classes do not need to be changed dynamically. At this time, you can use the viewModel settings to achieve centralized initialization of the data, but do not set them to observables, such as:
// js codevar viewModel = { shouldShowMessage: ko.observable(true), // Message initially visiblemyMessage: 'This text does not require dynamic update' // Initially blank};Process class attributes
Process classes include foreach, if, ifnot, with and more advanced "component" bindings. If and ifnot are similar to visible. The difference is: if will directly remove the corresponding components from the DOM, while visible only controls hidden display, and the components are still in the DOM. with has the same effect as with in js, which is to extend the scope chain. In simple terms, it is to add a 'prefix.' before the variable. Here I will only introduce foreach, and component is placed together with template binding.
Check out the code:
<!--HTML code--><p>Test foreach binding</p><ul data-bind="foreach: people"><li>No.<span data-bind="text: $index"> </span>people's name: <span data-bind="text: name"> </span><a href="#" data-bind="click: $parent.removePeople">RemovePeople</a><a href="#" data-bind="click: remove">Remove</a></li></ul><input type="button" data-bind="click: addPeople" value="Add" /> var listModel = function () {//Set the value of the people array (people is actually a function array). Use foreach to traverse the array object //ul, li corresponds to the children of people and people. Therefore, when binding internally li, the scope is in the people child {name...}. In order to call removePeople outside people, $parent is required//If it is called remove internally, this in remove is {name...} corresponding to the current li item, and the scope is the current domain, no $parent is required. this.people = ko.observableArray([{name: "Mark Zake", remove: function () {that.people.remove(this); //Note the current object (that is {name...}) and scope. Don't worry about HTML tags, pure js understanding is simple}},{name: "James Lebo", remove: function () {that.people.remove(this);}},{name: "Green Deny", remove: function () {that.people.remove(this);}}]);//AdPeople calls the method of the same level of people internally. This will change, and this should be saved in advance and passed in. var that = this;this.addPeople = function () {that.people.push({name: new Date().toDateString(),remove: function () {that.people.remove(this);}});};//The object of remove is the entire li tag, that is, the parent object of the a tag. What you want to execute is listModel.people.remove(a.parent)this.removePeople = function() {that.people.remove(this);}};ko.applyBindings(new listModel());What is easier to mess with here is the hierarchical correspondence between the DOM node and the ViewModel. First, apply foreach binding on ul, that is, each li corresponds to each people child. After this corresponds to it, you can understand it according to the scope rules of js. Speaking of scope, I have to mention this. As the saying goes, I treat this as if I were my first love, and this tricked me thousands of times. Here, Xiaojia added a remove function to the official version, which is simple to correspond to the official removePeople. As for variables such as $index and $parent, just understand them literally.
Interaction class attributes
Finally, it's time to get the point. The most important reason for using ko is to deal with the dynamic interactive UI presentation problem. Here we will introduce some bindings related to forms.
(1) Click binding
Syntax: data-bind="click: clickHandler". The clickHandler function here can be any function, not necessarily a function in the ViewModel, as long as it can be referenced. There are a few things to note about the click event:
1. Parameter pass, ko passes the current component as the first parameter to the clickHandler function by default. Pay attention to the current binding context here. For example, in the with environment, the returned component will become the with component instead of the current component you want. If you also need to pass the event parameter, pass the event as the second parameter. If you need to pass in more parameters, you need to wrap it with a function. like:
<button data-bind="click: function(data, event) { myFunction('param1', 'param2', data, event) }">Click me</button>2. Settings of default behavior (such as links)
ko is prohibited by default event behavior, and we usually bind click events for links and will not let them jump. However, if you have to enable it, just return true in clickHandler.
3. Bubble
ko is allowed to bubble by default. You can set the click event not to bubble by data-bind="click: clickHandler, clickBubble: false".
(2) Event binding
ko provides this interface for users to customize binding events. Regarding parameter passing, default behavior, bubbling, etc., the same as click binding, use case:
<div><div data-bind="event: { mouseover: enableDetails, mouseout: disableDetails }">Mouse over me</div><div data-bind="visible: detailsEnabled">Details</div></div><script type="text/javascript">var viewModel = {detailsEnabled: ko.observable(false),enableDetails: function() {this.detailsEnabled(true);},disableDetails: function() {this.detailsEnabled(false);}};ko.applyBindings(viewModel);</script>(3) Submit binding
It is mainly used to do some verification form work. ko will block the default submission form action and transfer to the submit bound function. When you need to submit in the future, return true in the binding event.
PS: Why not use click events in the form to handle it? Because submit is originally designed to handle submission events, it can also accept submission actions such as carriage return, but click cannot.
(4) Value is bound to textInput
The binding value and textInput in the input box look similar, but it is more recommended to use the textInput event for binding, because textInput is a new one specifically used to handle input events. As you can see in the previous article, when using value binding (left) input, the focus must be moved out of the input box before it will be updated, while textInput (right) is updated immediately.
Although value binding can also achieve the same effect as textInput by setting data-bind="{value: price, valueUpdate: 'afterkeydown'}" , this is not as compatible with textInput in the browser.
(5) options binding (selectedOptions)
In the drop-down list, options can be used to bind the value of the child. The child can be either a string or a js object. The previous article ([Knockoutjs Learning Experience Journey] (1) ko first experience) shows strings, and this time I will pass on an object:
Code:
<p>Your country:<select data-bind="options: availableCountries,optionsText: 'countryName',value: selectedCountry,optionsCaption: 'Choose...'"></select></p><div data-bind="visible: selectedCountry"><!-- Appears when you select something -->You have chosen a country with population<span data-bind="text: selectedCountry() ? selectedCountry().countryPopulation: 'unknown'"></span>.</div><script type="text/javascript">// Constructor for an object with two propertiesvar Country = function(name, population) {this.countryName = name;this.countryPopulation = population;};var viewModel = {availableCountries: ko.observableArray([new Country("UK", 65000000),new Country("USA", 320000000),new Country("Sweden", 29000000)]), selectedCountry: ko.observable() // Nothing selected by default};ko.applyBindings(viewModel);</script>Here is an option to bind the list box option, and a value is used to bind the selected item. Since the options are js objects, you need to use an optionText to specify the display in the list box. optionCaption refers to the default display value when no item is selected. If we set a multi-select list box, then we cannot use value to bind selected items. At this time, selectOptions should be used to bind selected items.
(6) Other bindings: enable/disable, hasFocus, checked, uniqueName.
These events are very simple to use, so I won't introduce them in detail. The last uniqueName is used to set the unique name attribute of the form control. When the form is submitted to the background, it will not be submitted to the background without setting the value of the name attribute, so there is such a binding function. There is another relatively common effect on hasFoucus in the official website:
Name:
Name: Bert Bertington
Click the name to edit it; click elsewhere to apply changes.
Clicking on the name above can become editable, and then losing focus and then becoming ordinary text. This effect is quite simple to implement with ko.
Summarize
This article mainly introduces the usage methods of various bindings in knockoutjs . Using the combination of these binding methods, you can simply create a UI page that requires more dynamic interactions. The most important thing to use these methods is to remember that all bindings are function objects, so you can operate directly in HTML, so that the js code structure can sometimes be simpler.
Official tutorial: http://knockoutjs.com/documentation/introduction.html