Knockout.js是什么?
Knockout是一款很优秀的javascript库,它可以帮助你仅使用一个清晰整洁的底层数据模型(data model)即可创建一个富文本且具有良好的显示和编辑功能的用户界面。任何时候你的局部UI内容需要自动更新(比如:依赖于用户行为的改变或者外部的数据源发生变化),KO都可以很简单的帮你实现,并且非常易于维护。
KO重要特性:
-
优雅的依赖跟踪-任何时候当数据源模型发生变化时,它都能够自动的更新你UI的指定内容。
-
声明式绑定-它通过简单浅显的方式将你的UI与数据源模型进行绑定,你可以使用任意嵌套的结构模版来组建一个复杂的动态界面。
-
良好的可扩展性-通过简单的几行代码就可以实现一个自定义行为作为新的声明进行绑定。
其他优点:
-
纯JavaScript库-兼容任何服务器和客户端技术。
-
可以很好的应用到已有的应用程序中-而不需要程序主要架构发生变化。
-
简洁-采用Gzip压缩之后只要13K。
-
兼容任何主流浏览器-(IE 6+, Firefox 2+, Chrome, Safari, 及其他)
-
一套全面完整的规范(采用行为驱动开发)-这意味着在新的浏览器或平台中也能够很容易验证通过。
开发人员如果熟悉Ruby on Rails,Asp.net MVC 或其它MVC技术可能会发现它是一个带有声明式语法的MVC实时form。换句话说,你可以把KO当成通过编辑JSON数据来制作UI用户界面的一种方式… 不管它为你做什么。
如何使用它?
最快速、最有趣的方式就是通过互动式教学的方式来开始学习,一旦你掌握了最基本的技巧,学习了每个在线实例,你就可以在你的项目中一展身手了。
KO和Jquery(prototype等)是相互竞争还是可以兼容一起使用?
每个人都很喜欢Jquery!在过去,我们不得不忍受各种不一致的DOM对象操作的API方法,Jquery的出现,很出色的代替了以往种种笨拙的框架,显得灵活易用。Jquery在Web页面元素操作和事件处理上显得相当出色并且易用,而KO是解决另外不同的问题的。
当你的UI界面稍微复杂且含有一些相同的行为的话,如果你仅仅只使用Jquery,那么UI处理上会比你想象的要复杂棘手,同时会让维护费用相当昂贵。思考这样一个例子:在一个表格里显示一个项目列表,统计表格中列表的数量,当项目列表数量小于5时启用“Add”按钮,否则就禁用。Jquery没有基本的数据模型概念,所以你想要获取项目列表的数量,你需要从表格table/tr/div这些数量上去进行推断才能知道。如果需要在某些SPAN里显示数据的数量,当添加新数据的时候,你还要记得更新这个SPAN的text。当然,你还要记住当总数>=5条的时候,你需要禁用Add按钮。然后,如果还要实现Delete功能的时候,你不得不指出哪一个DOM元素被点击以后需要改变。
用Knockout来实现又有何不同?
使用KO这一切都变得非常简单。它可以让你很轻易的扩展项目的复杂度,而不必担心由此产生的数据不一致问题。它仅仅只需要将你的数据转换成一个JavaScript数组,然后使用foreach将数据数组绑定到页面中的一个表格table或者一组div中。每当数据数组发生变化时,UI界面会自动响应改变(你不需要指出如何插入新行或在哪里插入),剩下的就是UI界面数据同步了。例如:你可以声明绑定如下一个SPAN显示数据数量:
隐藏代码Thereare<span data-bind="text:myItems().count"></span>items
就是这些!你不需要写代码去更新它,它的更新依赖于数组myItems的改变。同样, Add按钮的启用和禁用依赖于数组myItems的长度,如下:
隐藏代码<button data-bind="enable:myItems().count<5">Add</button>
之后,如果你需要实现“Delete”功能,你不必去指定如何操作UI元素,只需要修改数据模型就可以了。
总结:KO无意与jQuery这些类似的DOM 操作框架进行竞争。KO提供了一个数据模型与用户UI界面进行关联的高层次方式。KO本身不依赖jQuery,但是你可以一起同时使用jQuery, 生动平缓的UI改变需要使用jQuery。
以上转自:http://www.aizhengli.com/knockoutjs/50/knockout.html
以下是实际事例:
text绑定:你可以为p,span,div,td等标记去加这个text元素
value绑定:你可以为input标记加value元素
attr绑定:你可以为标记动态添加它们的属性,如<a>标签的href,title,<img>标签的src,alt等等
visible绑定:可以动态显示或隐藏指定的标记,true值为显示,false值为隐藏
with绑定:可以绑定一个对象,然后在内部标记里就可以访问对象的属性了
//---------------------------------------------------------------------------------------------------------
<script type="text/javascript" src="js/knockout-2.2.0.debug.js"></script> <script type="text/javascript" src="js/jquery-2.1.0.js"></script> </head> <body> <h4>People</h4> <ul data-bind="foreach: people"> <li>Name at position <span data-bind="text: $index"> </span>: <span data-bind="text: name"> </span> <a href="#" data-bind="click: $parent.removePerson">Remove</a> </li> </ul> <button data-bind="click: addPerson">Add</button> <button data-bind="click: msg">Length</button> <!-- <div data-bind="visible: myValues().length >0">You will see this message only when \'myValues\' has at least one member.</div> --> <script type="text/javascript"> //var viewModel = { // myValues : ko.observableArray([]) //// Initially empty, so message hidden //}; //viewModel.myValues.push("some value"); // Now visible function AppViewModel() { var self = this; self.people = ko.observableArray([ { name : \'Bert\' }, { name : \'Charles\' }, { name : \'Denise\' } ]); self.addPerson = function() { self.people.push({ name : "New at " + new Date() }); }; self.removePerson = function() { self.people.remove(this); } self.msg = function() { alert(self.people().length); var i = 0; for (i = 0; i < self.people().length; i++) { alert(self.people()[i].name); } } } ko.applyBindings(new AppViewModel()); </script> </body> </html>
//-------------------------------------------------------------------------------------------------------------------- <script type="text/javascript" src="js/knockout-2.2.0.debug.js"></script> <script type="text/javascript" src="js/jquery-2.1.0.js"></script> </head> <body> <p> Enter bid price:<input data-bind="value: formattedPrice" id="txtPrice" /> </p> <p> Enter bid price:<input data-bind="value: formattedPrice" id="txtRmb" /> </p> <div id="div1"> <p> Enter a numeric value: <input data-bind="value: attemptedValue" id="v1" /> </p> <div data-bind="visible: !lastInputWasValid()">That\'s not a number!</div> </div> <div id="div2"> <div data-bind="visible: myValues().length >0">You will see this message only when \'myValues\' has at least one member.</div> <p> <button data-bind="click: addMyValue">Add</button> </p> </div> <p>http://www.xiaoboy.com/detail/2015042809.html</p> <div id="div3"> <div> <button data-bind="click:show">显示/隐藏</button> </div> <div data-bind="visible:visible">小虾虎鱼</div> </div> <p></p> <div id="div4"> <div> <button data-bind="click:show.bind($data,1)">按钮1</button> <button data-bind="click:show.bind($data,2)">按钮3</button> <button data-bind="click:show.bind($data,3)">按钮3</button> </div> <p></p> <div data-bind="visible:visible()===1">内容1</div> <div data-bind="visible:visible()===2">内容2</div> <div data-bind="visible:visible()===3">内容3</div> </div> <p></p> <div id="div5"> <p data-bind="with:lines"> 单价:<input type="text" data-bind=\'value:productPrice, valueUpdate: "afterkeydown"\' /> 数量:<input type="text" data-bind=\'visible:productPrice() > 0,value: productCount, valueUpdate: "afterkeydown"\' /> 小计:<span data-bind="text:total"></span> <a data-bind=\'attr:{href:"/test/demo/test.json?id="+id,title:name}\'>添加</a> </p> </div> <script type="text/javascript"> function MyViewModel() { this.price = ko.observable(25.99); this.formattedPrice = ko.computed({ 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" servable value = parseFloat(value.replace(/[^\\.\\d]/g, "")); this.price(isNaN(value) ? 0 : value); // Write to underlying storage }, owner : this }); } ko.applyBindings(new MyViewModel(), document.getElementById("txtPrice")); function MyViewModel2() { this.price = ko.observable(25.93); this.formattedPrice = ko.computed({ 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" servable value = parseFloat(value.replace(/[^\\.\\d]/g, "")); this.price(isNaN(value) ? 0 : value); // Write to underlying storage }, owner : this }); } ko.applyBindings(new MyViewModel2(), document.getElementById("txtRmb")); function MyViewModel3() { this.acceptedNumericValue = ko.observable(123); this.lastInputWasValid = ko.observable(true); this.attemptedValue = ko.computed({ read : this.acceptedNumericValue, write : function(value) { if (isNaN(value)) this.lastInputWasValid(false); else { this.lastInputWasValid(true); this.acceptedNumericValue(value); // Write to underlying storage } }, owner : this }); } ko.applyBindings(new MyViewModel3(), document.getElementById("div1")); var viewModel = { myValues : ko.observableArray([]) }; this.addMyValue = function() { if (viewModel.myValues().length > 0) { viewModel.myValues.removeAll(); } else { viewModel.myValues.push("some value"); } }; //viewModel.myValues.push("some value"); // Now visible ko.applyBindings(viewModel, document.getElementById("div2")); var viewmodel2 = { visible : ko.observable(false), show : function() { this.visible(!this.visible()); } }; ko.applyBindings(viewmodel2, document.getElementById("div3")); var vm = { visible : ko.observable(1), show : function(index) { this.visible(index); } }; ko.applyBindings(vm, document.getElementById("div4")); var product = function() { self = this; self.id = 1; self.name = "测试产品"; self.productPrice = ko.observable(0); self.productCount = ko.observable(1); self.total = ko.computed(function() { return (self.productCount() * self.productPrice()).toFixed(2); }); } var products = function() { var self = this; self.lines = ko.observable(new product()); } ko.applyBindings(new products(), document.getElementById("div5")); </script> </body> </html>
//http://www.cnblogs.com/lori/p/3502100.html
//---------------------------------------------------------------------------------------------------------