15

我希望能够将单击事件和双击事件绑定到一段文本。我知道我可以使用

data-bind ="event: { dblclick: doSomething }

双击,但我还需要能够在单击时执行不同的功能。有什么建议么?

4

5 回答 5

26
<div data-bind="singleClick: clicked, event : { dblclick: double }">
    Click Me
</div>

这将过滤掉也是双击的单击。

ko.bindingHandlers.singleClick= {
    init: function(element, valueAccessor) {
        var handler = valueAccessor(),
            delay = 200,
            clickTimeout = false;

        $(element).click(function() {
            if(clickTimeout !== false) {
                clearTimeout(clickTimeout);
                clickTimeout = false;
            } else {        
                clickTimeout = setTimeout(function() {
                    clickTimeout = false;
                    handler();
                }, delay);
            }
        });
    }
};

是一个演示。

于 2012-06-13T18:25:21.203 回答
12

上面的答案非常有帮助,但没有给出我认为 OP 所追求的确切解决方案:一个简单的 Knockout 绑定,允许独占单击和双击事件。我知道这篇文章是一年前的,但是我在今天想做同样的事情时发现了这篇文章,所以我发帖以防这个答案对其他人有用。

下面的示例似乎符合 OPs 要求,并且可以节省一些时间(免责声明:有限的跨浏览器测试)。JSFiddle:http: //jsfiddle.net/UxRNy/

此外,还有关于您是否应该首先使用它的问题(移动浏览器、减慢页面速度、可访问性等) - 但这是另一篇文章(例如https://ux.stackexchange.com/questions/7400 /应该双击避免在网络应用程序中

示例视图用法:

<div data-bind="singleOrDoubleClick: { click: singleClick, dblclick: doubleClick }">
    Click or double click me...
</div>

捆绑:

ko.bindingHandlers.singleOrDoubleClick= {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var singleHandler   = valueAccessor().click,
            doubleHandler   = valueAccessor().dblclick,
            delay           = valueAccessor().delay || 200,
            clicks          = 0;

        $(element).click(function(event) {
            clicks++;
            if (clicks === 1) {
                setTimeout(function() {
                    if( clicks === 1 ) {
                        // Call the single click handler - passing viewModel as this 'this' object
                        // you may want to pass 'this' explicitly
                        if (singleHandler !== undefined) { 
                            singleHandler.call(viewModel, bindingContext.$data, event); 
                        }
                    } else {
                        // Call the double click handler - passing viewModel as this 'this' object
                        // you may want to pass 'this' explicitly
                        if (doubleHandler !== undefined) { 
                            doubleHandler.call(viewModel, bindingContext.$data, event); 
                        }
                    }
                    clicks = 0;
                }, delay);
            }
        });
    }
};

以上是上面的例子和这里的例子的组合:https ://gist.github.com/ncr/399624 - 我刚刚合并了这两个解决方案。

于 2014-05-29T03:31:34.767 回答
5

@madcapnmckay 提供了一个很好的答案,下面是使用相同想法提供双击的修改版本。并且通过使用最新版本的淘汰赛,虚拟机作为上下文传递给处理程序。这可以通过单击同时工作。

<div data-bind="doubleClick: clicked">
    Double click Me
</div>

--

ko.bindingHandlers.doubleClick= {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var handler = valueAccessor(),
            delay = 200,
            clickTimeout = false;

        $(element).click(function() {
            if(clickTimeout !== false) {
                handler.call(viewModel);
                clickTimeout = false;
            } else {        
                clickTimeout = setTimeout(function() {
                    clickTimeout = false;
                }, delay);
            }
        });
    }
};
于 2013-10-15T21:37:13.367 回答
4

首先,我根本不建议click绑定。相反,您应该使用jQuery 中的"click"和处理程序:"dblclick"

$(someParentElement).on('click', 'your span selector', function (event) {
    var myViewModelFragment = ko.dataFor(this);
    // your code here
});

$(someParentElement).on('dblclick', 'your span selector', function (event) {
    var myViewModelFragment = ko.dataFor(this);
    // your code here
});

编辑:另请参阅Niko关于支持单击和双击的建议。基本上,您应该手动计算点击次数并相应地调用不同的函数。我假设 jQuery 会为你处理这个问题,但不幸的是,它没有。

于 2012-06-13T15:57:40.100 回答
0

这是我对该问题的编程解决方案:

var ViewModel = function() {
  var self = this;
  this.onSingleClick = function() {
    self.lastTimeClicked = undefined;
    console.log('Single click');
  };

  this.onDoubleClick = function() {
    console.log('Double click');
  };

  this.timeoutID = undefined;

  this.lastTimeClicked = undefined;
  this.clickDelay = 500;
  this.clickedParagraph = function(viewModel, mouseEvent) {
    var currentTime = new Date().getTime();
    var timeBetweenClicks = currentTime - (viewModel.lastTimeClicked || currentTime);
    var timeToReceiveSecondClick = viewModel.clickDelay - timeBetweenClicks;

    if (timeBetweenClicks > 0 && timeBetweenClicks < viewModel.clickDelay) {
      window.clearTimeout(viewModel.timeoutID); // Interrupt "onSingleClick"
      viewModel.lastTimeClicked = undefined;
      viewModel.onDoubleClick();
    } else {
      viewModel.lastTimeClicked = currentTime;
      viewModel.timeoutID = window.setTimeout(viewModel.onSingleClick, timeToReceiveSecondClick);
    }
  };
};

ko.applyBindings(new ViewModel(), document.getElementById("myParagraph"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script>
<p id="myParagraph" data-bind="click: clickedParagraph">Click me</p>

每个“双击”都是通过两次单击创建的。如果有“双击”,我们必须确保第一次单击的事件处理程序不会被执行(这就是我使用window.setTimeout&的原因window.clearTimeout)。在设置计时器时,我们还必须考虑到第一次单击元素可能已经是双击。

在我的代码中,我将其设置clickDelay为 500 毫秒。所以500ms内的两次点击被识别为“双击”。你也可以增加这个值来测试我的clickedParagraph函数的行为。

于 2016-08-10T10:01:54.290 回答