官术网_书友最值得收藏!

Using internal functions with Knockout

The applyBindings method in the previously explained bindings section uses a common structure. We included that example in case you cross code written in that style. It will help you understand it if you see it someone else's code that is using that approach. Another style of coding is to declare the Model with a function declaration. The DOM markup or View code does not change for either scenario. Let's convert our binding example to a functional declaration. Copy the binding.htm file and create a new file called functions.htm in the same folder. Here is the original declaration:

var viewModel = {
  myVariable: ko.observable()
  ,myHTML: ko.observable()
  ,myLeft: ko.observable()
  ,myRight: ko.observable()
  ,myBalance: ko.observable()
  ,isVisible: ko.observable()
};

Note that we could have set the values of the observables immediately along with the declaration. If we had done that it would have looked like this:

var viewModel = {
  myVariable: ko.observable("Awesome simple!")
  ,myHTML: ko.observable("<strong>Awesome</strong> simple!")
  ,myLeft: ko.observable("pullLeft")
  ,myRight: ko.observable("pushRight")
  ,myBalance: ko.observable(-47.23)
  ,isVisible: ko.observable(true)
};

We are doing this to tighten our code for the sake of the book. You should use good logic when choosing which way to do this in your code. There are times where using this style of coding is important, but often it is just a matter of the coder's style. Beware of letting your style keep you from considering which one is best as you write the code.

Now we will look at moving the code over to a functional declaration. We start, of course, with a different kind of declaration because it is a function as appears here:

function viewModel() {
// add declarations here}

It would be equally valid to declare the ViewModel as follows. There is no significant difference:

viewModel = function() {
// add declarations here}

Now, we will look at adding our ViewModel items back in. In the structured approach we just described, the items were entered as collection items with the classic comma separator. In this model, each item is a parameter and is terminated by a semi-colon:

viewModel = function() {
this.myVariable = ko.observable("Awesome simple!");
this.myHTML = ko.observable("<strong>Awesome</strong> simple!");
this.myLeft = ko.observable("pullLeft");
this.myRight = ko.observable("pushRight");
this.myBalance = ko.observable(-47.23);
this.isVisible = ko.observable(true);}

Note that we declared each of these items with the this scope declaration, which refers to the ViewModel object. When programming in JavaScript, it is common practice to alias this to avoid scope confusion. We will rewrite the previous code one more time using self rather than this as the base scope:

viewModel = function() {
  var self = this;
self.myVariable = ko.observable("Awesome simple!");
self.myHTML = ko.observable("<strong>Awesome</strong> simple!");
self.myLeft = ko.observable("pullLeft");
self.myRight = ko.observable("pushRight");
self.myBalance = ko.observable(-47.23);
self.isVisible = ko.observable(true);}

Tip

Note that we set the self variable using a var declaration. This prevents issues of external naming conflicts.

Now, if we run the page for functions.htm from our browser, it should run identical to our binding.htm file. Yet, there is a difference. This will help you understand why we introduced the developer tools where we did in the course. Open the tools and in the command prompt, enter viewModel.isHTML() to see what you get as a result:

Using internal functions with Knockout

Preventing hidden features

In the previous screenshot we obtained the what you might think is an unexpected result as the View is obviously bound to the ViewModel. The issue here is an issue of the concept of closure. You are welcome to explore more about closure if you wish but just realize it means parts of an object or the item contents are there but hidden. When this type of declaration is made in this style, you cannot interact with it from JavaScript. The declaration should have been made with new to create an object from the function as follows:

ko.applyBindings(new viewModel());

If you run the browser and try to connect to the ViewModel now, you will see that it is still having the same issue with closure. We found this is the best way to work around it at my company:

vm = new viewModel();
ko.applyBindings(viewModel);

Now, we will reference the Model using vm rather than viewModel and this is the result we will get:

Preventing hidden features

We see that by declaring the object outside the argument passed to our Knockout applyBindings method, we avoided the closure issue. This is not an issue when using the structured style of ViewModel declaration. Hopefully, this saves you from hours of wondering what is wrong with your code or if Knockout is broken. We will not answer how much time I burned on this the first time it occurred, but it was long after I started using Knockout. It says that even experts can make rookie mistakes. I humbled myself and asked the community for help, and the answer came pretty fast.

主站蜘蛛池模板: 闵行区| 壤塘县| 宜黄县| 裕民县| 大埔区| 金阳县| 德庆县| 谷城县| 青冈县| 苗栗市| 禹州市| 郯城县| 昭苏县| 会昌县| 湘西| 桐柏县| 康保县| 确山县| 乌拉特后旗| 彝良县| 昌图县| 南乐县| 岳池县| 西乡县| 泰州市| 西和县| 平罗县| 南丹县| 如皋市| 睢宁县| 疏附县| 固镇县| 合江县| 堆龙德庆县| 遵义县| 安平县| 宽城| 河间市| 安康市| 余干县| 恩平市|