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

本文介绍了在使用KnockOut JS时遇到的几个关键点,包括使用ko.observable()和ko.observableArray()进行数据绑定,视图层的with绑定,subscribe函数响应视图变化,以及observableArray仅跟踪对象存在而不监控其状态。此外,文章提到了深度监控对象属性的必要性,并提供了官方文档链接以供参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近,在项目中需要改之前同事的代码,发现他用了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,如果所写的有问题,还请各位大神指教。



这个文档是我自己原创制作的,在别的网上肯定是没有的。 而且做得非常好看,和非常准确。 如果下载的人多,将会把中英文对照的版本也上传。 Knockout是一个以数据模型(data model)为基础的能够帮助你创建富文本,响应显示和编辑用户界面的JavaScript类库。任何时候如果你的UI需要自动更新(比如:更新依赖于用户的行为或者外部数据源的改变),KO能够很简单的帮你实现并且很容易维护。 重要特性: 优雅的依赖追踪 - 不管任何时候你的数据模型更新,都会自动更新相应的内容。 Elegant dependency tracking - automatically updates the right parts of your UI whenever your data model changes. 声明式绑定 - 浅显易懂的方式将你的用户界面指定部分关联到你的数据模型上。 Declarative bindings - a simple and obvious way to connect parts of your UI to your data model. You can construct a complex dynamic UIs easily using arbitrarily nested binding contexts. 轻易可扩展 - 几行代码就可以实现自定义行为作为新的声明式绑定。 Trivially extensible - implement custom behaviors as new declarative bindings for easy reuse in just a few lines of code. 额外的好处: 纯JavaScript类库 – 兼容任何服务器端和客户端技术 Pure JavaScript library - works with any server or client-side technology 可添加到Web程序最上部 – 不需要大的架构改变 Can be added on top of your existing web application - without requiring major architectural changes 简洁的 - Gzip之前大约25kb Compact - around 13kb after gzipping 兼容任何主流浏览器 - (IE 6+、Firefox 2+、Chrome、Safari、其它) Works on any mainstream browser - (IE 6+, Firefox 2+, Chrome, Safari, others) 采用行为驱动开发 - 意味着在新的浏览器和平台上可以很容易通过验证。 Comprehensive suite of specifications - (developed BDD-style) means its correct functioning can easily be verified on new browsers and platforms 开发人员如果用过Silverlight或者WPF可能会知道KO是MVVM模式的一个例子。如果熟悉 Ruby on Rails 或其它MVC技术可能会发现它是一个带有声明式语法的MVC实时form。换句话说,你可以把KO当成通过编辑JSON数据来制作UI用户界面的一种方式… 不管它为你做什么 Developers familiar with Ruby on Rails, ASP.NET MVC, or other MV* technologies may see MVVM as a real-time form of MVC with declarative syntax. In another sense, you can think of KO as a general way to make UIs for editing JSON data… whatever works for you :) OK, 如何使用它? 简单来说:声明你的数据作为一个JavaScript 模型对象(model object),然后将DOM 元素或者模板(templates)绑定到它上面. The quickest and most fun way to get started is by working through the interactive tutorials. Once you’ve got to grips with the basics, explore the live examples and then have a go with it in your own project. KO和jQuery (或Prototype等)是竞争关系还是能一起使用? 所有人都喜欢jQuery! 它是一个在页面里操作元素和事件的框架,非常出色并且易使用,在DOM操作上肯定使用jQuery,KO解决不同的问题。 Everyone loves jQuery! It’s an outstanding replacement for the clunky, inconsistent DOM API we had to put up with in the past. jQuery is an excellent low-level way to manipulate elements and event handlers in a web page. I certainly still use jQuery for low-level DOM manipulation. KO solves a different problem. 如果页面要求复杂,仅仅使用jQuery需要花费更多的代码。 例如:一个表格里显示一个列表,然后统计列表的数量,Add按钮在数据行TR小于5调的时候启用,否则就禁用。jQuery 没有基本的数据模型的概念,所以需要获取数据的数量(从table/div或者专门定义的CSS class),如果需要在某些SPAN里显示数据的数量,当添加新数据的时候,你还要记得更新这个SPAN的text。当然,你还要判断当总数>=5条的时候禁用Add按钮。 然后,如果还要实现Delete功能的时候,你不得不指出哪一个DOM元素被点击以后需要改变。 As soon as your UI gets nontrivial and has a few overlapping behaviors, things can get tricky and expensive to maintain if you only use jQuery. Consider an example: you’re displaying a list of items, stating the number of items in that list, and want to enable an ‘Add’ button only when there are fewer than 5 items. jQuery doesn’t have a concept of an underlying data model, so to get the number of items you have to infer it from the number of TRs in a table or the number of DIVs with a certain CSS class. Maybe the number of items is displayed in some SPAN, and you have to remember to update that SPAN’s text when the user adds an item. You also must remember to disable the ‘Add’ button when the number of TRs is 5. Later, you’re asked also to implement a ‘Delete’ button and you have to figure out which DOM elements to change whenever it’s clicked. Knockout的实现有何不同? 使用KO非常简单。将你的数据描绘成一个JavaScript数组对象myItems,然后使用模板(template)转化这个数组到表格里(或者一组DIV)。不管什么时候数组改变, UI界面也会响应改变(不用指出如何插入新行或在哪里插入),剩余的工作就是同步了。例如:你可以声明绑定如下一个SPAN显示数据数量(可以放在页面的任何地方,不一定非要在template里): It’s much easier with KO. It lets you scale up in complexity without fear of introducing inconsistencies. Just represent your items as a JavaScript array, and then use a foreach binding to transform this array into a TABLE or set of DIVs. Whenever the array changes, the UI changes to match (you don’t have to figure out how to inject new TRs or where to inject them). The rest of the UI stays in sync. For example, you can declaratively bind a SPAN to display the number of items as follows: There are <span data-bind="text: myItems().count"></span> items就是这些!你不需要写代码去更新它,它的更新依赖于数组myItems的改变。同样, Add按钮的启用和禁用依赖于数组 myItems 的长度,如下: That’s it! You don’t have to write code to update it; it updates on its own when the myItems array changes. Similarly, to make the ‘Add’ button enable or disable depending on the number of items, just write: <button data-bind="enable: myItems().count < 5">Add</button>之后,如果你要实现Delete功能,不必指出如何操作UI元素,只需要修改数据模型就可以了。 Later, when you’re asked to implement the ‘Delete’ functionality, you don’t have to figure out what bits of the UI it has to interact with; you just make it alter the underlying data model. 总结:KO没有和jQuery或类似的DOM 操作API对抗竞争。KO提供了一个关联数据模型和用户界面的高级功能。KO本身不依赖jQuery,但是你可以一起同时使用jQuery, 生动平缓的UI改变需要真正使用jQuery。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值