基于jquery的可多选的下拉列表框

这里是基于jQuery的可多选下拉列表框实现攻略。

实现思路

  • 使用jQuery作为主要框架,便于操作DOM元素;
  • 首先隐藏原生的下拉列表框,然后在它的位置上添加一个自定义的下拉框,用于显示选中的选项;
  • 给自定义下拉框添加打开和关闭事件,分别显示和隐藏下拉选项,用输入框实现搜索功能;
  • 在下拉列表中添加复选框,并为每个复选框绑定点击事件,点击时更新自定义下拉框中展示的选项,同时判断选项是否超出最大选项限制。

代码实现

下面就是具体的代码实现,先介绍HTML部分,包含了原生下拉列表和自定义下拉列表:

<!-- 原生下拉列表 -->
<select name="multi-select" multiple id="multi-select" style="display: none;">
  <option value="1">选项1</option>
  <option value="2">选项2</option>
  <option value="3">选项3</option>
  <option value="4">选项4</option>
  <option value="5">选项5</option>
  <option value="6">选项6</option>
</select>

<!-- 自定义下拉列表 -->
<div class="multi-select-box">
  <input type="text" class="multi-select-search" placeholder="请输入关键词">
  <span class="multi-select-tags"></span>
  <div class="multi-select-options">
    <ul>
      <li><label><input type="checkbox" value="1"> 选项1</label></li>
      <li><label><input type="checkbox" value="2"> 选项2</label></li>
      <li><label><input type="checkbox" value="3"> 选项3</label></li>
      <li><label><input type="checkbox" value="4"> 选项4</label></li>
      <li><label><input type="checkbox" value="5"> 选项5</label></li>
      <li><label><input type="checkbox" value="6"> 选项6</label></li>
    </ul>
  </div>
</div>

接着是CSS样式部分,包含了下拉列表的样式以及自定义下拉框的样式:

/* 原生下拉框隐藏 */
select { display: none; }

/* 自定义下拉框样式 */
.multi-select-box {
  position: relative;
  display: inline-block;
}
.multi-select-box input {
  display: inline-block;
  width: 100px;
  padding: 2px 10px;
  border: 1px solid #aaa;
  border-radius: 3px;
  font-size: 14px;
  outline: none;
}
.multi-select-box .multi-select-tags {
  position: absolute;
  left: 0;
  top: 30px;
  display: inline-block;
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 3px 10px;
  background-color: #fff;
  border: 1px solid #aaa;
  border-radius: 3px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .1);
  z-index: 10;
}
.multi-select-box .multi-select-options {
  position: absolute;
  left: 0;
  top: 34px;
  display: none;
  max-height: 200px;
  overflow-y: auto;
  background-color: #fff;
  border: 1px solid #aaa;
  border-radius: 3px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .1);
  z-index: 10;
}
.multi-select-box .multi-select-options ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
.multi-select-box .multi-select-options li {
  height: 30px;
  line-height: 30px;
  padding: 0 10px;
  cursor: pointer;
}
.multi-select-box .multi-select-options li:hover {
  background-color: #f5f5f5;
}
.multi-select-box .multi-select-options input[type="checkbox"] {
  margin-right: 5px;
  vertical-align: middle;
}

最后是JavaScript部分,包含了下拉框的初始化、事件绑定和选项更新:

