选择器组件
代码分析
<template>
<div class="dis-i-b ver-ali-mid">
<el-popover placement="bottom-start" trigger="click" v-model="show_dropdown" width="230">
<template slot="reference">
<div :class="['display-box', 'my-select','select-size-' +size, {'theme-color':themeColor, 'not-click': disabled}]" :style="{'width' : width }">
<div class="display-content" v-if="hardReset">{{selctLabel}}</div>
<i class="display-icon el-icon-caret-bottom" v-show="!displayText"></i>
</div>
</template>
<div :class="{'hide' : !show_dropdown}">
<div class="padd-all-10" v-if="isQuery">
<el-input class="input-34" v-model.trim="query_" v-bind="$attrs"></el-input>
</div>
<div>
<div style="height:260px;overflow:auto;">
<div v-show="!query_">
<div class="content_option" :key="alldeFault_.key" @click.stop="handler(alldeFault_)" v-if="Object.keys(alldeFault).length">
<span class="ellipsis" :style="value === alldeFault_.key ? 'color: #229DFF' : 'color: #333'" :title="alldeFault_.label">{{alldeFault_.label}}</span>
<i class="el-icon-check" style="color: #229DFF;line-height: 28px;" v-show="value == alldeFault_.key"></i>
</div>
</div>
<div v-for="(item,index) in data_" :key="index">
<div class="content_option" :key="item.key" @click.stop="handler(item)">
<span class="ellipsis" :style="value === item.key ? 'color: #229DFF' : 'color: #333'" :title="item.label">{{item.label}}</span>
<i class="el-icon-check" style="color: #229DFF;line-height: 28px;" v-show="value === item.key"></i>
</div>
</div>
</div>
</div>
</div>
</el-popover>
</div>
</template>
<style scoped>
.display-box {
border: 1px solid #ddd;
border-radius: 2px;
position: relative;
box-sizing: border-box;
}
.display-box .display-content {
position: absolute;
right: 26px;
left: 15px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.display-box .display-icon {
position: absolute;
width: 25px;
right: 0;
height: 100%;
border-left: 1px solid #ddd;
text-align: center;
}
.select-size-small {
height: 34px;
}
.select-size-small .display-content {
line-height: 34px;
}
.select-size-small .display-icon {
line-height: 32px;
}
.select-size-middle {
height: 40px;
}
.select-size-middle .display-content {
line-height: 40px;
}
.select-size-middle .display-icon {
line-height: 38px;
}
.theme-color {
color: #91a1a9;
background-color: #f6f6f6;
}
.content_option {
height: 36px;
line-height: 36px;
padding: 0 16px;
}
.content_option span {
max-width: 170px;
display: inline-block;
vertical-align: middle;
margin-right: 9px;
}
.content_option:hover {
background: #e2f2ff;
}
.content_option.active {
background: #dbebf9;
}
.content_option:hover span,
.content_option.active span {
color: #229dff !important;
}
.dis-i-b {
display: inline-block;
}
.ver-ali-mid {
vertical-align: bottom;
}
.not-click {
pointer-events: none;
color: #c0c4cc;
}
.hide {
display: none;
}
.el-form-item.is-error .my-select {
border-color: #f56c6c;
}
</style>
<script>
export default {
name: 'MySelect',
inheritAttrs: false,
props: {
isQuery: {
type: Boolean,
default: false
},
dataList: {
type: Array,
default: function() {
return []
}
},
alldeFault: {
type: Object,
require: false,
default: function() {
return {}
}
},
value: {
type: [String, Number],
require: true,
default: ''
},
width: {
type: String,
default: '150px'
},
themeColor: {
type: Boolean,
default: false
},
prop: {
type: Object,
default: function() {
return { key: 'id', label: 'name' }
}
},
disabled: {
type: Boolean,
default: false
},
size: {
type: String,
default: 'small'
}
},
data() {
return {
show_dropdown: false,
selctId: '',
timer: null,
data_: [],
query_: '',
loading_: false,
busy_: false,
keyValue_: {},
hardReset: true,
alldeFault_: {},
prop_: {}
}
},
watch: {
query_(n, o) {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.data_ = this.dataList
.map(v => ({
key: v[this.prop_.key],
label: v[this.prop_.label]
}))
.filter(v => {
if (n) {
return v.label.indexOf(n) != '-1'
} else {
return true
}
})
}, 300)
},
dataList(n, o) {
if (n) {
this.get_data()
}
}
},
methods: {
handler(item) {
this.show_dropdown = false
this.$emit('input', item.key)
this.$nextTick(() => {
this.$emit('change', item)
try {
this.$parent.validate('change')
} catch (error) {}
})
},
getkeyValue(e) {
this.keyValue_ = Object.assign({}, this.keyValue_)
let type = Object.prototype.toString.call(e)
if (type === '[object Array]') {
e.forEach(ele => {
this.keyValue_[ele.key] = ele.label
})
} else if (type === '[object Object]') {
this.keyValue_[e.key] = e.label
}
},
reSet() {
this.hardReset = false
this.$nextTick(() => {
this.hardReset = true
})
},
get_alldeFault() {
if (!Object.keys(this.alldeFault).length) return
let { key = '', label = '-全选-' } = this.alldeFault
this.alldeFault_ = { key: key, label: label }
},
get_prop() {
let { key = 'id', label = 'name' } = this.prop
this.prop_ = { key: key, label: label }
},
get_data() {
this.data_ = this.dataList.map(v => ({
key: v[this.prop_.key],
label: v[this.prop_.label]
}))
this.getkeyValue(this.data_)
}
},
created() {
this.get_alldeFault()
this.get_prop()
if (Object.keys(this.alldeFault).length) {
this.getkeyValue(this.alldeFault_)
}
if (this.dataList.length) {
this.get_data()
}
},
computed: {
selctLabel: function() {
return this.keyValue_[this.value]
}
}
}
</script>
组件使用(基础组件可进行全局注册,直接使用)
<my-select
v-model="selectId"
:dataList="dataList"
:alldeFault="{label: '-全选-'}"
:prop="{ key: 'id', label: 'name' }"
isQuery
width="200px"
themeColor
placeholder="你好"
></my-select>
属性
参数 |
说明 |
类型 |
可选值 |
默认值 |
selectId |
v-model 的绑定值 |
[String,Number] |
- |
- |
dataList |
options列表 |
Array |
- |
- |
alldeFault |
全选option定义(支持merge) |
Object |
{ key = ‘’, label = ‘-全选-‘ } |
- |
prop |
传入dataList格式解析,默认解析(支持merge) |
Object |
{ key: ‘id’, label: ‘name’ } |
{key: ‘id’, label: ‘name’:} |
isQuery |
是否支持搜索 |
Boolean |
true/false |
false |
width |
组件宽度 |
String |
- |
150px |
disabled |
组件是否只读 |
Boolean |
true/false |
false |
size |
组件大小 |
String |
small/middle |
small |
themeColor |
组件主题 |
Boolean |
true/false |
false |
placeholder |
搜索框 占位符 |
String |
- |
- |
方法
事件名称 |
说明 |
回调参数 |
change |
选中值发生变化时触发 |
当前选中的对象 |