In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces the use of Observables in Knockout, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let the editor take you to understand it.
1 create a view model with monitoring attributes
Observables
Knockout is built on the following three core functions:
◆ Monitoring Properties (Observables) and dependency tracking (Dependency tracking)
◆ declarative binding (Declarative bindings)
◆ template (Templating)
In this section, you talk about * of the three functions. Before we do that, let's explain the concepts of MVVM schema and view model.
MVVM and View Models
Model-View-View Model (MVVM) is a design pattern for creating user interfaces. Describes how to divide the complex UI user interface into three parts:
◆ model: the data stored in your program. This data includes objects and business operations (for example, a silver account can transfer money) and is independent of any UI. When using KO, it is usually said to call Ajax to the server to read and write the stored model data.
◆ view model: on UI, pure code describes the data and operations. For example, if you implement list editing, your view model should be an operation method that contains objects containing list items items and exposed add/remove list items (item).
Note that this is not UI itself: it does not contain any button concept or display style. Nor is it a persistent data model-it contains unsaved data that the user is using. When using KO, your view models is a pure JavaScript object that does not contain any HTML knowledge. Keeping the view model abstract keeps it simple so that you can manage more complex behaviors.
◆ view: a visible, interactive UI that represents the state of view model. Display data from view model, send commands to view model (for example, when the user click button), and update any view model status changes.
When using KO, your view is your HTML document with binding information, and these declarative bindings are managed on your view model. Or you can use templates to get data from your view model and generate HTML.
To create a view model, you only need to declare any JavaScript object. For example:
Var myViewModel = {personName: 'Bob', personAge: 123}
You can create a simple view for declarative binding for view model. For example, the following code displays the personName value:
The name is
Activating Knockout
The data-bind attribute is easy to use as soon as possible, but it is not a native property of HTML (it strictly follows the HTML5 syntax, and although the HTML4 validator prompts for unrecognized attributes, it is still available). Since the browser doesn't recognize what it means, you need to activate Knockout to make it work.
To activate Knockout, you need to add the following code block:
Ko.applyBindings (myViewModel)
You can put this code block at the bottom of HTML, or in the $function or ready function of jQuery, and then put it on the top of the page, and the final result is the following HTML code:
The name is Bob
You may wonder what parameters ko.applyBindings uses.
◆ * parameter is what you want to use for declarative binding
The second parameter of ◆ (optional) can be declared as a HTML element or container that uses data-bind. For example, ko.applyBindings (myViewModel, document.getElementById ('someElementId')). For now, only elements and children of someElementId can activate KO functionality. The advantage is that you can declare multiple view model on the same page to distinguish between regions.
Observables
Now you know how to create a simple view model and display its properties through binding. But one of the important features of KO is that it automatically updates your interface when your view model changes. How does KO know when your view model part changes? The answer is: you need to declare your model property as observable because it is a very special JavaScript objects that notifies subscribers of its changes and automatically detects relevant dependencies.
For example, change the view model of the above example to the following code:
Var myViewModel = {personName: ko.observable ('Bob'), personAge: ko.observable (123)}
You don't need to modify view at all-all data-bind syntax still works, except that it can monitor the change, and view will update automatically when the value changes.
Reading and writing of monitoring attributes (observables)
Not all browsers support JavaScript's getters and setters (such as IE), so for compatibility, objects monitored using ko.observable are real function functions.
◆ reads the value of the monitoring property (observable) and only needs to call the monitoring property (observable) directly (no parameters are required). For example, myViewModel.personName () will return 'Bob', myViewModel.personAge () will return 123.
◆ writes a new value to the monitoring property (observable), invokes the observable property and takes the new value as a parameter. For example, calling myViewModel.personName ('Mary') will update the name value to' Mary'.
◆ writes new values to multiple properties of a model object, and you can use chained syntax. For example: myViewModel.personName ('Mary'). PersonAge (50) will update name to' Mary' and age to 50.
The characteristic of observables is observed, for example, other code can say that I need to be notified of object changes, so there are a lot of built-in binding syntax inside KO. So if your code is written as data-bind= "text: personName", the text binding is registered with itself, and once the value of personName changes, it will be notified.
Of course, call myViewModel.personName ('Mary') to change the value of name, and the text binding will automatically update the new value to the corresponding DOM element. This is how changes to view model are propagated to view.
Explicit subscriptions to monitor properties (Observables)
Usually, you don't have to subscribe by hand, so beginners can ignore this section. Advanced users, if you want to register your subscription to the monitoring property (observables), you can call its subscribe function. For example:
MyViewModel.personName.subscribe (function (newValue) {alert ("The person's new name is" + newValue);})
This subscribe function is used in many places inside. You can also terminate your subscription: first get your subscription, and then call the object's dispose function, for example:
Var subscription = myViewModel.personName.subscribe (function (newValue) {/ * do stuff * /}); / /... then later... Subscription.dispose (); / / I no longer want notifications
In most cases, you don't need to do this, because the built-in binding and template system has done a lot of things for you, and you can use them directly.
2 use dependency monitoring properties (Dependent Observables)
What if you already have the monitoring properties firstName and lastName, and you want to display the full name? This requires the use of dependency monitoring properties-these functions are one or more monitoring properties, and if their dependency object changes, they will automatically change.
For example, the following view model
Var viewModel = {firstName: ko.observable ('Bob'), lastName: ko.observable (' Smith')}
... You can add a dependency monitoring attribute to return the full name:
ViewModel.fullName = ko.dependentObservable (function () {return this.firstName () + "+ this.lastName ();}, viewModel)
And bind to the element of UI, for example:
The name is
... Regardless of whether the firstName or lastName changes, the full name fullName will be updated automatically (no matter who changes, the execution function will be called once, and no matter what the change is, his value will be updated to UI or other dependent monitoring properties).
Manage 'this'
Novices can ignore this section, you just need to install the code pattern in the above example to write, do not need to know / follow this this.
You may wonder what the second parameter of ko.dependentObservable is for (I passed viewModel in the above example), which is used to declare this that depends on monitoring properties. Without it, you cannot refer to this.firstName () and this.lastName (). Seasoned JavaScript developers don't think much of this, but if you're not familiar with JavaScript, you'll be new to it. (whether C# and Java need to set a value of this for set, but JavaScript does, because their functions themselves are not part of any object by default).
Unfortunately, there is no way for JavaScript objects to reference themselves, so you need to use myViewModelObject.myDependentObservable =. To add dependency monitoring properties to the view model object in the form of You can't declare them directly in view model, in other words, you can't write something like this:
Var viewModel = {myDependentObservable: ko.dependentObservable (function () {...}, / * can't refer to viewModel from here, so this doesn't work * /)}
... Instead, you have to write something like this:
Var viewModel = {/ / Add other properties here as you wish}; viewModel.myDependentObservable = ko.dependentObservable (function () {...}, viewModel); / / This is OK
As long as you know what to expect, it's really not a problem.
Dependency chain
Of course, you can create a chain that relies on monitoring properties if you want. For example:
The ◆ monitoring property items represents a set of list items
The ◆ monitoring property selectedIndexes holds the index of the list items selected by the user
◆ relies on the monitoring property selectedItems to return an array of list items corresponding to selectedIndexes
Another ◆ dependency on the true or false returned by the monitoring property depends on whether each list item of the selectedItems contains some properties (for example, whether it is new or has not been saved). The state of some UI element (like the enable / disable of buttons) depends on this value.
Then, changes to items or selectedIndexes will affect all chains that depend on monitoring attributes, and all UI elements that bind these attributes will be updated automatically. How neat and elegant it is!
Writable dependency monitoring properties
Beginners can ignore this section, writeable dependency monitoring properties are really too advanced and are not needed in most cases.
As you have learned, dependency monitoring properties are obtained by calculating other monitoring properties. The feeling is dependent on monitoring properties. Normally, it should be read-only. So, is it possible to make dependency monitoring properties writable? You just need to declare your own callback function and then use the written value to process the corresponding logic.
You can use dependency monitoring attributes like normal monitoring attributes-data are bidirectionally bound to DOM elements and intercept all read and write operations through custom logic. This is a very powerful feature and can be used on a large scale.
Example 1: decompose the user's input
Going back to the classic "first name + last name = full name" example, you can turn things around: make the dependency monitoring property fullName writable, let the user enter the full name directly, and then the entered value will be parsed and mapped to the basic monitoring properties firstName and lastName:
Var viewModel = {firstName: ko.observable ("Planet"), lastName: ko.observable ("Earth")}; viewModel.fullName = ko.dependentObservable ({read: function () {return this.firstName () + "+ this.lastName ();}, write: function (value) {var lastSpacePos = value.lastIndexOf (") If (lastSpacePos > 0) {/ / Ignore values with no space character this.firstName (value.substring (0, lastSpacePos)); / / Update "firstName" this.lastName (value.substring (lastSpacePos + 1)); / / Update "lastName"}, owner: viewModel})
In this example, the callback of the write operation accepts the written value, separates the value and writes it to "firstName" and "lastName", respectively. You can bind this view model to the DOM element as usual, as follows:
First name:
Last name:
Hello,!
This is a counterexample of the Hello World example, where the last name and first name are not editable, while the full name of the first name and last name is editable.
The above view model demonstrates initializing dependency monitoring properties with a simple parameter. You can pass any JavaScript object to the following properties:
◆ read-required, a function used to execute a function that gets the current value of a dependent monitoring property.
◆ write-optional, if the declaration will make your dependency monitoring property writable, other code if this writeable function writes a new value, write the value back to each underlying monitoring property through custom logic.
◆ owner-optional, if declared, is the this that KO uses when calling read or write's callback. Check "manage this" for update information.
Example 2:Value converter
Sometimes you may need to display data in different formats, transforming from the basic data to the display format. For example, you store the price as float, but the fields that allow users to edit need to support currency units and decimal points. You can do this with writable dependency monitoring properties, and then parse the incoming data into the basic float type:
ViewModel.formattedPrice = ko.dependentObservable ({read: function () {return "$" + this.price (). ToFixed (2);}, write: function (value) {/ / Strip out unwanted characters, parse as float, then write the raw data back to the underlying "price" observable value = parseFloat (value.replace (/ [^\.\ d] / g, "")) This.price (isNaN (value)? 0: value); / / Write to underlying storage}, owner: viewModel})
Then we bind formattedPrice to text box:
Enter bid price:
So, no matter when the user enters the new price and what format the user enters, the text box will automatically update to a value with 2 decimal places and currency symbols. In this way, the user can see how smart your program is to tell the user that you can only enter 2 decimal places, otherwise you can automatically delete the extra digits, and of course you can't enter a negative number, because write's callback function automatically removes the negative sign.
Example 3: filter and validate user input
Example 1 shows the write filtering function. If the value you write does not meet the criteria, it will not be written, ignoring all values that do not include spaces.
One more step, you can declare a monitoring attribute isValid to indicate whether a write is legal or not, and then display the corresponding prompt according to the true and false values. To introduce it in detail later, refer to the following code:
Var viewModel = {acceptedNumericValue: ko.observable (123), lastInputWasValid: ko.observable (true)}; viewModel.attemptedValue = ko.dependentObservable ({read: viewModel.acceptedNumericValue, write: function (value) {if (isNaN (value)) this.lastInputWasValid (false); else {this.lastInputWasValid (true); this.acceptedNumericValue (value) / / Write to underlying storage}, owner: viewModel})
... Declare the binding element in the following format:
Enter a numeric value:
That's not a number!
For now, acceptedNumericValue will only accept numbers, and any other value entered will trigger the display of validation information and update the acceptedNumericValue.
Note: the above example is too lethal, and an easier way is to use jQuery Validation and number class on the. Knockout works well with jQuery Validation. Refer to the example: grid editor. Of course, the above example still shows how to use custom logic to filter and validate data, which you can use if validation is complex and jQuery Validation is difficult to use.
Rely on tracking how it works
Novices don't need to know too much, but senior developers need to know why relying on monitoring properties can automatically track and update UI.
In fact, it's very simple, even cute. The logic of the trace is as follows:
◆ when you declare a dependent monitoring property, KO immediately calls the execution function and gets the initialization value.
◆ when your execution function runs, KO records all dependent attributes (or monitoring dependent properties) into a Log list.
After the end of the ◆ execution function, KO subscribes to all the objects that need to be relied on in the Log. The subscribed callback function is to rerun your execution function. Then go back and re-perform the above * step (and log out subscriptions that are no longer in use).
◆ * * KO notifies all upstream subscribers that I have set the new value.
So, KO doesn't just detect your dependencies during the * execution of the function, it does it every time. For example, your dependency attribute can be dynamic: dependency attribute A represents whether you depend on dependency attribute B or C, and the execution function is re-executed only when An or your current choice B or C changes. You don't need to declare any other dependencies: the runtime will detect them automatically.
Another trick is that the binding of a template output is a simple implementation that relies on the monitoring property. If the template reads the value of a monitoring property, the template binding will automatically become dependent on the monitoring attribute. Once the monitoring property is changed, the dependent monitoring property of the template binding will be executed automatically. Nested templates are also automatic: if template X render template Y, and Y needs to display the value of the monitoring property Z, when Z changes, only Y is redrawn (render) because only Y depends on it.
3 use observable array
If you want to detect and respond to changes in an object, you should use observables. If you need to detect and respond to changes in a collection object, you should use observableArray. It is very useful in many scenarios, such as a list data collection that you need to display / edit on UI, and then add and delete the collection.
Var myObservableArray = ko.observableArray (); / / Initially an empty array myObservableArray.push ('Some value'); / / Adds the value and notifies observers
Key point: the monitoring array tracks the objects in the array, not the state of those objects themselves.
To put it simply, putting an object in an observableArray does not make the property changes of the object itself controllable. Of course, you can declare the property of this object to be observable, but it becomes a dependent monitoring object. An observableArray only monitors the objects it owns and notifies them when they are added or deleted.
Preload a monitoring array observableArray
If you want your monitoring array to have some initial values at the beginning, you can add these initial objects to the constructor at the time of declaration. For example:
/ / This observable array initially contains three objects var anotherObservableArray = ko.observableArray ([{name: "Bungle", type: "Bear"}, {name: "George", type: "Hippo"}, {name: "Zippy", type: "Unknown"}])
Read information from observableArray
An observableArray is actually a monitoring object of an observable, except that its value is an array (observableArray adds a lot of other features, which will be described later). So you can get your own value just like getting the value of a normal observable by calling a no-parameter function. For example, you can get its value as follows:
Alert ('The length of the array is' + myObservableArray (). Alert ('The first element is' + myObservableArray () [0]))
Theoretically, you can use any native JavaScript array function to manipulate these arrays, but KO provides better functional equivalence functions, and they are very useful because:
◆ is compatible with all browsers. (for example, indexOf cannot be used on IE8 and earlier versions, but KO's own indexOf can be used on all browsers)
◆ in terms of array manipulation functions (such as push and splice), KO's own way can automatically trigger dependency tracking and notify all subscribers of its changes, and then let the UI interface update automatically accordingly.
The ◆ syntax is more convenient. To call the push method of KO, you just need to write: myObservableArray.push (...). For example, the myObservableArray (). Push (...) of the primitive array. It's much better.
The following is about the read and write functions of observableArray.
IndexOf
The indexOf function returns * * indexes equal to the items in your parameter array. For example: myObservableArray.indexOf ('Blah') will return the index of * array items equal to Blah with an index of 0. If no equals are found,-1 is returned.
Slice
The slice function is the equivalent of observableArray to the JavaScript native function slice (returns a given collection of objects from the start index to the end index). Call myObservableArray.slice (...) Is equivalent to calling the JavaScript native function (for example: myObservableArray () .slice (...)).
Manipulate observableArray
ObservableArray shows similar functions of array objects and notifies subscribers.
Pop, push, shift, unshift, reverse, sort, splice
All of these functions are equivalent to the native functions of the JavaScript array, and the only different array changes can notify the subscriber:
MyObservableArray.push ('Some new value') adds a new entry to the end of the array
MyObservableArray.pop () deletes an item in the array * and returns it
MyObservableArray.unshift ('Some new value') adds an item to the array header
MyObservableArray.shift () deletes the array header * item and returns it
MyObservableArray.reverse () flips the order of the entire array
MyObservableArray.sort () sorts the array
By default, it sorts by character (if it is a character) or by number (if it is a number).
You can sort by passing in a sort function, which needs to accept 2 parameters (representing the items to be compared in the array). If the * * items are less than the second item, return-1, and if greater than 1, return 1, which is equal to 0. For example, to sort person with lastname, you can write: myObservableArray.sort (function (left, right) {return left.lastName = = right.lastName? 0: (left.lastName < right.lastName?-1: 1)})
MyObservableArray.splice () deletes the specified starting index and the specified number of array object elements. For example, myObservableArray.splice (1, 3) removes three elements from index 1 (2, 3) and returns these elements as an array object.
For more information about the observableArray function, refer to the equivalent JavaScript array standard function.
Remove and removeAll
ObservableArray adds some useful functions that are not available by default in the JavaScript array:
MyObservableArray.remove (someItem) deletes all elements equal to someItem and returns the deleted elements as an array
MyObservableArray.remove (function (item) {return item.age < 18}) deletes all elements whose age attribute is less than 18 and returns the deleted elements as an array
MyObservableArray.removeAll (['Chad', 132, undefined]) deletes all elements equal to' Chad', 123, or undefined and returns the deleted elements as an array
Destroy and destroyAll (Note: usually only related to Ruby on Rails developers)
The destroy and destroyAll functions are developed for the convenience of Ruby on Rails developers:
MyObservableArray.destroy (someItem) finds all the elements equal to someItem and adds an attribute _ destroy to them, and assigns them a value of true.
MyObservableArray.destroy (function (someItem) {return someItem.age < 18}) finds all elements whose age attribute is less than 18 and adds an attribute _ destroy to them, and assigns it to true.
MyObservableArray.destroyAll (['Chad', 132, undefined]) finds all elements equal to' Chad', 123, or undefined, and adds an attribute _ destroy to them, and assigns them a value of true.
So, what is _ destroy for? As I mentioned, this is only for Rails developers. During Rails development, if you pass in a JSON object, the Rails framework will automatically convert it to an ActiveRecord object and save it to the database. The Rails framework knows which objects exist in the database and which need to be added or updated, and marking _ destroy as true tells the framework to delete the record.
Note that when you KO render a foreach template, the element with the _ destroy attribute and the value true is automatically hidden. So if your "delete" button calls the destroy (someItem) method, the corresponding element on the UI interface will be automatically hidden, and then when you submit the JSON object to the Rails, the element item will be deleted from the database (while other element items will be inserted or updated normally).
Thank you for reading this article carefully. I hope the article "what is the use of Observables in Knockout" shared by the editor will be helpful to you. At the same time, I also hope you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.