如何使用knockout.js在特定条件下将click事件绑定到body?

时间:2014-11-27 00:09:44

标签: javascript html knockout.js

我设计了一个下拉菜单(试图在浏览器中一致地设置实际<select>元素的样式)是徒劳的,点击后会显示一个无序的下拉选项列表。此功能由Knockout.js提供,它使用observable来检查是否应显示或隐藏下拉列表。 DOM结构在这里:

<div id="actionsDropdown">
  <a data-bind="click: toggleDropdownVisibility, css: { active: showDropdown() == true }">Actions</a>
    <ul data-bind="visible: showDropdown">
      <li>Option 1</li>
      <li>Option 2</li>
    </ul>
</div>

这是我的Knockout.js代码:

self.showDropdown = ko.observable(false);
self.toggleDropdownVisibility = function () {
    console.log(self.showDropdown());
    self.showDropdown(!self.showDropdown());
};

除了一些事情之外,这很有效。

如果下拉菜单已经显示,如何点击页面上的其他位置时,如何实施逻辑以隐藏下拉列表?

猜测我可以将点击处理程序绑定到body元素,但如果它被关闭则打开它,这显然不是最佳的。

1 个答案:

答案 0 :(得分:1)

见这个jsfiddle:

http://jsfiddle.net/dwp0etrg/9/

我刚刚创建了一个快速的自定义绑定处理程序,它接受showDropdown并向文档添加一个事件监听器。当showDropdown为true时,它会绑定侦听器,当它为false时,它会将其删除。

ko.bindingHandlers.dropdown = {
    update: function (element, valueAccessor) {
        var value = valueAccessor();
        var valueUnwrapped = ko.unwrap(value);
        if (valueUnwrapped) {
            $(document).on('click.dropdown', function (e) {
                var $target = $(e.target);
                if ($target.parents('#actionsDropdown').length === 0) {
                    value(false);
                }
            });
        } else {
            $(document).off('click.dropdown');
        }
    }
};

只需更改模板即可使用绑定并将其传递给showDropdown observable。

<div id="actionsDropdown"> 
    <a data-bind="dropdown: showDropdown, 
                  click: toggleDropdownVisibility,
                  css: { active: showDropdown() == true }">Actions</a>

    <ul data-bind="visible: showDropdown">
        <li>Option 1</li>
        <li>Option 2</li>
    </ul>
</div>