二次封装element-plus:自定义下拉框可输入次数

要实现一个自定义的下拉框,并且包含你提到的几个要点

我们这里需要使用到Vue3模板、计算属性、方法和事件监听等功能。

以下是一个简化的实现思路

  1. 输入框的显示与隐藏

    • 使用v-ifv-show来控制输入框的显示与隐藏。
    • 当用户点击下拉框但未选择具体项(比如点击了自定义选项),显示输入框。
    • 当用户选择具体项或确认自定义输入后,隐藏输入框。
  2. 下拉框宽度自适应

    • 使用CSS来控制下拉框的宽度,可以使用min-widthmax-widthwidth: 100%等来实现自适应。
    • 确保下拉框容器的宽度设置能够正确影响内部的el-option等元素。
  3. 自定义的数据回显

    • 监听输入框的input事件,实时更新自定义数据。
    • 当用户从下拉框中选择项时,更新v-model绑定的值。
    • 使用计算属性或方法来合并显示默认选项和自定义选项。
  4. 接口数据要回显对应的次数

    • 假设接口返回的数据包含次数信息,可以在el-option:label中使用模板字符串来显示次数。
    • 例如::label="item.label({item.count}次)"
  5. 优化与交互

    • 当用户选择自定义选项(值为0)时,显示输入框并聚焦。
    • 提供一个"确认"按钮来确认自定义输入,并添加到下拉框的选项中。
    • 使用Vue的ref$refs来访问DOM元素,实现输入框的聚焦。

这里是具体的dom样式,这里不是频繁修改就使用v-if,在下拉框最下面显示一个自定义次数选项,给值0,并进行监听,如果是0就展示输入框并收起下拉框,还有默认聚焦输入框,只有点击确认按钮才会确认并新增到options里面。

ini 复制代码
<template>
  <div>
    <el-select
      v-model="value"
      placeholder="Select"
      class="relative"
      :style="{ width: selectWidth }"
      @change="handleSelectChange"
      @visible-change="visibleChange"
    >
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
      <el-option
        key="custom"
        label="自定义次数"
        :value="0"
      />
    </el-select>
    <div v-if="showInput" class="input-container absolute">
      <el-input
        ref="inputRef"
        v-model="customValue"
        placeholder=""
        style="width: 80px;margin-right: 16px;"
      />
      <el-button type="text" @click="addCustomOption">
        确认
      </el-button>
    </div>
  </div>
</template>

监听到下拉框显示就关闭输入框

php 复制代码
// 下拉框显示关闭输入框
function visibleChange(val: boolean) {
  if (val) {
    showInput.value = false
  }
}

调整下拉框宽度,如果是自定义次数,宽度就是120px,可以显示全自定义次数的字

ini 复制代码
// 调整下拉框宽度
function adjustSelectWidth(val: number) {
  const tempDiv = document.createElement('div')
  tempDiv.style.position = 'absolute'
  tempDiv.style.visibility = 'hidden'
  tempDiv.style.width = 'auto'
  tempDiv.style.fontSize = '14px'
  document.body.appendChild(tempDiv)
  tempDiv.innerHTML = getLabel(val)
  selectWidth.value = val ? `${tempDiv.clientWidth + 60}px` : '120px'
  document.body.removeChild(tempDiv)
}

下拉框选择之后的输入框展示与隐藏

kotlin 复制代码
// 处理选择变化
function handleSelectChange(val: number) {
  if (val === 0) { // 假设 0 是自定义选项的值
    showInput.value = true
    customValue.value = null
    adjustSelectWidth(val)
    // 输入框聚焦
    nextTick(() => {
      const input = inputRef.value as HTMLInputElement
      input.focus()
    })
  }
  else {
    showInput.value = false
    adjustSelectWidth(val)
  }
}

添加自定义选项

ini 复制代码
function addCustomOption() {
  if (customValue.value !== null) {
    const customLabel = getLabel(customValue.value)
    options.value.push({ value: customValue.value, label: customLabel })
    value.value = customValue.value
    showInput.value = false
  }
}

监控 props.value,动态添加不存在的选项

scss 复制代码
watch(
  () => props.value,
  (newVal) => {
    ensureValueInOptions(newVal)
    adjustSelectWidth(newVal)
  },
  { immediate: true },
)

确保传递的动态值在 options 中存在

scss 复制代码
function ensureValueInOptions(val: number) {
  if (!options.value.some(option => option.value === val)) {
    val && options.value.push({
      value: val,
      label: getLabel(val),
    })
  }
}

// 初始检查
ensureValueInOptions(props.value)

最终的效果

去掉输入框的边框,以及输入框的位置

css 复制代码
.input-container {
  display: flex;
  align-items: center;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.12);
  padding: 15px;
  z-index: 9999;
}
::v-deep(.el-input__wrapper) {
  box-shadow: none;
}

总结:

  1. showInput : 新增的 ref,控制是否显示 el-input
  2. customValue: 用于存储自定义输入的值。
  3. handleSelectChange : 处理 el-select 选择变化的函数。如果选择的是自定义选项(假设值为 0),则显示 el-input
  4. addCustomOption : 当自定义值输入完成后,将其添加到 options 列表中,并设置为当前选中的值。

通过这种方式,你可以在下拉框中添加一个自定义选项,点击该选项后显示输入框以输入自定义次数,并将输入的值添加到选项列表中进行选择,有一些样式还有其他细节也可以根据自己的需要进行一个补充,大致的逻辑就是这样。

相关推荐
F-2H13 分钟前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
gqkmiss1 小时前
Chrome 浏览器插件获取网页 iframe 中的 window 对象
前端·chrome·iframe·postmessage·chrome 插件
m0_748247553 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
m0_748255023 小时前
前端常用算法集合
前端·算法
真的很上进4 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web130933203984 小时前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2344 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1235 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~6 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语6 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js