二次封装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 列表中,并设置为当前选中的值。

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

相关推荐
阿珊和她的猫4 小时前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
加班是不可能的,除非双倍日工资8 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi9 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip9 小时前
vite和webpack打包结构控制
前端·javascript
excel10 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国10 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼10 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy10 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT10 小时前
promise & async await总结
前端
Jerry说前后端10 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化