原生js实现下拉框,支持多选、搜索

原生js实现下拉框,支持多选、搜索

就是一些事件绑定,话不多说上代码。

使用起来的话就调用init方法
1.搜索框与选中结果同框

<!--
 * @Description: 
 * @Autour: lkx
 * @Date: 2023-10-07 13:47:03
 * @LastEditors: lkx
 * @LastEditTime: 2023-12-21 20:17:25
-->
<!DOCTYPE html>
<html>

<head>
  <style>
    .custom-select {
      width: 260px;
      position: relative;
      display: flex;
      align-items: flex-start;
      border: 1px solid #999;
      border-radius: 5px;
    }

    .custom-select-content {
      width: 100%;
      min-height: 32px;
      max-height: 120px;
      overflow-x: hidden;
      overflow-y: auto;
    }

    .select-input {
      width: 254px;
      height: 26px;
      margin-right: 20px;
      border: none;
    }

    .select-input:focus {
      outline: none;
    }

    .select-result-label {
      display: block;
      height: 32px;
      line-height: 32px;
    }

    .select-list {
      position: absolute;
      left: 0;
      bottom: 0;
      transform: translateY(110%);
      width: 260px;
      min-height: 32px;
      max-height: 120px;
      overflow-x: hidden;
      overflow-y: auto;
      border: 1px solid #999;
      border-radius: 5px;
    }

    .select-list div {
      padding: 2px 4px;
      box-sizing: border-box;
    }

    .select-list div:hover {
      background-color: #eee;
      cursor: pointer;
    }

    .selected {
      color: blue;
    }

    .select-result {
      display: flex;
      flex-wrap: wrap;
      box-sizing: border-box;
    }

    .select-result div {
      height: 26px;
      border: 1px solid #999;
      border-radius: 5px;
      padding: 3px;
      margin: 3px;
      box-sizing: border-box;
      display: flex;
      align-items: center;
    }

    .select-result div span:last-of-type {
      display: inline-block;
      border: 1px solid #999;
      height: 8px;
      width: 8px;
      border-radius: 100%;
      padding: 2px;
      line-height: 7px;
      text-align: center;
      font-size: 12px;
      margin-left: 3px;
      cursor: pointer;
    }
  </style>
</head>

<body>
  <div class="custom-select">
    <div class="custom-select-content">
      <div class="select-result select-box "></div>
      <input type="text" class="select-input" placeholder="搜索">
    </div>
    <div class=" select-list select-box " style=" display: none;"></div>
  </div>


  <script>
    const selectContent = document.querySelector('.custom-select .custom-select-content')
    const selectInput = document.querySelector('.custom-select .custom-select-content .select-input')
    const selectList = document.querySelector('.custom-select .select-list')
    const selectResult = document.querySelector('.custom-select .custom-select-content .select-result')

    let selectInputBlurTimes = null
    let selectDataHit = []
    let selectDataAll = []

    // 事件绑定
    selectInput.addEventListener('input', () => {
      const elList = Array.from(selectList.querySelectorAll('div'))
      selectList.style.display = (!selectInput.value || elList.findIndex(item => item.textContent.includes(selectInput.value)) !== -1) ? 'block' : 'none'
      Array.from(selectList.querySelectorAll('div')).forEach(item => {
        item.style.display = (!selectInput.value || item.textContent.includes(selectInput.value)) ? 'block' : 'none'
      })
    })
    document.addEventListener('click', e => {
      selectList.style.display = e.target.className.includes('select-input') || e.target.className.includes('select-list') || e.target.className.includes('select-result-close') || (e.target.offsetParent && e.target.offsetParent.className.includes('select-list')) ? 'block' : 'none'
    })
    selectContent.addEventListener('click', e => {
      selectInput.focus()
      selectList.style.display = 'block'
      selectInput.scrollIntoView({ behavior: 'smooth', block: 'center' })
      e.stopPropagation()
    })

    // 生成下拉列表
    const createSelectList = (content) => {
      const div = document.createElement('div')
      div.addEventListener('click', () => {
        if (selectDataHit.includes(content.value)) {
          selectDataHit.splice(selectDataHit.indexOf(content.value), 1)
          Array.from(selectResult.querySelectorAll('div span')).find(item => item.textContent === content.label).parentNode.remove()
          div.classList.remove('selected')
        } else {
          selectDataHit.push(content.value)
          createSelectResult(content)
          div.classList.add('selected')
        }
      })
      div.textContent = content.label
      selectList.append(div)
    }

    // 生成选中列表
    const createSelectResult = (content) => {
      const div = document.createElement('div')
      const span = document.createElement('span')
      span.textContent = "x"
      span.className = 'select-result-close'
      span.addEventListener('click', () => {
        selectDataHit.splice(selectDataHit.indexOf(content.value), 1)
        selectList.querySelectorAll('div')[selectDataAll.findIndex(item => item.value === content.value)].classList.remove('selected')
        div.remove()
      })

      div.innerHTML = `
				<span>${content.label}</span>
			`
      div.append(span)
      selectResult.append(div)
      selectInput.scrollIntoView({ behavior: 'smooth', block: 'center' })
    }

    // 初始化
    const init = () => {
      selectDataAll = [{ label: '111111', value: 111111 }, { label: '222222', value: 222222 }, { label: '333333', value: 333333 }, { label: '444444', value: 444444 }, { label: '5555555', value: 5555555 }, { label: '666666', value: 1116111 }, { label: '1111711', value: 1111711 }, { label: '1111181', value: 1118111 }, { label: '1111191', value: 1911111 },]
      selectDataAll.forEach(item => {
        createSelectList(item)
      })
    }

    init()
  </script>
