1、话不多说先看效果
主要实现功能:筛选:输入框、下拉框、时间;表格适用:多选、序号、排序、自定义、开关、链接可跳转、输入框、图片、自定义操作按钮(部分页面需要每行显示按钮不用所以大家按需添加)、常规操作按钮(每行操作按钮都相同无其他需求)、设置行背景色、分页
2、本文部分原创,大框架是复制的https://blog.csdn.net/qq_37346639/article/details/115556605这个博客,因为懒的自己写😂,按照需求改为自己所需要格式
3、筛选组件代码
<template>
<div>
<ul class="row-list" v-if="screenConfig.searchShow">
<li v-for="(item,index) in screenConfig.formItem" :key="index">
<label v-if="item.type != 'operationBtn'">{{item.label}}:</label>
<!-- 输入框-->
<el-input v-if="item.type === 'input'" clearable v-model.trim="screenConfig.searchParams[item.prop]"
class="w215" size="small" :placeholder="item.placeholder"></el-input>
<!-- 下拉框-->
<el-select v-if="item.type === 'select'" filterable clearable v-model.trim="screenConfig.searchParams[item.prop]"
:placeholder="item.placeholder" size="small" :multiple="item.multiple" :filterable="item.filterable">
<el-option v-for="selectItem in item.options" :key="selectItem[item.value]" :value="selectItem[item.value]"
:label="selectItem[item.leftLabel]" :disabled="selectItem.disabled">
<span style="float: left">{{ selectItem[item.leftLabel] }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ selectItem[item.rightLabel] }}</span>
</el-option>
</el-select>
<!-- 时间选择器-->
<el-date-picker v-if="item.type === 'datePicker'" clearable v-model="screenConfig.searchParams[item.prop]"
:type="item.dateType" size="small" :value-format="item.format" placeholder="请选择"
range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
</el-date-picker>
<!-- 自定义-->
<slot v-if="item.type == 'custom'" name='customFilter'></slot>
<!-- 按钮-->
<span v-if="item.type == 'operationBtn'" v-for="(operations, index) in item.operation" :key="index">
<el-button v-if="operations.isShow" :type="operations.btnType" :icon="`iconfont ${operations.icon}`"
@click="screenBtn(operations)" class="screen-btn" :disabled="operations.disabled"
size="mini">{{operations.label}}
</el-button>
</span>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "PublicFilter",
props: {
screenConfig: {
type: Object,
required: true
},
},
data() {
return {};
},
methods: {
// 操作按钮
screenBtn(data) {
this.$emit("screenBtn",data)
}
},
}
</script>
<style scoped lang="less">
.screen-btn {
margin-right: 10px;
}
.row-list {
li{
margin-bottom: 15px;
float: left;
margin-right: 15px;
min-height: 32px;
line-height: 32px;
}
}
</style>
4、表格组件代码
<template>
<div>
<el-table size="medium" :data="tableData" :stripe="false" :border="false" :fit="true"
:header-cell-style="{background:columnObj.headerBgColor,color: columnObj.headerColor,height: columnObj.headerHigh}"
:highlight-current-row="columnObj.highlight" :row-class-name="tableRowClassName"
@row-click="rowClick" :row-style="tableRowStyle" @sort-change="sortChange">
<!-- 选择框是否开启,selectable控制是否单行禁用 -->
<el-table-column v-if="columnObj.selection" type="selection" :selectable="selectable" :align="columnObj.align || 'center'"></el-table-column>
<el-table-column v-if="columnObj.serialNumber" type="index" label="序号" :align="columnObj.align || 'center'" width="50"></el-table-column>
<!-- 普通列 -->
<el-table-column v-for="(column,columIndex) in columnObj.columnData" :key="columIndex" :prop="column.prop"
:label="column.label" :width="column.width" :fixed="column.fixed" :align="columnObj.align || 'center'"
:sortable="column.sortable" :index="columIndex" show-overflow-tooltip>
<template slot-scope="{row,$index}">
<!-- 默认展示 -->
<span v-if="column.type == 'text'" :style="{color:row[column.colorName]}">
{{row[column.prop]}}
</span>
<!-- 标签类型 -->
<span v-if="column.type == 'tag'">
<el-tag :type="row[column.tagType]">{{row[column.prop]}}</el-tag>
</span>
<!-- 自定义内容 -->
<slot v-if="column.type == 'ownDefined'" name='ownDefined' :row="row,column"></slot>
<!-- switch开关 -->
<el-switch v-if="column.type == 'switch'" v-model="row[column.prop]"
:inactive-text="row[column.prop] ? column.openText:column.closeText"
@change="switchChange(row,$index,column.prop)"></el-switch>
<!-- 图片展示 -->
<el-image v-if="column.type == 'image'" style="width: 50px; height: 50px" :src="row[column.prop]" fit="cover" :preview-src-list="[row[column.prop]]"></el-image>
<!-- url-->
<div v-if="column.type == 'url'">
<a v-if="row[column.urlName]" :href="row[column.urlName]" target="_blank" class="url">{{row[column.prop]}}</a>
<span v-else>{{row[column.prop]}}</span>
</div>
<!-- 可编辑-->
<el-input v-if="column.type == 'editRow'" v-model="row[column.prop]" :disabled="row[column.editRow]"
@blur="editInputBlur(row,$index,column.prop,columIndex)" size="mini"></el-input>
<!-- 自定义操作按钮,每行不一样-->
<span v-if="column.type == 'customAction'" v-for="(operations, index) in row[column.prop]" :key="index">
<el-button v-if="operations.isShow" type="text"
@click="rowOperation(row,$index,operations.type)" :style="{color:operations.color}"
size="small">{{operations.label}}
</el-button>
</span>
<!-- 常规操作按钮-->
<span v-if="column.type == 'routineAction'" v-for="(operations, index) in column.operation" :key="index">
<el-button v-if="operations.isShow" type="text"
@click="rowOperation(row,$index,operations.type)" :style="{color:operations.color}"
size="small">{{operations.label}}
</el-button>
</span>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="page_div" :style="{textAlign: pageObj.position || 'center'}" v-if="pageObj.show">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
:hide-on-single-page="false" :current-page="pageObj.pageNo" :pager-count="7"
:page-sizes="[10, 15, 20, 30,50]" :page-size="pageObj.pageSize" background
layout="total,sizes,prev, pager, next" :total="pageObj.total">
</el-pagination>
</div>
</div>
</template>
<script>
export default {
name: 'public-table',
props: {
tableData: {
type: Array,
required: true
},
columnObj: {
type: Object,
required: true
},
pageObj: {
type: Object,
required: true
}
},
data() {
return {
}
},
methods: {
// 控制单行是否可用
selectable(row, index) {
if (row.switchs) {
return true;
}
this.$emit("selectable", row, index)
},
// 操作按钮
rowOperation(row, $index, now) {
this.$emit("rowOperation", row, $index, now)
},
// switchChange调用
switchChange(row, $index, prop) {
this.$emit("switchChange", row, $index, prop);
},
// 行样式
tableRowStyle({row}) {
if(row.styleData) {
return {'background': `${row.styleData.bgColor}`,'color':`${row.styleData.fontColor}`};
}
},
// 行的 className 的回调方法
tableRowClassName({row, rowIndex}) {
row.rowIndex = rowIndex;
},
// 点击行
rowClick(row, column, event) {
this.$emit("rowClick", row, column, event);
},
// 可编辑input失去焦点
editInputBlur(row, $index, prop, columIndex) {
this.$emit('editInputBlur', row, $index, prop, columIndex);
},
// 远程排序
sortChange({column, prop, order}) {
// ascending上 descending下
this.$emit('sortChange', column, prop, order);
},
// 条数变化
handleSizeChange(e) {
this.$emit('handleSizeChange', e);
},
// 页码变化
handleCurrentChange(e) {
this.$emit('handleCurrentChange', e);
}
}
}
</script>
<style lang="less" scoped>
.el-button {
margin: 0 6px;
}
.page_div {
padding: 15px 0;
}
.url {
color: #3d8de0;
cursor: pointer;
}
/deep/.el-table__body tr.current-row>td.el-table__cell {
background-color: #a8b9cc;
}
/deep/.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell {
color: #606266;
}
</style>
5、全局引入组件
main.js页面全局引入组件或单页面引入看需求,我是全局引入
import { PublicTable,PublicFilter } from '@/components';
Vue.component(PublicTable.name,PublicTable);
Vue.component(PublicFilter.name,PublicFilter);
文件目类
[图片上传失败...(image-70848a-1662602567621)]
components>index.js
import PublicTable from '@/components/PublicTable';
import PublicFilter from '@/components/PublicFilter';
export {
PublicTable,PublicFilter
};
6、父组件使用
<template>
<div class="box">
<el-card shadow="never">
<public-filter :screenConfig="screenConfig" @screenBtn="screenBtn">
<template slot='customFilter'>
<el-radio-group v-model="screenConfig.searchParams.aaa" class="radio">
<el-radio :label="3">备选项</el-radio>
<el-radio :label="6">备选项</el-radio>
<el-radio :label="9">备选项</el-radio>
</el-radio-group>
</template>
</public-filter>
</el-card>
<el-card shadow="never" class="mt-20">
<public-table :tableData="tableData" :columnObj="columnObj" :pageObj="pageObj" @rowOperation="rowOperation"
@switchChange="switchChange" @editInputBlur="editInputBlur" @rowClick="rowClick"
@sortChange="sortChange"
@handleSizeChange="handleSizeChange" @handleCurrentChange="handleCurrentChange">
<template slot='ownDefined' slot-scope="{row,column}">
<p>
<span v-if="row.names" :class="`iconfont ${row.names.icon}`" :style="{fontSize: row.names.fontSize,color: row.names.color}"></span>
{{row.name}}
</p>
<p>{{row.address}}</p>
</template>
</public-table>
</el-card>
</div>
</template>
<script>
export default {
data() {
return {
// 筛选配置
screenConfig:{
searchShow: true, //筛选是否显示
formItem: [{
type: "input",
prop:'input',
label: "姓名",
placeholder:'请输入姓名'
}, {
type: "select",
prop: "parkingType",
label: "类型",
value:"id",
leftLabel:"name",
rightLabel:"gender",
multiple: false,
filterable: true,
options: [{
id: '1',
name: '张三',
gender: '男',
},{
id: '2',
name: '李四',
disabled: true
},{
id: '3',
name: '李四',
gender: '女',
}],
placeholder:'请选择数据'
}, {
type: "datePicker",
prop: "data",
label: "导出时间",
format: "yyyy-MM-dd", //数据格式'yyyy-MM-dd'、timestamp(时间戳)
dateType: "datetimerange", //显示类型(常用类型daterange、date、datetime) year年、month月、date日期、dates多个日期、 week周、datetime日期和时间点、datetimerange日期和时间范围、 daterange日期范围、monthrange月份范围
placeholder: '请选择',
}, {
type: "custom",
prop: "aaa",
label: "自定义筛选",
}, {
type: "operationBtn",
prop: "data",
operation: [{
btnType: "primary", //primary蓝色、success绿色、warning橘黄、danger红色、 info灰色、text文本
type: 'cx',
label: "查询",
isShow: true,
disabled: false,
icon: 'icon-cry',
},{
btnType: "danger", //primary蓝色、success绿色、warning灰色、danger橘黄、 info红色、text文本
type: 'cz',
label: "重置",
isShow: true,
disabled: true,
icon:'icon-atm-away'
}]
}]
},
// 表头配置
columnObj: {
selection: true,// 选择框
serialNumber: true,// 序号
highlight: false,// 当前行是否高亮
align: 'center',// 对齐方式
headerBgColor: '',// 表头背景色
headerColor: '',// 表头字体颜色
headerHigh: '55px',// 表头高
// columnObj
// selection(是否有多选框):true显示,false隐藏
// serialNumber(是否有序列号):true显示,false隐藏
// align(行文字对其方式):left左,right右,center居中
// highlight(当前行是否高亮)
// headerColor(表头字体颜色)
// headerHigh(表头高):小于55px没有效果
// columnObj>columnData
//type(列类型):text文本,ownDefined自定义 ,switch开关,url链接,editRow可编辑,image图片,customAction自定义操作,routineAction常规操作
//prop(参数),label(列名),width(宽度)
//sortable(是否支持排序):true开启排序,false关闭排序'custom'远程排序
//openText,closeText(开关开启/关闭名称),urlName(url地址对应参数):参数为空时只展示文字不可跳转
//editRow(当前行是否可编辑和type为editRow对应):false可编辑,true不可编辑
//colorName 控制文字颜色字段名
columnData: [{
type:'text',
prop: "school",
label: "默认样式",
width: "",
colorName: "color",
}, {
type:'tag',
prop: "tag",
tagType: "tagType",
label: "标签类型",
width: "",
}, {
type:'text',
prop: "id",
label: "可以排序",
width: "",
sortable: true,
}, {
type:'ownDefined',
prop: "aaa",
label: "自定义内容",
width: "",
}, {
type:'switch',
prop: "switchs",
label: "switch开关",
width: "",
openText: "打开", //type='switch' 打开时的文字描述
closeText: "关闭", //type='switch' 关闭时的文字描述
}, {
type:'url',
prop: "name2",
label: "可跳转",
urlName: "url", //type='url',跳转地址名称(按需返回)
width: "",
}, {
type:'editRow',
prop: "name",
label: "可编辑",
width: "",
editRow: 'editRow',
},{
type:'image',
prop: "img",
label: "图片",
width: "",
}, {
type:'customAction',
label: "自定义操作",
width: "180",
prop: "operation",
}, {
type:'routineAction',
label: "常规操作",
width: "180",
operation: [{
type: "cg",
label: "常规",
color: '',
isShow: true,
}]
}],
},
// 表格数据
// editRow(可编辑行是否可操作true/false)
// styleData(Object类型,行样式,背景色、字体颜色等)
//operation(Array类型,表头type=‘customAction’时按钮配置):type类型,label按钮名,color按钮颜色,isShow是否显示(true/false),
// tagType标签类型(success绿/info灰/warning橘黄/danger红/)返回空为默认值蓝色
tableData: [{
id: '1',
school: '北京大学',
name: '王小虎',
tag: '标签一',
tagType: 'success',
names:{
name: '王小虎',
icon:'icon-phone',
fontSize: '15px',
color:"red",
},
editRow: true,
address: '上海市普陀区金沙江路 1518 弄',
switchs: true,
img: '',
name2: '张三',
icon: 'icon-phone',
// 行样式
styleData: {
bgColor: '#878787',
fontColor: '#fff',
},
operation: [{
type: "edit",
label: "编辑",
color: '#be147d',
isShow: true,
}, {
type: "delete",
label: "删除",
color: 'red',
isShow: false,
}, {
type: "see",
label: "查看",
color: '#d77000',
isShow: true,
}],
}, {
id: '2',
school: '天津大学',
name: '王小虎',
tag: '标签二',
tagType: '',
names:{
name: '王小虎2',
icon:'icon-cry',
fontSize: '18px',
color:"blue",
},
address: '上海市普陀区金沙江路 1517 弄',
switchs: true,
img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
name2: '李四',
url:'https://www.baidu.com/',
}, {
id: '3',
school: '北京体育',
tag: '标签三',
tagType: 'info',
color: 'red',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄',
switchs: false,
name2: '王五',
img: '',
operation: [{
type: "edit",
label: "编辑",
color: '#67C23A',
isShow: true,
}, {
type: "delete",
label: "删除",
color: 'red',
isShow: true,
}, {
type: "see",
label: "查看",
color: '',
isShow: true,
}]
}, {
id: '4',
school: '河北师范大学',
name: '王小虎',
tag: '标签四',
tagType: 'warning',
address: '上海市普陀区金沙江路 1516 弄',
switchs: true,
name2: '赵六',
url:'https://www.baidu.com/',
img: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
}],
//分页配置
pageObj: {
show: true, //是否显示
position: "right", //位置
total: 100,
pageNo: 1,
pageSize: 10
},
}
},
created(){
this.$set(this.screenConfig,'searchParams',{})
},
methods: {
screenBtn(data) {
},
rowOperation(row, $index, now) {
console.log(row, $index, now)
},
switchChange(row, $index, prop) {
console.log(row, $index, prop)
},
rowClick(row, column, event) {
// 点击行触发,编辑点击的所在列,排除selection选择框
// if (column.type != 'selection') {
// this.columnObj.columnData[column.index].editRow = row.rowIndex;
// }
},
sortChange(column, prop, order) {
// console.log(column, prop, order)
},
editInputBlur(row, $index, prop, columIndex) {
// console.log(row, $index, prop, columIndex)
// this.columnObj.columnData[columIndex].editRow = -1;
},
//页码变化
handleCurrentChange(e) {
this.pageObj.pageNo = e;
},
//条数变化
handleSizeChange(e) {
this.pageObj.pageSize = e;
this.pageObj.pageNo = 1;
},
},
}
</script>
<style>
.box {
background: #f4f4f4;
padding: 2% 1%;
box-sizing: border-box;
}
</style>