<template>
<div ref="selectWrapper" v-click-outside:[popperPaneRef]="handleClose" :class="wrapperKls" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" @click.stop="toggleMenu">
<el-tooltip
ref="tooltipRef"
:visible="dropMenuVisible"
:placement="placement"
:teleported="teleported"
:popper-class="[nsSelect.e('popper'), popperClass]"
:popper-options="popperOptions"
:fallback-placements="['bottom-start', 'top-start', 'right', 'left']"
:effect="effect"
pure
trigger="click"
:transition="`${nsSelect.namespace.value}-zoom-in-top`"
:stop-popper-mouse-event="false"
:gpu-acceleration="false"
:persistent="persistent"
@show="handleMenuEnter"
>
<template #default>
<div class="select-trigger" @mouseenter="inputHovering = true" @mouseleave="inputHovering = false">
<div v-if="multiple" ref="tags" :class="[nsSelect.e('tags'), nsSelect.is('disabled', selectDisabled)]" :style="selectTagsStyle">
<transition v-if="collapseTags && selected.length" @after-leave="resetInputHeight">
<span :class="[nsSelect.b('tags-wrapper'), { 'has-prefix': prefixWidth && selected.length }]">
<el-tag
v-for="item in showTagList"
:key="getValueKey(item)"
:closable="!selectDisabled && !item.isDisabled"
:size="collapseTagSize"
:hit="item.hitState"
:type="tagType"
disable-transitions
@close="deleteTag($event, item)"
>
<span :class="nsSelect.e('tags-text')" :style="tagTextStyle">
{{ item.currentLabel }}
</span>
</el-tag>
<el-tag v-if="selected.length > maxCollapseTags" :closable="false" :size="collapseTagSize" :type="tagType" disable-transitions>
<el-tooltip
v-if="collapseTagsTooltip"
:disabled="dropMenuVisible"
:fallback-placements="['bottom', 'top', 'right', 'left']"
:effect="effect"
placement="bottom"
:teleported="teleported"
>
<template #default>
<span :class="nsSelect.e('tags-text')">+ {{ selected.length - maxCollapseTags }}</span>
</template>
<template #content>
<div :class="nsSelect.e('collapse-tags')">
<div v-for="item in collapseTagList" :key="getValueKey(item)" :class="nsSelect.e('collapse-tag')">
<el-tag
class="in-tooltip"
:closable="!selectDisabled && !item.isDisabled"
:size="collapseTagSize"
:hit="item.hitState"
:type="tagType"
disable-transitions
:style="{ margin: '2px' }"
@close="deleteTag($event, item)"
>
<span
:class="nsSelect.e('tags-text')"
:style="{
maxWidth: inputWidth - 75 + 'px',
}"
>{{ item.currentLabel }}</span
>
</el-tag>
</div>
</div>
</template>
</el-tooltip>
<span v-else :class="nsSelect.e('tags-text')">+ {{ selected.length - maxCollapseTags }}</span>
</el-tag>
</span>
</transition>
<transition v-if="!collapseTags" @after-leave="resetInputHeight">
<span :class="[nsSelect.b('tags-wrapper'), { 'has-prefix': prefixWidth && selected.length }]">
<el-tag
v-for="item in selected"
:key="getValueKey(item)"
:closable="!selectDisabled && !item.isDisabled"
:size="collapseTagSize"
:hit="item.hitState"
:type="tagType"
disable-transitions
@close="deleteTag($event, item)"
>
<span :class="nsSelect.e('tags-text')" :style="{ maxWidth: inputWidth - 75 + 'px' }">{{ item.currentLabel }}</span>
</el-tag>
</span>
</transition>
<input
v-if="filterable"
ref="input"
v-model="query"
type="text"
:class="[nsSelect.e('input'), nsSelect.is(selectSize), nsSelect.is('disabled', selectDisabled)]"
:disabled="selectDisabled"
:autocomplete="autocomplete"
:style="{
marginLeft: (prefixWidth && !selected.length) || tagInMultiLine ? `${prefixWidth}px` : '',
flexGrow: 1,
width: `${inputLength / (inputWidth - 32)}%`,
maxWidth: `${inputWidth - 42}px`,
}"
@focus="handleFocus"
@blur="handleQueryBlur"
@keyup="managePlaceholder"
@keydown="resetInputState"
@keydown.esc="handleKeydownEscape"
@keydown.enter.stop.prevent="handleQueryBlur"
@keydown.delete="deletePrevTag"
@keydown.tab="visible = false"
@compositionstart="handleComposition"
@compositionupdate="handleComposition"
@compositionend="handleComposition"
@input="handleQueryChange"
/>
</div>
<!-- fix: https://github.com/element-plus/element-plus/issues/11415 -->
<input
v-if="isIOS && !multiple && filterable && readonly"
ref="iOSInput"
:class="[nsSelect.e('input'), nsSelect.is(selectSize), nsSelect.em('input', 'iOS')]"
:disabled="selectDisabled"
type="text"
/>
<el-input
:id="id"
ref="reference"
v-model="selectedLabel"
type="text"
:placeholder="typeof currentPlaceholder === 'function' ? currentPlaceholder() : currentPlaceholder"
:name="name"
:autocomplete="autocomplete"
:size="selectSize"
:disabled="selectDisabled"
:readonly="readonly"
:validate-event="false"
:class="[nsSelect.is('focus', visible)]"
:tabindex="multiple && filterable ? -1 : undefined"
@focus="handleFocus"
@blur="handleBlur"
@input="debouncedOnInputChange"
@paste="debouncedOnInputChange"
@compositionstart="handleComposition"
@compositionupdate="handleComposition"
@compositionend="handleComposition"
@keydown.down.stop.prevent="navigateOptions('next')"
@keydown.up.stop.prevent="navigateOptions('prev')"
@keydown.enter.stop.prevent="selectOption"
@keydown.esc="handleKeydownEscape"
@keydown.tab="visible = false"
>
<template v-if="$slots.prefix" #prefix>
<div style="height: 100%; display: flex; justify-content: center; align-items: center">
<slot name="prefix" />
</div>
</template>
<template #suffix>
<el-icon v-if="iconComponent && !showClose" :class="[nsSelect.e('caret'), nsSelect.e('icon'), iconReverse]">
<component :is="iconComponent" />
</el-icon>
<el-icon v-if="showClose && clearIcon" :class="[nsSelect.e('caret'), nsSelect.e('icon')]" @click="handleClearClick">
<component :is="clearIcon" />
</el-icon>
</template>
</el-input>
</div>
</template>
<template #content>
<el-select-menu>
<el-scrollbar
v-show="options.size > 0 && !loading"
ref="scrollbar"
tag="ul"
:wrap-class="nsSelect.be('dropdown', 'wrap')"
:view-class="nsSelect.be('dropdown', 'list')"
:class="[nsSelect.is('empty', !allowCreate && Boolean(query) && filteredOptionsCount === 0)]"
>
<el-option v-if="showNewOption" :value="query" :created="true" />
<el-options @update-options="onOptionsRendered">
<slot />
</el-options>
</el-scrollbar>
<template v-if="emptyText && (!allowCreate || loading || (allowCreate && options.size === 0))">
<slot v-if="$slots.empty" name="empty" />
<p v-else :class="nsSelect.be('dropdown', 'empty')">
{{ emptyText }}
</p>
</template>
</el-select-menu>
</template>
</el-tooltip>
</div>
</template>
<script>
import { defineComponent, toRefs } from 'vue'
import { ElSelect } from 'element-plus'
import { useSelectStates } from 'element-plus/lib/components/select/src/useSelect'
export default defineComponent({
name: 'MySelect',
extends: ElSelect,
setup(props, ctx) {
const states = useSelectStates(props)
const { query } = toRefs(states)
const handleQueryBlur = (e) => {
const val = e.target.value?.trim() || ''
if (val && val.length > 0) {
ctx.emit('update:modelValue', [...props.modelValue, val])
states.query = ''
}
}
const handleQueryChange = (val) => {
if (states.previousQuery === val || states.isOnComposition) return
if (val && val.length > 0) {
states.currentPlaceholder = ''
}
}
return {
...ElSelect.setup(props, ctx),
handleQueryBlur,
handleQueryChange,
query,
}
},
})
</script>
<my-select class="w-full" v-model="dialog.form.content" multiple placeholder="请选择水印内容" filterable clearable>
<el-option v-for="item in list" :key="item.value" :label="item.label" :value="item.label" />
</my-select>
== 你以为完了,别慌,vue2版本的也有 ==
<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%' }">
<transition-group @after-leave="resetInputHeight">
<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">{{ item.currentLabel }}</span>
</el-tag>
</transition-group>
<input
type="text"
class="el-select__input"
:class="[selectSize ? `is-${selectSize}` : '']"
:disabled="selectDisabled"
:autocomplete="autoComplete || autocomplete"
@focus="handleFocus"
@blur="handleQueryBlur"
@compositionstart="handleComposition"
@compositionupdate="handleComposition"
@compositionend="handleComposition"
@keydown.enter.prevent="handleQueryBlur"
@keydown.esc.stop.prevent="visible = false"
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 }"
:tabindex="multiple && filterable ? '-1' : null"
@focus="handleFocus"
@blur="handleBlur"
@input="debouncedOnInputChange"
@keydown.native.down.stop.prevent="handleNavigate('next')"
@keydown.native.up.stop.prevent="handleNavigate('prev')"
@keydown.native.enter.prevent="selectOption"
@keydown.native.esc.stop.prevent="visible = false"
@keydown.native.tab="visible = false"
@compositionstart="handleComposition"
@compositionupdate="handleComposition"
@compositionend="handleComposition"
@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: 'MySelect',
extends: Select,
methods: {
handleQueryBlur(e) {
const val = e.target?.value?.trim() || ''
if (val && val.length > 0) {
this.value.push(val)
}
this.softFocus = false
},
handleQueryChange(val) {
if (this.previousQuery === val || this.isOnComposition) return
if (val && val.length > 0) {
this.currentPlaceholder = ''
}
},
},
// End
}
</script>