【问题标题】:A custom bindingHandler's return value/observable自定义 bindingHandler 的返回值/observable
【发布时间】:2015-06-01 19:35:28
【问题描述】:

我还没有找到解决办法。

我正在尝试为 html 元素 div 标记上的单击事件创建自定义 bindingHandler。

// custom bindingHandler and observable
<div data-bind="OnClickEvent: HasBeenClicked"></div>
// to show observable's true/false value
<span data-bind="text: 'Observable: ' + HasBeenClicked()"></span>

这个 bindingHandler 做了它应该做的事情,如果你点击 div 文本将会改变。但是,observable 会说 if false

ko.bindingHandlers.OnClickEvent = {
    update: function (element, valueAccessor) {

        $(element).text('Click Here: false');

        var observable = ko.utils.unwrapObservable(valueAccessor());

        $(element).on('click', function () {

            observable = !observable;

            if (observable) {
                $(element).text('Click Here: true');
            } else {
                $(element).text('Click Here: false');
            }
        });
    }
}


function ViewModel() {
    var self = this;
    self.HasBeenClicked = ko.observable(false);
}

ko.applyBindings(new ViewModel());

如何设置可观察的 HasBeenClicked 以在每次点击时在真/假之间切换,就像文本一样?

【问题讨论】:

  • 你没有将新值写回你的 observable。所以你需要valueAccessor() 来做到这一点:observable = !observable; valueAccessor()(observable);。但是,您的自定义绑定非常奇怪且有问题。例如,对于每个可观察到的更改,它都会一次又一次地订阅点击事件......你想用这个绑定实现什么?
  • 我知道它很奇怪,它是为了看看我如何在点击时更改可观察的。最终,我将使用引导 glyphicons 使它看起来像一个花哨的复选框。但是,添加您建议的代码位不会更改可观察的。谢谢@nemesv

标签: knockout.js


【解决方案1】:

我第二次@nemesv 对快速修复的评论以及您的绑定看起来有点奇怪的事实。因为我需要房间,所以我将其扩展为答案。

首先,快速修复:

  • 我认为对于您正在编写的绑定类型,在 init 部分内完成您的工作更合适;
  • 你需要写回valueAccessor来改变observable的值(我在下面展示了一个又快又脏的demo);

这是一个工作示例:

ko.bindingHandlers.OnClickEvent = {
    init: function (element, valueAccessor) {

        $(element).text('Click Here: false');

        var observable = ko.utils.unwrapObservable(valueAccessor());
        
        $(element).on('click', function () {
            observable = !observable;
            
            valueAccessor()(observable);

            if (observable) {
                $(element).text('Click Here: true');
            } else {
                $(element).text('Click Here: false');
            }
        });
    }
}

function ViewModel() {
    var self = this;
    self.HasBeenClicked = ko.observable(false);
}

ko.applyBindings(new ViewModel());
div { padding: 10px; background-color: pink; margin-bottom: 10px; cursor: pointer; }
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<div data-bind="OnClickEvent: HasBeenClicked"></div>
<span data-bind="text: 'Observable: ' + HasBeenClicked()"></span>

但是,我认为这种 jQuery、事件处理和 Knockout 的混合是相当不确定的。您应该考虑您是否遇到 XY 问题,以及您是否无法使用现有的绑定处理程序解决您的需求。这是做类似事情的一种方法:

function ViewModel() {
    var self = this;
    self.HasBeenClicked = ko.observable(false);
    self.handleClick = function() {
      self.HasBeenClicked(!self.HasBeenClicked());
    };
}

ko.applyBindings(new ViewModel());
div { padding: 10px; background-color: pink; margin-bottom: 10px; cursor: pointer; }
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<div data-bind="click: handleClick, text: 'Click here: ' + HasBeenClicked()"></div>
<span data-bind="text: 'Observable: ' + HasBeenClicked()"></span>

谈到现有的绑定处理程序,知道有the click binding 可能适合您的需求。如果没有,我建议您查看相关来源(click 重定向到 event 绑定,请参阅 this file in GitHub),为您自己的处理程序汲取灵感。

【讨论】:

  • 谢谢@Jeroen & nemesv,我知道这很奇怪,但我很好奇淘汰赛设置可观察值的方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-09
  • 2018-04-02
  • 1970-01-01
相关资源
最近更新 更多