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

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

显示效果:
在这里插入图片描述

<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
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为你提供一个基本的ElDialog封装,供你参考: ```vue <template> <el-dialog :title="title" :visible.sync="dialogVisible" :before-close="handleClose" :close-on-click-modal="false" :custom-class="customClass" :width="width" :lock-scroll="lockScroll" :modal-append-to-body="modalAppendToBody" :destroy-on-close="destroyOnClose" :center="center" @opened="handleOpen" @closed="handleClosed" v-bind="$attrs" v-on="$listeners" > <slot></slot> </el-dialog> </template> <script lang="ts"> import { defineComponent } from 'vue'; import { ElDialog } from 'element-plus'; export default defineComponent({ name: 'MyDialog', props: { title: { type: String, default: '', }, dialogVisible: { type: Boolean, default: false, }, customClass: { type: String, default: '', }, width: { type: String, default: '50%', }, lockScroll: { type: Boolean, default: true, }, modalAppendToBody: { type: Boolean, default: true, }, destroyOnClose: { type: Boolean, default: false, }, center: { type: Boolean, default: true, }, }, emits: ['update:dialogVisible', 'opened', 'closed'], methods: { handleClose(done: () => void) { // 自定义关闭操作 done(); }, handleOpen() { this.$emit('opened'); }, handleClosed() { this.$emit('closed'); }, }, components: { ElDialog, }, }); </script> ``` 这里我们使用了Vue3的Composition API,使用`defineComponent`定义了一个组件,并引入了Element Plus的ElDialog组件。 我们将ElDialog组件的属性和事件通过props和emits暴露出来,并在组件内部进行了一些自定义操作,如自定义关闭操作和自定义事件触发。 你可以根据自己的需求对组件进行进一步封装和定制化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值