KnockOut JS 学习中遇到的几个问题

最近,在项目中需要改之前同事的代码,发现他用了KnockOut,Knockout是一个轻量级的UI类库,通过应用MVVM模式使JavaScript前端UI简单化(如果是正在开发的项目,建议不要使用,技术已经很老了,网上资料少,语法比较复杂,但是如果你想兼容低版本的IE浏览器,这是一个比较好的选择吧。。。)

KnockOut在理解上就和之前的JS控件有不少不同的地方

1)如果你要对模型中的某个属性和视图层进行绑定,必须要使用ko.observable()(或者ko.observableArray()监控数组)来申明一下,然后再视图层通过data-bind来进行绑定。如果你这样做了,你会发现KO会把你自己的属性全都变成函数来进行调用了。例子如下:

<div data-bind="visible: shouldShowMessage">
    You will see this message only when "shouldShowMessage" holds a true value.
</div>

<script type="text/javascript">
    var viewModel = {
        shouldShowMessage: ko.observable(true) // Message initially visible
    };
    viewModel.shouldShowMessage(false); // ... now it's hidden
    viewModel.shouldShowMessage(true); // ... now it's visible again
</script>
在你的JS代码中当你使用viewModel的 shouldShowMessage属性时,你会发现viewModel.shouldShowMessage访问不到改属性,因为它已经变成了一个函数了,你需要使用viewModel.shouldShowMessage()来进行访问,如果需要赋值的话,通过viewModel.shouldShowMessage(true); 来赋值,有点类似jQuery的val函数的使用。

2)如果你监控的是对象,在视图层是需要with来进行绑定的,如下面的例子,而且子属性必须在父属性的标签内部。

<h1 data-bind="text: city"> </h1>
<p data-bind="with: coords">
    Latitude: <span data-bind="text: latitude"> </span>,
    Longitude: <span data-bind="text: longitude"> </span>
</p>
 
<script type="text/javascript">
    ko.applyBindings({
        city: "London",
        coords: {
            latitude:  51.5001524,
            longitude: -0.1262362
        }
    });
</script>

3)使用subscribe回调函数,每次视图改变时,都会触发改函数;如果有需要计算的属性,可以使用ko.computed。

<pre name="code" class="javascript">var ViewModel = function(first, last) {
    this.firstName = ko.observable(first);
    this.lastName = ko.observable(last);
 	this.firstName.subscribe(function(newValue){
        console.log('firstName has changed '+ newValue);
    });
    this.fullName = ko.computed(function() {
        console.log('firstName or lastName has changed '+ this.firstName() + " " + this.lastName());
        return this.firstName() + " " + this.lastName();
    }, this);
};

<div class='liveExample'>   
    <p>First name: <input data-bind='value: firstName' /></p> 
    <p>Last name: <input data-bind='value: lastName' /></p> 
    <h2>Hello, <span data-bind='text: fullName'> </span>!</h2>  
</div>


 
 

4)关于监控数组。在API中有这么一段话

Key point: An observableArray tracks which objects are in the array, not the state of those objects

Simply putting an object into an observableArray doesn’t make all of that object’s properties themselves observable. Of course, you can make those properties observable if you wish, but that’s an independent choice. An observableArray just tracks which objects it holds, and notifies listeners when objects are added or removed.

这段话的意思是,对数组的监控只监控数组本身的属性,而不能监控数组中的每个元素的状态。数组本身的属性是指比如数组的长度,数组增加了或者移除了元素等等。如下面的例子,如果array数组增加了一个元素,或者减少了一个元素,数组的状态会改变,但是如果bob的id改变了,ko是不会进行监控。但是如果想要监控这种变化的话,就需要对数组里的对象中的每个属性再进行监控,如下段代码所示,即进行深度监控。

var ViewModel = function() {
    this.array = ko.observableArray([{
        name : 'join',
        id : '001'
    },{
        name : 'bob',
        id : '002'
    }
    ]);
};
 
ko.applyBindings(new ViewModel()); // This makes Knockout get to work

var ViewModel = function() {
    this.array = ko.observableArray([{
        name : ko.observable('join'),
        id : ko.observable('001')
    }
    ]);
};
 
ko.applyBindings(new ViewModel()); // This makes Knockout get to work
 
 

基本上我所遇到的问题也就这些,以上有些例子使用的是KO官网的例子http://knockoutjs.com/examples/
API http://knockoutjs.com/documentation/introduction.html
我只是在别人代码的基础上进行修改,并没有深入的了解KO,如果所写的有问题,还请各位大神指教。



你可能感兴趣的:(js,MVVM,knockout)