</body>

</html>

2.输入框与选中结果分离

<!--
 * @Description: 
 * @Autour: lkx
 * @Date: 2023-10-07 13:47:03
 * @LastEditors: lkx
 * @LastEditTime: 2023-10-07 14:30:17
-->
<!DOCTYPE html>
<html>

<head>
  <style>
    .custom-select {
      position: relative;
      display: flex;
      align-items: flex-start;
    }

    .select-input {
      width: 254px;
      height: 26px;
      margin-right: 20px;
    }

    .select-box {
      width: 260px;
      min-height: 32px;
      max-height: 120px;
      overflow-x: hidden;
      overflow-y: auto;
      border: 1px solid #999;
      border-radius: 5px;
    }

    .select-result-label {
      display: block;
      height: 32px;
      line-height: 32px;
    }

    .select-list {
      position: absolute;
      left: 0;
      top: 40px;

    }

    .select-list div {
      padding: 2px 4px;
      box-sizing: border-box;
    }

    .select-list div:hover {
      background-color: #eee;
      cursor: pointer;
    }

    .selected {
      color: blue;
    }

    .select-result {
      display: flex;
      flex-wrap: wrap;
      box-sizing: border-box;
    }

    .select-result div {
      height: 26px;
      border: 1px solid #999;
      border-radius: 5px;
      padding: 3px;
      margin: 3px;
      box-sizing: border-box;
      display: flex;
      align-items: center;
    }

    .select-result div span:last-of-type {
      display: inline-block;
      border: 1px solid #999;
      height: 8px;
      width: 8px;
      border-radius: 100%;
      padding: 2px;
      line-height: 7px;
      text-align: center;
      font-size: 12px;
      margin-left: 3px;
      cursor: pointer;
    }
  </style>
</head>

<body>
  <div class="custom-select">
    <input type="text" class="select-input" placeholder="搜索">
    <div class="select-list select-box " style="display: none;"></div>
    <span class="select-result-label">选中结果:</span>
    <div class="select-result select-box "></div>
  </div>


  <script>
    const selectInput = document.querySelector('.custom-select .select-input')
    const selectList = document.querySelector('.custom-select .select-list')
    const selectResult = document.querySelector('.custom-select .select-result')

    let selectInputBlurTimes = null
    let selectDataHit = []
    let selectDataAll = []

    // 事件绑定
    selectInput.addEventListener('input', () => {
      const elList = Array.from(selectList.querySelectorAll('div'))
      selectList.style.display = (!selectInput.value || elList.findIndex(item => item.textContent.includes(selectInput.value)) !== -1) ? 'block' : 'none'
      Array.from(selectList.querySelectorAll('div')).forEach(item => {
        item.style.display = (!selectInput.value || item.textContent.includes(selectInput.value)) ? 'block' : 'none'
      })
    })
    document.addEventListener('click', e => {
      selectList.style.display = e.target.className.includes('select-input') || e.target.className.includes('select-list') || e.target.className.includes('select-result-close') || (e.target.offsetParent && e.target.offsetParent.className.includes('select-list')) ? 'block' : 'none'
    })

    // 生成下拉列表
    const createSelectList = (content) => {
      const div = document.createElement('div')
      div.addEventListener('click', () => {
        if (selectDataHit.includes(content.value)) {
          selectDataHit.splice(selectDataHit.indexOf(content.value), 1)
          Array.from(selectResult.querySelectorAll('div span')).find(item => item.textContent === content.label).parentNode.remove()
          div.classList.remove('selected')
        } else {
          selectDataHit.push(content.value)
          createSelectResult(content)
          div.classList.add('selected')
        }
      })
      div.textContent = content.label
      selectList.append(div)
    }

    // 生成选中列表
    const createSelectResult = (content) => {
      const div = document.createElement('div')
      const span = document.createElement('span')
      span.textContent = "x"
      span.className = 'select-result-close'
      span.addEventListener('click', () => {
        selectDataHit.splice(selectDataHit.indexOf(content.value), 1)
        selectList.querySelectorAll('div')[selectDataAll.findIndex(item => item.value === content.value)].classList.remove('selected')
        div.remove()
      })

      div.innerHTML = `
				<span>${content.label}</span>
			`
      div.append(span)
      selectResult.append(div)
    }

    // 初始化
    const init = () => {
      selectDataAll = [{ label: '111111', value: 111111 }, { label: '222222', value: 222222 }, { label: '333333', value: 333333 }, { label: '444444', value: 444444 }, { label: '5555555', value: 5555555 }, { label: '666666', value: 1116111 }, { label: '1111711', value: 1111711 }, { label: '1111181', value: 1118111 }, { label: '1111191', value: 1911111 },]
      selectDataAll.forEach(item => {
        createSelectList(item)
      })
    }

    init()
  </script>
