input的blur 事件触发, 如何区分click了list还是其他元素

1.点击list中内容,input的blur会先触发,导致list消失,导致list的click事件无法触发。

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    * {
      box-sizing: border-box;
    }
    .container {
      position: relative;
      width: 100px;
    }
    .container input {
      width: 100%;
    }
    .list {
      position: absolute;
      width: 100%;
      display: none;
      border: 1px solid #9DC2E6;
    }
    .list div:hover {
      background-color: #C1F5B0;
      cursor: pointer;
    }
  </style>
</head>

<body>
  <!--[if lt IE 7]>
      <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
    <![endif]-->
  <div class="container">
    <input list="cars" />
    <datalist id="cars">
      <option value="BMW">test</option>
      <option value="Ford"></option>
      <option value="Volvo"></option>
    </datalist>
  </div>
  <div class="container">
    <input name="text" bind="text">
    <div class="list"></div>
  </div>
  <script>
    function asyncList(dom, goodArr, filter) {
      function getDisplayHtml(str) {
        return ['<div>', str, '</div>'].join('');
      }

      const selectedArr = goodArr.filter(function (item) {
        return item.includes(filter) ? true : false;
      });

      dom.innerHTML = selectedArr.reduce(function (prev, item) {
        return prev.concat([getDisplayHtml(item)]);
      }, []).join('');
    }

    function setDisplay(dom, display) {
      display ? dom.style.display = 'block' : dom.style.display = 'none';
    }


    const goodArr = ['a', 'abc', 'ddff'];
    const input = document.querySelector('input[name=text]');
    const list = document.querySelector('.list');

    input.addEventListener('input', function () {
      asyncList(list, goodArr, input.value);
    });
    input.addEventListener('blur', function (e) {
      // console.log(e.target);

      setDisplay(list, false);
    });
    input.addEventListener('focus', function () {
      asyncList(list, goodArr, input.value);
      setDisplay(list, true);
    });

    list.addEventListener('click', function(e) {
      const node = e.target;
      if(node !== e.currentTarget) {
        input.value = node.textContent;
      }
    });
  </script>

</body>

</html>
阅读 2.7k
1 个回答

这里看上去是要做一个下拉菜单对吧?
下拉菜单隐藏下拉列表可以换一种方式实现,这样就可以避免这个问题。
在window上监听click事件,出发后将菜单隐藏。当然,这个时候就要考虑点击的是菜单还是其他的位置,这个也很容易处理,有两种办法:
1是在菜单的dom上stoppropagation,这样菜单上面的点击事件就不会触发window上的回调
2是搞一个状态变量,当鼠标进入(mouseenter)的时候置为true,鼠标离开(mouseleave)的时候置为false,在window上监听的那个函数里面根据这个状态变量决定是否执行回调

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题