我是怎么给el-select添加插槽的

一句话概括需求,multiple的select,需要在鼠标悬浮到选中的选项时弹出悬浮框

el-select不支持内容的插槽,选中的内容就只显示该选项的currentLabel字段。我就想到给el-select添加一个插槽,能够定制显示的内容。这样让我重新思考了扩展el-select的方式。这次我选择使用mixins的方式来扩展.

开始贴代码了:)

<template>
  <div
    class="el-select"
    :class="[selectSize ? 'el-select--' + selectSize : '']"
    @click.stop="toggleMenu"
    v-clickoutside="handleClose">
    <div
      class="el-select__tags"
      v-if="multiple"
      ref="tags"
      :style="{ 'max-width': inputWidth - 32 + 'px', width: '100%' }">
      <span v-if="collapseTags && selected.length">
        <el-tag
          :closable="!selectDisabled"
          :size="collapseTagSize"
          :hit="selected[0].hitState"
          type="info"
          @close="deleteTag($event, selected[0])"
          disable-transitions>
          <span class="el-select__tags-text">{{ selected[0].currentLabel }}</span>
        </el-tag>
        <el-tag
          v-if="selected.length > 1"
          :closable="false"
          :size="collapseTagSize"
          type="info"
          disable-transitions>
          <span class="el-select__tags-text">+ {{ selected.length - 1 }}</span>
        </el-tag>
      </span>
      <transition-group @after-leave="resetInputHeight" v-if="!collapseTags">
        <el-tag
          v-for="item in selected"
          :key="getValueKey(item)"
          :closable="!selectDisabled"
          :size="collapseTagSize"
          :hit="item.hitState"
          type="info"
          @close="deleteTag($event, item)"
          disable-transitions>
          <span class="el-select__tags-text"><slot name="content" v-if="$scopedSlots.content" v-bind:item="item"></slot><template v-else>{{ item.currentLabel }}</template></span>
        </el-tag>
      </transition-group>

      <input
        type="text"
        class="el-select__input"
        :class="[selectSize ? `is-${ selectSize }` : '']"
        :disabled="selectDisabled"
        :autocomplete="autoComplete || autocomplete"
        @focus="handleFocus"
        @blur="softFocus = false"
        @click.stop
        @keyup="managePlaceholder"
        @keydown="resetInputState"
        @keydown.down.prevent="navigateOptions('next')"
        @keydown.up.prevent="navigateOptions('prev')"
        @keydown.enter.prevent="selectOption"
        @keydown.esc.stop.prevent="visible = false"
        @keydown.delete="deletePrevTag"
        @compositionstart="handleComposition"
        @compositionupdate="handleComposition"
        @compositionend="handleComposition"
        v-model="query"
        @input="debouncedQueryChange"
        v-if="filterable"
        :style="{ 'flex-grow': '1', width: inputLength / (inputWidth - 32) + '%', 'max-width': inputWidth - 42 + 'px' }"
        ref="input">
    </div>
    <el-input
      ref="reference"
      v-model="selectedLabel"
      type="text"
      :placeholder="currentPlaceholder"
      :name="name"
      :id="id"
      :autocomplete="autoComplete || autocomplete"
      :size="selectSize"
      :disabled="selectDisabled"
      :readonly="readonly"
      :validate-event="false"
      :class="{ 'is-focus': visible }"
      @focus="handleFocus"
      @blur="handleBlur"
      @keyup.native="debouncedOnInputChange"
      @keydown.native.down.stop.prevent="navigateOptions('next')"
      @keydown.native.up.stop.prevent="navigateOptions('prev')"
      @keydown.native.enter.prevent="selectOption"
      @keydown.native.esc.stop.prevent="visible = false"
      @keydown.native.tab="visible = false"
      @paste.native="debouncedOnInputChange"
      @mouseenter.native="inputHovering = true"
      @mouseleave.native="inputHovering = false">
      <template slot="prefix" v-if="$slots.prefix">
        <slot name="prefix"></slot>
      </template>
      <template slot="suffix">
        <i v-show="!showClose" :class="['el-select__caret', 'el-input__icon', 'el-icon-' + iconClass]"></i>
        <i v-if="showClose" class="el-select__caret el-input__icon el-icon-circle-close" @click="handleClearClick"></i>
      </template>
    </el-input>
    <transition
      name="el-zoom-in-top"
      @before-enter="handleMenuEnter"
      @after-leave="doDestroy">
      <el-select-menu
        ref="popper"
        :append-to-body="popperAppendToBody"
        v-show="visible && emptyText !== false">
        <el-scrollbar
          tag="ul"
          wrap-class="el-select-dropdown__wrap"
          view-class="el-select-dropdown__list"
          ref="scrollbar"
          :class="{ 'is-empty': !allowCreate && query && filteredOptionsCount === 0 }"
          v-show="options.length > 0 && !loading">
          <el-option
            :value="query"
            created
            v-if="showNewOption">
          </el-option>
          <slot></slot>
        </el-scrollbar>
        <template v-if="emptyText && (!allowCreate || loading || (allowCreate && options.length === 0 ))">
          <slot name="empty" v-if="$slots.empty"></slot>
          <p class="el-select-dropdown__empty" v-else>
            {{ emptyText }}
          </p>
        </template>
      </el-select-menu>
    </transition>
  </div>
