1.简述
element-ui是由饿了么前端团队推出的一套为开发者、设计师和产品经理准备的基于 vue 实现的一套不依赖业务的 UI 组件库,提供了丰富的PC端组件,减少用户对常用组件的封装,降低了开发的难易程度。而手机端有对应框架是 Mint UI 。
2.官方文档
https://element.eleme.cn/2.15/#/zh-CN/component/quickstart
3.TABLE自定义列筛选器
3.1.说明
element-ui默认的table组件支持的表头筛选器是比较简单的只支持数组的下拉单选或多选的形式,但有时候因为不同的需求不同的场景,需要支持输入框形式。
3.2.代码
////////////////////////////////////////header-tools///////////////////////////////////////
<template>
<el-popover :placement="placement" :width="width" v-model="visible">
<div class="header-tools-order">
<div @click="sortOrder('ascending')" class="order-item AZ-anime"><i class="el-icon-top"></i>升序</div>
<div @click="sortOrder('descending')" class="order-item AZ-anime"><i class="el-icon-bottom"></i>降序</div>
<div @click="sortOrder(null)" class="order-item AZ-anime"><i class="el-icon-close"></i>取消排序</div>
</div>
<h3 v-text="label"></h3>
<div class="header-tools-body">
<div>
<el-select class="filter-mode-select" v-model="option.filterMode">
<el-option v-for="operation in operationList" :key="operation.value" :value="operation.value" :label="operation.label"></el-option>
</el-select>
</div>
<el-input v-if="['_null','_not_null','_in','_not_in'].indexOf(option.filterMode)<0" v-model="option.inputValue" clearable />
<el-input v-if="['_between'].indexOf(option.filterMode)>-1" v-model="option.subInputValue" clearable />
<div class="option-list-input container-flex-space-between" v-if="['_in','_not_in'].indexOf(option.filterMode)>-1" v-for="(op,opIndex) in option.optionList">
<el-input v-model="op.inputValue" @paste.native.capture.prevent="onPaste($event,opIndex)" clearable />
<div class="container-flex-space-between">
<i @click="addFilter(opIndex)" class="el-icon-circle-plus"></i>
<i v-if="option.optionList.length > 1" @click="removeFilter(opIndex)" class="el-icon-error"></i>
</div>
</div>
</div>
<div class="header-tools-footer container-flex-space-between">
<el-button size="small" @click="visible = false">关闭</el-button>
<el-button size="small" type="primary" @click="doSubmit()">确定</el-button>
</div>
<span slot="reference" class="header-tools-title">
<span :class="{'has-search':hasFilter()}" :title="label" v-text="label"></span>
<span style="white-space: nowrap;">
<span class="caret-wrapper">
<i class="sort-caret ascending"></i>
<i class="sort-caret descending"></i>
</span>
<i class="fa fa-filter AZ-anime" :class="{'has-search':hasFilter()}"></i>
</span>
</span>
</el-popover>
</template>
<script>
export default {
name: 'header-tools',
props: {
placement: {
type: String,
default: 'bottom'
},
width: {
type: String,
default: '240'
},
dataType: {
type: String,
default: 'string'
},
label: String,
prop: String,
mirrorProp: String //解决列的prop和headerTools的prop不一致导致不能排序问题
},
data () {
return {
visible: false,
option:{
inputValue:'',
subInputValue:'',
filterMode:'_eq',
optionList:[{
inputValue:''
}]
},
operationList:[],
stringOperation:[
{value:'_eq',label:'正好是'},
{value:'_ne',label:'不是'},
{value:'_like',label:'包含'},
{value:'_not_like',label:'不包含'},
{value:'_in',label:'在之中'},
{value:'_not_in',label:'不在之中'},
{value:'_null',label:'为空'},
{value:'_not_null',label:'不为空'}
],
numberOperation:[
{value:'_eq',label:'等于'},
{value:'_ne',label:'不等于'},
{value:'_ge',label:'大于等于'},
{value:'_le',label:'小于等于'},
{value:'_between',label:'介于以下项之间'},
{value:'_null',label:'为空'},
{value:'_not_null',label:'不为空'}
],
dateOperation:[
{value:'_eq',label:'正好是'},
{value:'_ne',label:'不是'},
{value:'_ge',label:'晚于'},
{value:'_le',label:'早于'},
{value:'_between',label:'介于以下时间之间'},
{value:'_null',label:'为空'},
{value:'_not_null',label:'不为空'}
]
}
},
mounted : function() {
this.$emit('regist-component', this);
this.operationList =
this.dataType == 'string'? this.stringOperation :
this.dataType == 'number'? this.numberOperation :
this.dataType == 'date'? this.dateOperation :
this.stringOperation;
},
computed: {
defaultTheme () {
return this.$store.state.config.defaultTheme
}
},
methods: {
addFilter (optionIndex) {
this.option.optionList.splice(optionIndex+1,0,{
inputValue:'',
filterMode:'_eq'
})
},
removeFilter (optionIndex) {
this.option.optionList.splice(optionIndex,1);
},
hasFilter () {
if(this.option.inputValue || this.option.subInputValue){
return true;
}else{
if(this.option.optionList && this.option.optionList.length){
for(var i = 0; i < this.option.optionList.length; i++){
if (this.option.optionList[i].inputValue) {
return true;
}
}
}
return false;
}
},
doSubmit () {
var option = {
prop: this.prop,
option: this.option,
label: this.label
};
for (var i = 0; i < this.operationList.length; i++) {
if (this.option.filterMode == this.operationList[i].value) {
option.operationLabel = this.operationList[i].label;
break;
}
}
this.$emit('apply-option', option)
this.visible = false;
},
sortOrder (sort) {
var option = {
prop: this.prop,
sort: sort
};
if(this.mirrorProp) {
option['mirrorProp'] = this.mirrorProp
}
this.$emit('sort-order', option);
this.visible = false;
},
clearFilter () {
this.option = {
inputValue:'',
subInputValue:'',
filterMode:'_eq',
optionList:[{
inputValue:''
}]
}
},
onPaste(e,index){
var _this = this;
var rows = e.clipboardData.getData('text').split('\n');
//去除最后一位空位
if (!rows[rows.length-1]) {
rows.splice(rows.length-1,1);
}
//去重
var obj = {};
var resultRows = []
rows.forEach(function(row){
if(!obj[row]){
resultRows.push(row);
}
obj[row]=true;
});
if(resultRows && resultRows.length){
resultRows.forEach(function(row,rowIndex){
if (_this.option.optionList.length<=index+rowIndex) {
_this.option.optionList.push({inputValue:row})
}else{
_this.option.optionList[index+rowIndex].inputValue = row;
}
});
}
}
}
}
</script>
<style lang="scss" scoped>
@import '@/assets/scss/element-variables.scss';
h3{
margin: 10px 0;
}
.header-tools-title{
display: flex;
align-items: center;
justify-content: space-between;
line-height: 1.1;
white-space: normal;
word-break: break-word;
}
.header-tools-title>span:first-child{
display:-webkit-box;
overflow:hidden;
white-space:normal !important;
text-overflow:ellipsis;
word-wrap:break-word;
-webkit-line-clamp:2;
-webkit-box-orient:vertical;
}
.header-tools-title i{
cursor: pointer;
}
.filter-mode-select{
width: 100px;
}
.filter-mode-select ::v-deep .el-input .el-input__inner{
padding-left: 0px;
border: none;
}
.header-tools-footer{
margin-top: 10px;
}
.header-tools-order {
border-bottom: 1px solid #EBEEF5;
padding-bottom: 10px;
font-size: $--font-size-small;
.order-item {
padding-top: 3px;
padding-bottom: 3px;
}
::v-deep div{
padding: 5px 0px;
border-radius: 4px;
cursor: pointer;
}
::v-deep div:hover{
background-color: #409EFF;
color: white;
}
}
.has-search{
color: #409EFF;
}
.header-tools-body{
max-height: 320px;
overflow: auto;
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
::v-deep i {
color: #409EFF;
margin-left: 10px;
font-size: 16px;
}
}
.header-tools-body::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
.el-table .header-tools-title .caret-wrapper .sort-caret{
border-top-color: transparent;
border-bottom-color: transparent;
}
.el-table .ascending .header-tools-title .sort-caret.ascending {
border-bottom-color: #409EFF;
}
.el-table .descending .header-tools-title .sort-caret.descending {
border-top-color: #409EFF;
}
.el-input+.el-input,
.option-list-input+.option-list-input{
margin-top: 4px;
}
.el-select-dropdown__item {
font-size: $--font-size-small;
}
</style>
<style>
.header-tools-tag{
background-color: #ecf5ff;
color: #409eff;
border: 1px solid #d9ecff;
padding: 9px 15px;
line-height: 1;
height: 32px;
margin-top: 5px;
}
.header-tools-tag+.header-tools-tag{
margin-bottom: 0px;
margin-left: 10px;
}
.header-tools-tag .el-icon-close{
color: #409eff;
}
.header-tools-tag .el-tag__close:hover{
background-color: #409eff;
color: #FFFFFF;
}
.header-tools-tag-field{
width: auto;
max-width: 50%;
overflow: auto;
display: inline-block;
vertical-align: top;
margin: -5px 10px 0px 10px;
}
</style>
//////////////////////////////////element-variables.scss//////////////////////////////////
// zhimi variables
$zm-size-base: 13px;
// element variables
/* 改变主题色变量 */
$--color-primary: #1D4ED8;
$--color-success: #047857;
$--color-warning: #D97706;
$--color-danger: #B91C1C;
$--color-info: #7F8082;
// 字体
// $--font-size-extra-large: 20px;
// // 18px
// $--font-size-large: 18px;
// // 16px
// $--font-size-medium: 16px;
// // 14px
$--font-size-base: $zm-size-base;
// // 13px
// $--font-size-small: 13px;
// // 12px
// $--font-size-extra-small: 12px;
// // 500
// $--font-weight-primary: 500;
// // 100
// $--font-weight-secondary: 100;
// // 24px
// $--font-line-height-primary: 2;
// // 16px
// $--font-line-height-secondary: 1.12;
$--menu-item-font-size: 14px;
/* 改变 icon 字体路径变量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";