公司有一个新的需求,点击ElTableColumn的头部可以进行搜索,这个功能同事已经做出来了,但是使用有些不方便,自己就打算封装成一个组件,学习一下。
ElTableColumn本来是这个样子的:
elemnet table.png
要做成的是这个样子:
gif.gif
我直接就放代码了,挨着挨着说明太多了。
新版本在下面
代码的结构:
代码结构.png
组件
<!-- ElTableColumnPro.vue -->
<template>
<el-table-column v-if="visible" :formatter="formatter" :align='align' :prop="prop" :header-align="headerAlign" :label="label" :width="width" :render-header="renderHeader" >
<template slot-scope="scope">
<slot :row="scope.row" :$index="scope.$index" >
<span>{{fomatMethod(scope.row[prop])}}</span>
</slot>
</template>
</el-table-column>
</template>
<script>
import moment from "moment";
export default {
name: "el-table-column-pro",
props: {
prop: {
type: String
},
label: {
type: String
},
width: {
type: Number
},
renderType: {
type: String,
validator: value => ["date", "input", "select"].includes(value)
},
placeholder: {
type: String
},
rederWidth: {
type: String,
default: "230px"
},
param: {
type: String,
default: ""
},
startDate: {
type: String
},
endDate: {
type: String
},
selectList: {
type: Array
},
isClear: {
type: Boolean,
default:true
},
visible: {
type: Boolean,
default: true
},
filterIcon: {
type: String,
default: "el-icon-search"
},
callback: {
type: Function
},
formatter: {
type: Function,
default:(row, column, cellValue)=>cellValue
},
align:{
type:String
},
headerAlign:{
type:String
}
},
data() {
return {
formatD:this.filterIcon
};
},
methods: {
fomatMethod(value){
return this.formatter('','',value)
},
renderHeader(createElement, { column, $index }) {
switch (this.renderType) {
case "date":
return this.renderDate(createElement, { column, $index });
case "input":
return this.rederInput(createElement, { column, $index });
case "select":
return this.rederSelect(createElement, { column, $index });
default:
return column.label;
}
},
rederInput(createElement, { column, $index }) {
return createElement(
"div",
{
class: "filters",
style: {
color: column.color
}
},
[
createElement(
"el-popover",
{
props: {
placement: "bottom",
width: "200",
trigger: "click"
}
},
[
createElement("el-input", {
props: {
placeholder: this.placeholder,
value: this.param
},
nativeOn: {
keyup: event => {
if (event.keyCode === 13) {
this.$emit("update:param", event.target.value);
this.callback && this.callback();
}
}
},
on: {
blur: event => {
this.$emit("update:param", event.target.value);
this.callback && this.callback();
}
}
}),
createElement(
"span",
{
slot: "reference"
},
[
column.label,
createElement("i", {
class: this.filterIcon,
style: {
marginLeft: "4px"
}
})
]
)
]
)
]
);
},
rederSelect(createElement, { column, $index }) {
return createElement(
"div",
{
class: "filters",
style: {
color: column.color
}
},
[
createElement(
"el-popover",
{
props: {
placement: "bottom",
width: "200",
trigger: "click"
}
},
[
createElement(
"el-select",
{
props: {
placeholder: this.placeholder,
value: this.param,
clearable: this.isClear
},
on: {
input: value => {
this.$emit("update:param", value);
this.callback && this.callback();
}
}
},
[
this.selectList.map(item => {
return createElement("el-option", {
props: {
value: item.value,
label: item.label
}
});
})
]
),
createElement(
"span",
{
slot: "reference"
},
[
column.label,
createElement("i", {
class: this.filterIcon,
style: {
marginLeft: "4px"
}
})
]
)
]
)
]
);
},
renderDate(createElement, { column, $index }) {
return createElement(
"div",
{
class: "filters"
},
[
createElement(
"el-popover",
{
props: {
placement: "bottom",
width: this.rederWidth,
trigger: "click"
}
},
[
createElement("el-date-picker", {
props: {
placeholder: this.placeholder,
value: this.value,
type: "daterange",
rangeSeparator:"至",
startPlaceholder:"开始日期",
endPlaceholder:"结束日期",
},
style: {
width: this.rederWidth
},
on: {
input: value => {
if (value) {
const startDate = moment(value[0]).format("YYYY-MM-DD");
const endDate = moment(value[1]).format("YYYY-MM-DD");
this.$emit("update:startDate", startDate);
this.$emit("update:endDate", endDate);
this.callback && this.callback();
}
}
}
}),
createElement(
"span",
{
slot: "reference"
},
[
column.label,
createElement("i", {
class: this.filterIcon,
style: {
marginLeft: "4px"
}
})
]
)
]
)
]
);
}
}
};
</script>
新版本的实现
这个版本里面直接用了dayjs处理了时间,如果不需要处理,直接去掉对应的地方就可。还有pug,可以直接转,网上有在线的工具。
<template lang='pug'>
el-table-column(:align="align", :prop="prop", :header-align="headerAlign", :label="label", :width="width", :fixed="fixed", v-if='show')
template(slot="header", slot-scope="scope")
el-popover.popover(:disabled="!renderType", placement="bottom-start", :ref="'popover'+scope.$index", :width="renderWidth", trigger="click")
el-input(v-show="renderType === 'input'" ,v-model="value", @change="handlerInput", :placeholder="placeholder")
el-select(v-show="renderType === 'select'", :isClear="isClear", @change="handlerSelect", v-model="value", :placeholder="placeholder")
el-option(:label="item.label", :value="item.value", :key="item.value", v-for="item in selectList")
el-date-picker(v-show="renderType === 'date'", v-model="value", @change="handlerDate", type="date", :width="renderWidth", :placeholder="placeholder")
el-date-picker(v-show="renderType === 'datetime'", v-model="value", @change="handlerDate", type="daterange", range-separator="至", start-placeholder="开始日期", end-placeholder="结束日期")
div(slot="reference", :class="renderType?'popover-ref':''", :style="color")
span {{label}}
i(v-show="renderType", :class="filterIcon")
template(slot-scope="scope")
slot(:row="scope.row", :$index="scope.$index")
el-tooltip(:content="formatter(scope.row,scope.row[prop])",placement="top", v-show='isMore')
span.ellipsis {{scope.row[prop] | substring}}
span.ellipsis(v-show='!isMore') {{formatter(scope.row,scope.row[prop])}}
</template>
<script>
import moment from 'dayjs'
export default {
name: "el-table-column-pro",
props: {
fixed: {
type: String,
default: null
},
prop: {
type: String
},
label: {
type: String
},
width: {
type: Number
},
renderType: {
type: String,
validator: value => ['date', 'input', 'select', 'datetime'].includes(value)
},
placeholder: {
type: String
},
renderWidth: {
type: String,
default: '350px'
},
param: {
type: String,
default: ''
},
startDate: {
type: String
},
endDate: {
type: String
},
selectList: {
type: Array
},
isClear: {
type: Boolean,
default: true
},
visible: {
type: Boolean,
default: true
},
filterIcon: {
type: String,
default: 'el-icon-search'
},
callback: {
type: Function
},
formatter: {
type: Function,
default: (row,cellValue) => cellValue?cellValue.toString():''
},
align: {
type: String,
default:'center'
},
headerAlign: {
type: String,
default:'center'
},
page: {
type: Number
},
isMore: {
type: Boolean,
default: false
}
},
filters: {
substring(value){
if(value){
if(value instanceof String){
return `${value.substring(0,10)}...`
}
return value
}
return ''
}
},
watch: {
'param'(val) {
this.value = val
this.color = val ? 'color:#20a0ff' : ''
},
'startDate'(val) {
this.color = val ? 'color:#20a0ff' : ''
this.value[0] = new Date(val)
},
'endDate'(val) {
this.color = val ? 'color:#20a0ff' : ''
this.value[1] = new Date(val)
}
},
data() {
return {
value: this.startDate || this.endDate ? [new Date(this.startDate), new Date(this.endDate)] : this.param,
color: this.param || this.startDate || this.endDate ? 'color:#20a0ff' : '',
show: this.visible
}
},
methods: {
toggle(visible) {
this.show = visible
},
handlerInput(value) {
this.$emit('update:param', value)
this.$emit('update:page', 0)
this.color = value ? 'color:#20a0ff' : ''
this.callback()
},
handlerSelect(value) {
this.$emit('update:param', value)
this.$emit('update:page', 0)
this.color = value ? 'color:#20a0ff' : ''
this.callback()
},
handlerDate(value) {
if (value) {
if (this.renderType === 'date') {
this.$emit('update:param', moment(value).format('YYYY-MM-DD'))
this.$emit('update:page', 0)
this.color = value ? 'color:#20a0ff' : ''
this.callback()
} else {
this.color = value ? 'color:#20a0ff' : ''
const startDate = moment(value[0]).format('YYYY-MM-DD')
const endDate = moment(value[1]).format('YYYY-MM-DD')
this.$emit('update:param', startDate + '~' + endDate)
this.$emit('update:startDate', startDate)
this.$emit('update:endDate', endDate)
this.$emit('update:page', 0)
this.callback()
}
} else {
if (this.renderType === 'date') {
this.$emit('update:param', value)
this.$emit('update:page', 0)
this.color = value ? 'color:#20a0ff' : ''
this.callback()
} else {
this.color = value ? 'color:#20a0ff' : ''
this.$emit('update:param', '')
this.$emit('update:startDate', '')
this.$emit('update:endDate', '')
this.$emit('update:page', 0)
this.callback()
}
}
}
}
}
</script>
<style lang="stylus" scoped>
.popover-ref {
cursor: pointer;
padding: 0;
}
.popover
display flex
justify-content center
align-items center
</style>
<!-- index.js -->
import ElTableColumnPro from './ElTableColumnPro'
ElTableColumnPro.install = function(Vue) {
Vue.component(ElTableColumnPro.name, ElTableColumnPro);
};
export default ElTableColumnPro;
安装
import ElTableColumnPro from 'components/ElTableColumnPro/index'
...
...
...
Vue.use(ElTableColumnPro)
使用
<el-table :data="bankFlow" style="width:100%" stripe>
<el-table-column-pro :visible="showMore" prop="transactionId" label="流水号" :width="120"> </el-table-column-pro>
<el-table-column-pro prop="clientCode" label="客户代码 " :width="120" placeholder="请输入客户代码" :callback="requestTransactionLogs" renderType="input" :param.sync="request_params.clientCode"> </el-table-column-pro>
<el-table-column-pro prop="eventTypeName" label="事件 " placeholder="请选择事件" :selectList="listEventEnum" :callback="requestTransactionLogs" renderType="select" :param.sync="request_params.event" :width="100"> </el-table-column-pro>
<el-table-column-pro prop="createTime" :callback="requestTransactionLogs" :startDate.sync="request_params.startDate" :endDate.sync="request_params.endDate" :formatter="$timeformat" label="时间" renderType="date" :width="180" ></el-table-column-pro>
</el-table>
<el-table :data="lists.content" v-loading="loading" @row-dblclick="detail" >
<el-table-column-pro :width="120" prop="clientCode" label="客户代码 " align="center" header-align="center" placeholder="请输入客户代码" :callback="getLists" renderType="input" :param.sync="params.clientCode"></el-table-column-pro>
<el-table-column-pro label="内容 " placeholder="请输入内容" :callback="getLists" renderType="input" :param.sync="params.content">
<template slot-scope="scope">
<pre>{{scope.row.content}}</pre>
</template>
</el-table-column-pro>
<el-table-column-pro prop="userName" :width="100" label="记录人 " align="center" header-align="center" placeholder="请输入记录人" :callback="getLists" renderType="input" :param.sync="params.userName"></el-table-column-pro>
<el-table-column prop="createTime" width="150" label="记录时间" align="center" header-align="center" :formatter="$dateTimeFormat"></el-table-column>
</el-table>
注释就不挨着打了....
如果有问题,联系方式Q121116111,在的话就能看到。