【问题标题】:Knockout.JS - Run function when clicking outside of divKnockout.JS - 在 div 外部单击时运行函数
【发布时间】:2017-07-23 00:57:54
【问题描述】:

我正在尝试使用敲除在 div 外部单击时执行一个函数。我试图通过使用带有模糊的事件绑定来做到这一点。我想我很接近了,我只需要一点帮助。

filterFromList 函数工作正常。

相关JS

self.filterFromList = function (item) {
    self.selectedName(item.name);
    self.location().forEach(function(place) {
        if (place.name === self.selectedName()) {
            place.showLocation(true);
            place.marker.setVisible(true);
        } else {
            place.showLocation(false);
            place.marker.setVisible(false);
        }
    });
};

self.unfilter = function (item) {
    console.log("blurring");
    self.location().forEach(function (place) {
        place.showLocation(true);
        place.marker.setVisible(true);
    })
};

相关 HTML

<ul data-bind="foreach: location">
<a class="location-click" data-bind="click: $parent.filterFromList, event: { blur: $parent.unfilter }">
    <li class="location-block" data-bind="visible: showLocation">
        <img class="location-img" data-bind="attr: {src: imgURL}" />
        <h4 data-bind="text: name"></h4>
        <hr>
    </li>
</a>
</ul>

【问题讨论】:

  • 当您说“在 div 外部单击时”指的是什么 div?是在你的
      周围吗?
  • 我还想知道您为什么要这样做 - 除了具有过滤器角色的按钮之外,单击几乎任何地方来清除过滤器都是用户友好的。即使单击“详细信息”按钮或链接或类似的东西也会删除过滤器。只需添加一个清除过滤器按钮或在现有按钮上实现切换。

标签: javascript html knockout.js


【解决方案1】:

您可以使用自定义 bindingHandler (fiddle):

ko.bindingHandlers.clickOutside = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    var fn = ko.utils.unwrapObservable(valueAccessor());

    $('html').on('click', function(e) {
      if (!($.contains(element, e.target) || element === e.target)) {
        fn();
      }
    });
  },
}

var vm = {
  clickOutside: function(msg) {
    console.log(msg);
  }
};

ko.applyBindings(vm);

HTML:

<div style="background-color:green;">
  Outside area
  <div data-bind="clickOutside: clickOutside.bind($data, 'clicked outside of red div')" style="background-color:red;">
  inside area
  <ul>
    <li><a href="#">Link 1</a></li>
    <li><a href="#">Link 2</a></li>
    <li><a href="#">Link 3</a></li>
  </ul>
</div>

基本上,这个想法是您将事件侦听器添加到可能的最外层元素 (&lt;html&gt;),并检查点击目标是直接还是间接位于所需容器内 ($.contains(what contains, what is contained))。如果是,则什么都不做,如果不是,则调用绑定函数。

【讨论】:

    【解决方案2】:

    通过将 tabindex 属性添加到有问题的 div 来解决问题。感谢您的帮助!

    <a class="location-click" tabindex="0" data-bind="click: $parent.filterFromList, event: { blur: $parent.unfilter } ">
                <li class="location-block" data-bind="visible: showLocation">
                    <img class="location-img" data-bind="attr: {src: imgURL}"></img>
                    <h4 data-bind="text: name"></h4>
                    <hr>
                </li>
    </a>
    

    【讨论】:

      【解决方案3】:

      注意不要像 (if 和 with ) 这样的敲除绑定起作用 第一次显示元素容器初始化顺利,如果再次隐藏并显示,单击外部不再起作用

      ,改为使用:

       ko.bindingHandlers.clickOutside = {
              init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
                  var fn = ko.utils.unwrapObservable(valueAccessor().fn);
                  var uid = ko.utils.unwrapObservable(valueAccessor().uid);
                  $('html').on('click', function (e) {
                      if ($(e.target).parents('.' + uid).length === 0) {
                          fn();
                      }
                  });
              },
          }
      

      为父级分配一个 UID,然后使用 'with' 和 'if' 绑定

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-17
        • 1970-01-01
        • 2011-09-20
        • 2013-04-18
        • 1970-01-01
        • 2020-01-01
        • 1970-01-01
        相关资源
        最近更新 更多