$(function() {
  // 初始化,将选中的选项添加到自定义下拉框中展示
  $('#multi-select option:selected').each(function() {
    var value = $(this).val();
    var text = $(this).text();
    var tagHtml = '<span data-value="' + value + '">' + text + '<i class="fa fa-times"></i></span>';
    $('.multi-select-tags').append(tagHtml);
  });

  // 点击文本框或已选标签时打开下拉选项
  $('.multi-select-box input, .multi-select-tags').click(function() {
    $('.multi-select-options').show();
  });

  // 点击其他地方时关闭下拉选项
  $(document).click(function(event) {
    if (!$(event.target).closest('.multi-select-box').length) {
      $('.multi-select-options').hide();
    }
  });

  // 输入框关键词改变时过滤选项
  $('.multi-select-search').keyup(function() {
    var keyword = $.trim($(this).val()).toLowerCase();
    $('.multi-select-options input[type="checkbox"]').each(function() {
      $(this).parent().parent().toggle($(this).next().text().toLowerCase().indexOf(keyword) > -1);
    });
  });

  // 点击复选框时更新选中标签
  $('.multi-select-options input[type="checkbox"]').click(function() {
    var $selectedTags = $('.multi-select-tags span');
    var $thisTag = $(this).parent().parent();
    var selectedCount = $selectedTags.length;
    var maxCount = 3; // 最多选3个

    if ($(this).is(':checked')) { // 新增选中标签
      if (selectedCount < maxCount) {
        var value = $(this).val();
        var text = $(this).next().text();
        var tagHtml = '<span data-value="' + value + '">' + text + '<i class="fa fa-times"></i></span>';
        $('.multi-select-tags').append(tagHtml);
      } else {
        $(this).prop('checked', false);
        alert('最多只能选' + maxCount + '个选项!');
      }
    } else { // 取消选中标签
      var value = $(this).val();
      $selectedTags.filter('[data-value="' + value + '"]').remove();
    }

    // 更新原生下拉列表、自定义下拉框的选中状态
    var selectedValues = [];
    $selectedTags.each(function() {
      selectedValues.push($(this).data('value'));
    });
    $('#multi-select option').prop('selected', false).filter('[value="' + selectedValues.join('"],[value="') + '"]').prop('selected', true);
    var tagsHtml = $selectedTags.length > 0 ? $selectedTags.clone().children('i').remove().end().html() : '请选择';
    $('.multi-select-box .multi-select-tags').html(tagsHtml);
    $selectedTags.hide();
  });

  // 点击标签右侧的删除图标时取消选中标签
  $('.multi-select-tags').on('click', 'span i', function() {
    var value = $(this).parent().data('value');
    $('.multi-select-options input[type="checkbox"]').filter('[value="' + value + '"]').prop('checked', false);
    $(this).parent().remove();
  });
});

示例演示

以下是两个具体的示例演示:

示例一