</body>

</html>
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: 这个错误是由于两个数组的形状不兼容导致的。其中一个数组的形状是(none, 1),另一个数组的形状是(none, 2)。这意味着它们的行数相同,但列数不同。在某些情况下,这可能是由于数据类型不匹配或数据维度不正确引起的。您需要检查数据并确保它们具有相同的形状和数据类型。如果需要,您可以使用numpy库中的reshape函数来更改数组的形状。 ### 回答2: ValueError: shapes (None, 1) and (None, 2) are incompatible。是Python语言中常见的错误,通常出现在人工智能、机器学习等领域。这个错误提示显示的是两个数组的形状(Shapes)不兼容。简单来说,就是指两个数组的维度不一致,无法进行运算。 其中,None代表的是数组的尺寸,意味着这个维度大小可以被任意赋值,但是两个数组在某些维度上的大小是不匹配的。这个问题通常可以通过改变数组形状或对数组进行重新组合来解决。 实际上,这个错误可能涉及到函数、方法、操作、层、参数等各种因素。其中,常见的原因是两个数组中的一部分维度大小不匹配、缺少数据或维度没有进行扩展等。在解决这个错误的过程中,需要认真检查代码中涉及到的所有参数和变量,特别是需要仔细检查数组的形状、大小和数据类型是否匹配。 在数据科学领域中,这个错误通常会出现在机器学习的模型训练和预测过程中。如果两个数组的维度不匹配,可能会导致无法正常训练模型或预测出错。因此,在使用Python进行数据处理和机器学习的过程中,需要注意数组的形状和大小,以避免这个错误的出现。 总之,ValueError: shapes (None, 1) and (None, 2) are incompatible。这个错误提示意味着两个数组的形状不兼容,需要进行调整和匹配才能进行运算。在处理数据和编写代码时需要认真检查数据的大小、形状和类型,以避免这个错误的出现。 ### 回答3: 这个错误是由于两个numpy数组的形状不兼容而导致的。在 numpy 中,数组的形状是非常重要的,不同的形状可以产生不同的结果,如果两个数组的形状不兼容,就会出现这种 ValueError。 首先我们需要了解一下 numpy 数组的形状。在 numpy 中,数组的形状通常由两个属性组成:维度和大小。维度表示数组的维度数量,大小表示每个维度上的元素数量。比如一个二维数组的形状可以表示为 (3, 4),其中 3 表示该数组有 3 个维度,4 表示每个维度上有 4 个元素。 在出现 "shapes (none, 1) and (none, 2) are incompatible" 的错误时,通常是因为两个数组的形状在维度数量或者每个维度上的元素数量上不匹配。其中, (none, 1) 表示第一个数组的形状为一维数组,大小为 none 表示元素数量未知,后面的 1 表示每个维度上有 1 个元素。同理,(none, 2) 表示第二个数组的形状为一维数组,大小为 none 表示元素数量未知,后面的 2 表示每个维度上有 2 个元素。 针对这种错误,我们需要检查一下代码中两个数组的形状是否一致。如果不一致,我们需要进行相应的修改,使它们的形状兼容。具体的做法可以通过 numpy 提供的一些数组操作函数来实现,比如 reshape()函数可以改变数组的形状, concatenate()函数可以将两个数组拼接在一起,等等。 在解决这个错误时,我们还需要注意一些细节,比如 numpy 中不同操作函数对数组形状的要求可能会有所不同,我们需要根据具体情况进行选择。此外,我们还需要注意避免在操作数组时出现类型不一致的错误,比如将字符串类型的数组和浮点类型的数组进行拼接,这也可能会导致 ValueError 错误的出现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值