【问题标题】:Knockout, noUiSlider, custom bindings淘汰赛,noUiSlider,自定义绑定
【发布时间】:2015-11-03 19:26:41
【问题描述】:

我正在尝试将淘汰赛和 noUiSlider 与自定义绑定相结合。我为 jQuery-UI 滑块和 Knockout 找到了类似的代码,并以此为基础。

如果我使用下面的 sliderko 自定义绑定,noUisliders 不会更新 observables。我得到 NaN,输入字段中没有任何内容。

如果我直接使用下面的滑块自定义绑定和 noUiSlider 事件,那么一切正常。滑块自定义绑定表现不佳,可能是由于跟踪 noUiSlider 更新事件。但是,这是我弄清楚如何让滑块不断更新输入字段的唯一方法。

我想使用 Knockout 的 registerEventHandler,但我不知道如何让它工作。

// noUiSlider
ko.bindingHandlers.slider = {
  init: function(element, valueAccessor, allBindingsAccessor) {
    var options = allBindingsAccessor().sliderOptions || {};
    noUiSlider.create(element, options);

    // works with with noUiSlider but not with knockout event bindings
    element.noUiSlider.on('set', function(values, handle) {
      var observable = valueAccessor();
      observable(values[handle]);
    });

    // works with with noUiSlider but not with knockout event bindings
    element.noUiSlider.on('update', function(values, handle) {
      var observable = valueAccessor();
      observable(values[handle]);
    });

    ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
      element.noUiSlider.destroy();
    });
  },
  update: function(element, valueAccessor) {
    var value = ko.utils.unwrapObservable(valueAccessor());
    element.noUiSlider.set(value);

  }
};

// using knockout event handlers
ko.bindingHandlers.sliderko = {
  init: function(element, valueAccessor, allBindingsAccessor) {
    var options = allBindingsAccessor().sliderOptions || {};
    noUiSlider.create(element, options);

    ko.utils.registerEventHandler(element, 'set', function(values, handle) {
      var observable = valueAccessor();
      observable(values[handle]);
    });

    ko.utils.registerEventHandler(element, 'update', function(values, handle) {
      var observable = valueAccessor();
      observable(values[handle]);
    });

    ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
      element.noUiSlider.destroy();
    });
  },
  update: function(element, valueAccessor) {
    var value = ko.utils.unwrapObservable(valueAccessor());
    element.noUiSlider.set(value);

  }
};

// initialization for NoUiSlider - saves from adding stuff into page
var sillysv = {
  start: [10],
  step: 0.01,
  range: {
    'min': 0,
    'max': 100
  }
};

var sillysp = {
  start: [5],
  step: 0.01,
  range: {
    'min': 0,
    'max': 100
  }
};

var ViewModel = function() {
  var self = this;
  self.savings = ko.observable();
  self.spent = ko.observable();
  self.net = ko.computed(function() {
    return self.savings() - self.spent();
  });
};

ko.applyBindings(new ViewModel());
<link href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/8.1.0/nouislider.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/8.1.0/nouislider.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h2>Slider Demo</h2>
Savings:
<input data-bind="value: savings" />
<div style="margin: 10px" data-bind="slider: savings, sliderOptions: sillysv"></div>

Spent:
<input data-bind="value: spent" />
<div style="margin: 10px" data-bind="slider: spent, sliderOptions: sillysp"></div>

Net: <span data-bind="text: net"></span>

【问题讨论】:

    标签: knockout.js nouislider


    【解决方案1】:

    如果您使用 jQuery,那么使用 jQuery 或 ko registerEventHandler 绑定事件之间没有区别。此函数供内部使用,并且能够使绑定在不同的浏览器中正常工作。如果 jQuery 可用,则此函数使用 jQuery 绑定。

    第二个问题,多次更新 observable,应该通过限制 observable 中的 upsated 来解决。您可以直接在您的视图模型中使用rateLimit ko extender

    var ViewModel = function() {
      var self = this;
      self.savings = ko.observable()
        .extend({ rateLimit: { method: "notifyWhenChangesStop", timeout: 400 } });;
      self.spent = ko.observable()
        .extend({ rateLimit: { method: "notifyWhenChangesStop", timeout: 400 } });;
      self.net = ko.computed(function() {
         return self.savings() - self.spent();
    }
    

    如果你想扩展 init 中的 observables,你也可以修改自定义绑定。如果这样做,您应该检查 observable 是否尚未扩展:Check if extension was applied to observable

    【讨论】:

    • 这是正确的想法,但它违背了绑定的反馈目的。我将在下面发布一些我发现有效的东西。请注意,我是一个 JavaScript 菜鸟(主要是基础设施和服务器编程)。
    • 不,如果您选择正确的超时,它根本不会破坏反馈:您可以选择足够高的超时以避免性能问题,并且足够低以被用户感知。如果 400ms 太高,你可以把数字降低到 100ms,或者 50ms,甚至 20ms。无论您选择哪个数字,栏都会平稳移动,用户将无法以如此高的速度阅读文本中的所有更改或任何其他绑定。请在丢弃解决方案之前对其进行测试。不过,我真的很想看看您找到的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-13
    • 2014-03-07
    • 1970-01-01
    相关资源
    最近更新 更多