vue3+ts+element plus自定义el-select下拉选择器组件封装

自定义el-select,包含内容有:
1、自定义select后缀图标,清除默认边框,限定下拉框宽度时,内容显示省略号,鼠标经过内容,显示title全部信息
2、鼠标经过select上方显示el-tooltip内容,自定义el-tooltip样式背景为透明色

显示效果:
vue3+ts+element plus自定义el-select下拉选择器组件封装_第1张图片

<template>
  <div>
  <!-- raw-content:content 中的内容是否作为 HTML 字符串处理,</br>显示为换行
    effect="customized":自定义主题
     -->
    <el-tooltip
      :visible="visible"
      trigger="hover"
      placement="top"
      :content="tipContent || props.placeholder"
      raw-content
      effect="customized"
    >
      <div
        class="select-option"
        @mouseenter="mouseenter"
        @mouseleave="mouseleave"
      >
        <el-select
          v-model="value"
          filterable
          @change="handleChange"
          @visible-change="visibleChange"
          :title="props.placeholder"
          class="m-2"
          :placeholder="props.placeholder"
          suffix-icon="none"
          size="small"
        >
          <el-option
            v-for="(item, index) in props.option"
            :key="index"
            :label="item.label"
            :value="item.value"
            :title="item.label"
            :class="props.optionWidth"
          />
        </el-select>
        <p
          class="select-icon"
          :style="{
            transform: selectIconStyle ? 'none' : 'rotate(180deg)',
            top: selectIconStyle ? '3px' : '-1px'
          }"
        />
      </div>
    </el-tooltip>
  </div>
</template>
<script setup lang="ts">
import { ref, watch, nextTick, computed } from "vue";
const props = defineProps({
  // 下拉选项列表
  option: {
    type: Array,
    default() {
      return [];
    }
  },
  // 下拉选项框的宽度样式,默认不定义,定义后超出设置宽度则省略号显示,鼠标放上去显示title全部内容
  optionWidth: {
    type: String,
    default: ""
  },
  // Tooltip默认内容
  placeholder: {
    type: String,
    default: ""
  },
  // 父组件选中项绑定值
  value: {
    type: String,
    default: ""
  }
});

let value = ref(""); // 选中项绑定值
const visible = ref(false); // Tooltip是否可见
const selectIconStyle = ref(true); // 后缀图标状态样式
const tipContent = computed(() => {
  // Tooltip内容
  if (props.option.length > 0) {
    for (const i in props.option) {
      const obj = props.option[i];
      if (obj["value"] === value.value) {
        // 根据下拉选项的value值匹配显示的label值
        return obj["label"];
      } else {
        return;
      }
    }
  } else {
    return;
  }
  return "";
});

// 鼠标移入
function mouseenter() {
  // tooltip内容字符大于5的时候显示tooltip
  if (tipContent.value && tipContent.value.length > 5) {
    visible.value = true;
  }
}
// 鼠标移出
function mouseleave() {
  // 隐藏tooltip
  visible.value = false;
}
// 传值父组件
const emit = defineEmits(["change"]);
// 选中值发生变化时触发
const handleChange = () => {
  emit("change", value.value);
};
// 下拉框出现/隐藏时触发
const visibleChange = val => {
  if (val) {
    selectIconStyle.value = false;
  } else {
    selectIconStyle.value = true;
  }
};
// 监听父组件的传值,同步到下拉选项值
watch(
  () => props.value,
  val => {
    nextTick(() => {
      value.value = val;
    });
  },
  {
    deep: true,
    immediate: true
  }
);
</script>
<style scope lang="scss">
.select-option {
  position: relative;
  // 清除select默认外边框
  .el-input__wrapper,
  .el-input__wrapper:hover {
    box-shadow: none;
  }

  .el-select {
    --el-select-input-focus-border-color: "#ffffff";
    --el-select-border-color-hover: "#ffffff";
  }
}

// 清除默认后缀图标
:deep(.el-select__icon) {
  display: none;
}

// 自定义后缀图标样式(这里是▽)
.select-icon {
  position: absolute;
  border: 4px solid transparent;
  border-top-color: #303133;
  margin-top: 15px;
  right: 5px;
  line-height: 8px;
  transition: transform 0.3s;
}

// 自定义tooltip样式,背景颜色透明
.el-popper.is-customized {
  border-radius: 4px 4px 4px 4px;
  border: none;
  background: rgba(0, 0, 0, 0.75);
  font-size: 12px;
  font-weight: 400;
  color: #e6e8eb;
  line-height: 18px;
}

:deep(.el-popper.is-customized .el-popper__arrow::before) {
  background: rgba(0, 0, 0, 0.75);
}
</style>

组件使用:

<template>
	<SelectOption
	 :value="value"
	  :option="option"
	  @change="changeOption"
	  :placeholder="'抖音客服'"
	  class="w-[85px]"
	/>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import SelectOption from "./selectOption.vue";
const value =ref("")
const option =ref([{
	label:"抖音客服助手1",
	value:"0",
	},{
	label:"抖音客服助手2",
	value:"0",
	}
])

function changeOption(val){
	value.value=val
}

你可能感兴趣的:(vue.js,elementui,前端)