这个下拉框最多可以选择3个选项,如果选中了3个选项,在添加选项时会提示:"最多只能选3个选项!"。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>多选下拉框(示例一)</title>
  <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/font-awesome/5.15.4/css/all.min.css">
  <style>
    /* 原生下拉框隐藏 */
    select { display: none; }
    /* 自定义下拉框样式 */
    .multi-select-box {
      position: relative;
      display: inline-block;
    }
    .multi-select-box input {
      display: inline-block;
      width: 100px;
      padding: 2px 10px;
      border: 1px solid #aaa;
      border-radius: 3px;
      font-size: 14px;
      outline: none;
    }
    .multi-select-box .multi-select-tags {
      position: absolute;
      left: 0;
      top: 30px;
      display: inline-block;
      max-width: 160px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      padding: 3px 10px;
      background-color: #fff;
      border: 1px solid #aaa;
      border-radius: 3px;
      box-shadow: 0 2px 4px rgba(0, 0, 0, .1);
      z-index: 10;
    }
    .multi-select-box .multi-select-options {
      position: absolute;
      left: 0;
      top: 34px;
      display: none;
      max-height: 200px;
      overflow-y: auto;
      background-color: #fff;
      border: 1px solid #aaa;
      border-radius: 3px;
      box-shadow: 0 2px 4px rgba(0, 0, 0, .1);
      z-index: 10;
    }
    .multi-select-box .multi-select-options ul {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .multi-select-box .multi-select-options li {
      height: 30px;
      line-height: 30px;
      padding: 0 10px;
      cursor: pointer;
    }
    .multi-select-box .multi-select-options li:hover {
      background-color: #f5f5f5;
    }
    .multi-select-box .multi-select-options input[type="checkbox"] {
      margin-right: 5px;
      vertical-align: middle;
    }
  </style>
</head>
<body>
  <!-- 原生下拉列表 -->
  <select name="multi-select" multiple id="multi-select" style="display: none;">
    <option value="1">选项1</option>
    <option value="2">选项2</option>
    <option value="3">选项3</option>
    <option value="4">选项4</option>
    <option value="5">选项5</option>
    <option value="6">选项6</option>
  </select>

  <!-- 自定义下拉列表 -->
  <div class="multi-select-box">
    <input type="text" class="multi-select-search" placeholder="请输入关键词">
    <span class="multi-select-tags"></span>
    <div class="multi-select-options">
      <ul>
        <li><label><input type="checkbox" value="1"> 选项1</label></li>
        <li><label><input type="checkbox" value="2"> 选项2</label></li>
        <li><label><input type="checkbox" value="3"> 选项3</label></li>
        <li><label><input type="checkbox" value="4"> 选项4</label></li>
        <li><label><input type="checkbox" value="5"> 选项5</label></li>
        <li><label><input type="checkbox" value="6"> 选项6</label></li>
      </ul>
    </div>
  </div>

  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script>
    $(function() {
      // 初始化,将选中的选项添加到自定义下拉框中展示
      $('#multi-select option:selected').each(function() {
        var value = $(this).val();
        var text = $(this).text();
        var tagHtml = '<span data-value="' + value + '">' + text + '<i class="fa fa-times"></i></span>';
        $('.multi-select-tags').append(tagHtml);
      });

      // 点击文本框或已选标签时打开下拉选项
      $('.multi-select-box input, .multi-select-tags').click(function() {
        $('.multi-select-options').show();
      });

      // 点击其他地方时关闭下拉选项
      $(document).click(function(event) {
        if (!$(event.target).closest('.multi-select-box').length) {
          $('.multi-select-options').hide();
        }
      });

      // 输入框关键词改变时过滤选项
      $('.multi-select-search').keyup(function() {
        var keyword = $.trim($(this).val()).toLowerCase();
        $('.multi-select-options input[type="checkbox"]').each(function() {
          $(this).parent().parent().toggle($(this).next().text().toLowerCase().indexOf(keyword) > -1);
        });
      });

      // 点击复选框时更新选中标签
      $('.multi-select-options input[type="checkbox"]').click(function() {
        var $selectedTags = $('.multi-select-tags span');
        var $thisTag = $(this).parent().parent();
        var selectedCount = $selectedTags.length;
        var maxCount = 3; // 最多选3个

        if ($(this).is(':checked')) { // 新增选中标签
          if (selectedCount < maxCount) {
            var value = $(this).val();
            var text = $(this).next().text();
            var tagHtml = '<span data-value="' + value + '">' + text + '<i class="fa fa-times"></i></span>';
            $('.multi-select-tags').append(tagHtml);
          } else {
            $(this).prop('checked', false);
            alert('最多只能选' + maxCount + '个选项!');
          }
        } else { // 取消选中标签
          var value = $(this).val();
          $selectedTags.filter('[data-value="' + value + '"]').remove();
        }

        // 更新原生下拉列表、自定义下拉框的选中状态
        var selectedValues = [];
        $selectedTags.each(function() {
          selectedValues.push($(this).data('value'));
        });
        $('#multi-select option').prop('selected', false).filter('[value="' + selectedValues.join('"],[value="') + '"]').prop('selected', true);
        var tagsHtml = $selectedTags.length > 0 ? $selectedTags.clone().children('i').remove().end().html() : '请选择';
        $('.multi-select-box .multi-select-tags').html(tagsHtml);
        $selectedTags.hide();
      });

      // 点击标签右侧的删除图标时取消选中标签
      $('.multi-select-tags').on('click', 'span i', function() {
        var value = $(this).parent().data('value');
        $('.multi-select-options input[type="checkbox"]').filter('[value="' + value + '"]').prop('checked', false);
        $(this).parent().remove();
      });
    });
  </script>
</body>
</html>

示例二

这个下拉框可以任意选择选项,并在自定义下拉框中实时展示已选标签。

```html





多选下拉框(示例二)