</template>
<script>
import { Select } from 'element-ui';

export default {
  name: 'ExtendedSelect',
  mixins: [Select]
 }
</script>

以上内容大部分都是来自element源码,只做了一点点的修改

<slot name="content" v-if="$scopedSlots.content" v-bind:item="item"></slot><template v-else>{{ item.currentLabel }}</template>

使用方法

...
<extended-select v-model="value" placeholder="请选择">
    <el-option
      v-for="item in options"
      :key="item.value"
      :label="item.label"
      :value="item.value">
    </el-option>
    <el-popover
    slot="content"
    slot-scope="scope"
    placement="top-start"
    title="标题"
    width="200"
    trigger="hover"
    content="这是一段内容,这是一段内容,这是一段内容,这是一段内容。">
    <span slot="reference">{{ scope.item.currentLabel }}</span>
  </el-popover>
  </extended-select>
...

以上就是全部了

如果帮到你,给点个赞呗:)

<think>好的,我需要解决用户关于如何在Element UI的el-select组件中自定义选中插槽的问题。首先,我得回忆一下Element UI的文档和相关组件用法。记得el-select组件允许通过插槽来自定义选项的显示,比如使用slot="option"来定制每个选项的内容。但用户的问题是关于自定义选中后的显示,也就是当选项被选中后,在下拉框里如何展示自定义内容。 接下来,我应该检查用户提供的引用内容。引用[2]提到在el-select添加禁用的el-option,并调整样式,这可能与自定义显示有关,但不确定是否直接相关。引用[3]提到TSelectTable组件的多选隐藏删除icon,这可能涉及选中状态的样式调整,但用户的问题更侧重于插槽的自定义,而不是样式覆盖。 根据Element UI的文档,el-select组件确实有一个slot叫做“selected”,用于自定义选中项的显示。不过有时候可能需要结合使用scoped slot来获取当前选中的值。例如,使用slot="selected"并绑定数据到作用域插槽,从而渲染自定义内容。 然后,我需要构建一个示例代码,展示如何使用作用域插槽来显示自定义的选中项。例如,用户可能希望选中的项显示不同的格式,比如添加图标或颜色。代码部分应该包括el-select的结构,使用slot-scope或者v-slot来获取选中的值,并在template中定义显示内容。 另外,需要注意Element UI版本的问题,不同版本可能有不同的语法。例如,在较新的版本中可能需要使用v-slot代替slot-scope。但用户提供的引用中提到了Vue 2版本,因此应使用slot-scope的语法。 可能还需要处理多选的情况,这时候选中项的显示可能需要遍历选中的数组,每个项都应用自定义样式。同时,样式调整可能需要覆盖Element UI的默认样式,但用户的问题主要在于插槽的使用,而不是样式覆盖。 最后,确保代码示例正确无误,并解释关键部分,比如slot="selected"的作用,以及如何通过作用域获取选中的值。这样用户能够理解如何根据自己的需求调整代码。</think>在Element UI的`el-select`组件中,可以通过**作用域插槽**实现自定义选中项显示效果。这里提供两种实现方式: ### 方式1:使用`selected`插槽(基础用法) ```html <el-select v-model="selectedValue"> <!-- 自定义选中状态显示 --> <template slot="selected" slot-scope="{ value }"> <span style="color: #f56c6c">{{ value.label }} (已选中)</span> <i class="el-icon-success" style="margin-left: 5px"></i> </template> <!-- 正常选项列表 --> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item"> </el-option> </el-select> ``` *说明*:通过`slot="selected"`捕获当前选中值,`slot-scope`接收的`value`对应选项绑定的完整值对象[^2] ### 方式2:结合作用域插槽(复杂场景) ```html <el-select v-model="selectedValue"> <!-- 多选模式下自定义tag --> <template slot="selected" slot-scope="{ selected }"> <el-tag v-for="item in selected" :key="item.value" type="success" closable @close="removeTag(item)"> {{ item.label }} ✔ </el-tag> </template> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item"> </el-option> </el-select> ``` *说明*:当设置`multiple`属性时,`slot-scope`会返回`selected`数组,可遍历生成自定义标签[^3] ### 注意事项 1. 需要确保Element UI版本≥2.4.11(Vue 2.x) 2. 若需要覆盖默认样式,需添加`popper-class`自定义类名 3. 单选模式下`selected`插槽接收的是单个对象,多选模式下是数组
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值