data-bind ="event: { dblclick: doSomething }
我需要实现双击事件,但同时也需要在单击事件上执行不同的功能。有什么建议?
data-bind ="event: { dblclick: doSomething }
我需要实现双击事件,但同时也需要在单击事件上执行不同的功能。有什么建议?
<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);
}
});
}
};
这里有一个演示。
以上答案非常有帮助,但没有给出我认为OP想要的确切解决方案:一种简单的Knockout绑定,允许独占单击和双击事件。我知道这篇文章已经是一年前的,但今天在寻找相同的东西时发现了它,因此我发布了这个答案以防对他人有用。
以下示例似乎符合OP的要求,并可能为某人节省时间(免责声明:有限的跨浏览器测试)。 JSFiddle:http://jsfiddle.net/UxRNy/
此外,还有一些问题,例如是否应首先使用它(移动浏览器,减慢页面速度,可访问性等)- 但这是另一个帖子(例如https://ux.stackexchange.com/questions/7400/should-double-click-be-avoided-in-web-applications)
示例视图用法:
<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结合而成的 - 我只是合并了两个解决方案。
@madcapnmckay提供了一个很好的答案,下面是一个修改后的版本,使用相同的思路来提供双击功能。通过使用最新版本的knockout,vm作为上下文传递给处理程序。这可以与单击同时工作。
<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);
}
});
}
};
$(element).click(function() {
更改为 $(element).click(function(e) {
请注意e,然后将 handler.call(viewModel);
更改为 handler.call(this, bindingContext.$data, e);
从KO 3.0开始, bindingContext.$data
是KO首选的方式,可以参考这里。 - Grandizer首先,我不建议完全使用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会为您处理这个问题,但不幸的是,它没有。
onclick
属性。它直接将事件处理程序附加到元素上。这有两个问题。首先,如果你有许多这样的元素,你最终会得到许多处理程序。JS运行时必须单独优化它们,并增加内存使用量。其次,如果你通过Knockout click
将处理程序附加到某个元素上,而该元素具有带有_live_ click
事件的子元素,则ko-click将遮盖live-click。Live click不会被调用,你将无法获得正确的行为。 - Andrei Андрей Листочкин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毫秒。因此,在500毫秒内进行两次点击将被识别为“双击”。您也可以增加此值以测试我的clickedParagraph
函数的行为。