问题
单选按钮很难看到,不容易选择,让我们面对它,相当平凡。您可能想用一组具有相同功能的按钮来替换这些单选按钮,例如,在任何给定的时间只能选择其中一个选项。
解决方案
利用Bootstrap,它为按钮、警告框、表格、表单等提供了许多令人难以置信的样式组件,常规的单选按钮将被一个按钮组取代(见下面的截图)。js将用于创建一个定制的数据绑定,它将使这组按钮像常规的单选按钮一样工作(当然有更好的外观)。
这个例子假设您对Bootstrap和Knockout.js都有基本的了解。
本例使用的版本是Bootstrap的3.3.4和Knockout.js的3.3。这个示例应该与这些框架的旧版本兼容。
讨论
在开始之前,必须设置所需的框架。Bootstrap可以通过他们的CDN安装或下载。这个例子将使用CDN;但是,我建议您使用最适合您需要的选项。js已经被下载并保存到与示例相同的位置。确保根据项目的位置更新此位置。最后,在敲除定制绑定中使用了一点jQuery。再一次,这个例子利用了CDN;但是,如果你喜欢,你可以下载并包含它。
要使这个示例工作,它需要两个条件。一组按钮,如果它们是单选按钮,将包含哪些选项,以及将在数据绑定中使用的敲除可观察值。这个可观察对象将包含选中的选项。下面包含HTML标记和非常基本的Knockout ViewModel。
<html> <head> <linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> </head> <body> <divclass="btn-group"> <buttontype="button"class="btn btn-default"data-bind="radioButtonGroup: selectedOption, radioValue: 'option1'">Option 1</button> <buttontype="button"class="btn btn-default"data-bind="radioButtonGroup: selectedOption, radioValue: 'option2'">Option 2</button> <buttontype="button"class="btn btn-default"data-bind="radioButtonGroup: selectedOption, radioValue: 'option3'">Option 3</button> </div> <scriptsrc="knockout.js"></script> <scriptsrc="http://code.jquery.com/jquery-2.1.3.min.js"></script> <script> function ViewModel() { var self = this; self.selectedOption = ko.observable(); }; var viewModel = new ViewModel(); ko.applyBindings(viewModel); </script> </body> </html>
这个例子现在还不能工作。如果仔细观察,就会发现每个HTML按钮都包含一个名为radioButtonGroup的数据绑定(马上就会定义)。这是将完成我们的按钮组的定制数据绑定。提供给新数据绑定的是可观察变量,它被恰当地命名为selectedOption。第二个值也被命名为radioValue。这应该设置为用户按下按钮时希望selectedOption变量包含的值。
要完成这个示例,需要创建自定义绑定。在ko下添加自定义绑定。bindingHandlers名称空间。绑定处理程序是通过创建init和update函数定义的。两者都是可选的,但至少必须定义一个。当Knockout是绑定到页面的第一个数据时,将调用init函数。你可以在这里创建事件监听器等等。每次值更改时(包括第一次加载时)都会调用update函数。如果您希望在每次值更改时执行特定的操作,则将使用此函数。
radioButtonGroup自定义绑定只需要init函数,因为单击事件的事件监听器将用于跟踪所有更改。下面的JavaScript代码应该在包含Knockout框架之后,但在定义ViewModel和应用Knockout绑定之前放置(或从一个单独的文件中包含)。
<script> ko.bindingHandlers.radioButtonGroup = { init: function (element, valueAccessor, allBindings, viewModel, context) { var $buttons, $element, observable; observable = valueAccessor(); if (!ko.isWriteableObservable(observable)) { throw "You must pass an observable or writeable computed"; } $element = $(element); if ($element.hasClass("btn")) { $buttons = $element; } else { $buttons = $(".btn", $element); } elementBindings = allBindings(); $buttons.each(function () { var $btn, btn, radioValue; btn = this; $btn = $(btn); radioValue = elementBindings.radioValue || $btn.attr("data-value") || $btn.attr("value") || $btn.text(); $btn.on("click", function () { observable(ko.utils.unwrapObservable(radioValue)); }); return ko.computed({ disposeWhenNodeIsRemoved: btn, read: function () { $btn.toggleClass("active", observable() === ko.utils.unwrapObservable(radioValue)); $btn.toggleClass("btn-info", observable() === ko.utils.unwrapObservable(radioValue)); } }); }); } }; </script>
init函数接受5个参数。被数据绑定的元素,也是数据绑定的变量,这个元素上的所有其他绑定,整个ViewModel(尽管这是不赞成的),还有bindingContext,这是通过使用bindingContext.$data来访问ViewModel的新方法。
在init函数内部,它首先验证它正在处理一个可观察属性。通过使用带有数据绑定的HTML元素(和一些jQuery),可以找到相关的按钮并存储在一个变量中。然后循环使用这些按钮,并侦听单击事件。当它发生时,与数据绑定值相关联的可观察属性将使用所选选项更新。最后定义一个计算变量,如果可观察对象的值等于按钮的值,则添加类active和btn-info来标识当前选择的按钮。
这就完成了本示例,一如既往,您可以在GitHub上找到完整的源代码。
本文转载于:http://www.diyabc.com/frontweb/news14015.html