如何使用 knockout.js 正确绑定和初始化 jQuery Mobile 范围滑块?
Posted
技术标签:
【中文标题】如何使用 knockout.js 正确绑定和初始化 jQuery Mobile 范围滑块?【英文标题】:How to correctly bind and initialize a jQuery Mobile range slider with knockout.js? 【发布时间】:2013-05-05 23:32:52 【问题描述】:我很难让 JQM 范围滑块在淘汰赛中正常工作。 这是一个非常基本的 JQM 滑块的 html 代码:
<input type="range" name="quantity-slider" id="quantity-slider" min="0" max="10">
我已经创建了这个敲除绑定作为示例,应用于准备好的文档:
var ViewModel = function()
this.quantity = ko.observable(4);
$(document).ready(function ()
ko.applyBindings(new ViewModel());
);
我在互联网上阅读了其他人的一些帖子,这些帖子也发现了与范围滑块的 JQM 初始化相关的一些问题(例如这里:http://css.dzone.com/articles/knockoutjs-binding-helper 和这里:http://www.programico.com/1/post/2012/12/knockoutjs-jquerymobile-slider.html)并提供了一个可行的解决方案,每个都有他自己的自定义绑定实现。
其中之一,如下(by http://www.hughanderson.com/):
data-bind="value: quantity, slider: quantity"
到目前为止,一切都很好。之后,我遇到了这个问题:
如果 JQM 滑块在第一页上,它可以工作。当 JQM 滑块在第二页上时,不再工作。
我认为这是与这个特别的 JQM 小部件和他的 DOM 操作有关的问题,我可以理解。为了更好地解释这一点,我制作了两个 jsFiddle,我只是交换了两个 JQM 页面的顺序:
-
不工作:http://jsfiddle.net/5q38Q/ 第二个 JQM 页面上的滑块
工作:http://jsfiddle.net/5q38Q/1/ 第一个 JQM 页面上的滑块
谁能解释一下,为 JQM 滑块初始化敲除绑定的正确方法是什么?也许还有另一种方法可以为 JQM 滑块编写自定义绑定,或者将敲除绑定放在 pagebeforeshow 事件中?
更新: 通过以下更改,滑块显示正确的值,并且还与文本输入部分同步:
$(document).on('pagebeforeshow', '#slider-page', function()
$('#quantity-slider').val(viewModel.quantity());
$('#quantity-slider').slider('refresh');
);
但我想知道是否没有更好的解决方案。
至少,连同 Varun 的自定义绑定,它现在对我来说效果很好!
【问题讨论】:
【参考方案1】:我遇到了同样的问题。这就是我解决它的方法。尽管当您直接使用文本输入编辑值时,此解决方案不会更新可观察值。 (我不显示输入文本框,所以这个方案对我来说足够了)
http://jsfiddle.net/WMr8D/9/
$(document).ready(function ()
var ViewModel = function ()
var self = this;
self.quantity = ko.observable(4);
;
ko.bindingHandlers.slider =
init: function (element, valueAccessor)
var value = valueAccessor();
$(document).on(
"mouseup touchend keypress": function (elem)
value($('#' + element.id).val());
, ".c-slider");
;
ko.applyBindings(new ViewModel());
);
【讨论】:
嗨 Varun,非常感谢您分享您的经验和工作。但是当我尝试您的示例时,我总是看到同样的问题,当我转到第二页时,滑块未初始化为 4。所以问题是为什么会发生这种情况? 我在这里阅读了您关于此问题的另一篇文章:***.com/a/16493161/2308978 对我来说,唯一有效的自定义绑定是您的! 嗨 Varun 我直接使用 ui-slider 选择器更改了代码,没有 c-slider 包装器,它也运行良好。您能否更新您的答案,并解释为什么您需要“ko if: is”?没有它,它也对我有用。如果您能更好地解释您在这个有争议的问题上的经历,那就太好了。 If 条件是模拟后面添加的控件。在您的情况下,因为您正在导航页面,所以控件是由 jqm 动态添加的。我想在没有多个页面的情况下做同样的事情:)【参考方案2】:在花了几个小时测试网上找到的关于这个问题的所有变体后,我最终得到了以下解决方案,也许这有助于其他人腾出时间:
最终的工作小提琴: http://jsfiddle.net/CT7fy/
问题是关于如何将 knockout.js 和 JQuery Mobile 滑块与多页导航集成在一起,我认为这将是最常见的情况之一。
很抱歉,我不能认为 Varun 的回答是完整且令人满意的,但我必须说,如果没有 Varun 的自定义绑定处理程序,我将永远找不到可行的解决方案。
这是自定义绑定处理程序,稍作修改:
/* custom binding handler thanks to Varun http://***.com/a/16493161/2308978 */
ko.bindingHandlers.slider =
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext)
var value = valueAccessor();
$(document).on(
"mouseup touchend keypress": function (elem)
var sliderVal = $('#' + element.id).val();
value(sliderVal);
, ".ui-slider");
;
...这是页面初始化:
$(document).on('pagebeforeshow', '#slider-page', function()
$('#quantity-slider').val(viewModel.quantity());
$('#quantity-slider').slider('refresh');
);
在您按下 enter 或 tab 后,滑块的文本部分也会同步,因为这是标准的滑块行为。
【讨论】:
【参考方案3】:在自定义处理程序中,绑定到“更改”事件比绑定到 mouseup touchend 和 keypress 更可靠。也不需要 pagebeforeshow 事件。您可以在处理程序的 init 期间设置 value 属性:
ko.bindingHandlers.slider =
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext)
var value = valueAccessor();
$(element).attr("value", value());
$(document).on(
"change": function (elem)
var sliderVal = $('#' + element.id).val();
value(sliderVal);
, ".ui-slider");
;
查看示例:http://jsfiddle.net/ZbrB7/2483/
【讨论】:
以上是关于如何使用 knockout.js 正确绑定和初始化 jQuery Mobile 范围滑块?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 knockout.js 数据绑定对数组进行分组和读取:使用