低代码不只是少写代码而已:代码写得少,bug也就越少(正所谓“少做少错”),因此开发环节的两大支柱性工作“赶需求”和“修bug”就都少了;要测的代码少了,那么测试用例也可以少写不少
1.提高开发效率 2.减少开发成本 3.维护性更高
后台管理系统中频繁出现列表,普通开发代码重复且枯燥,而且可读性差密密麻麻的 一个列表页写上小千行
我们需要解决这个问题,达到方便便捷切代码统一 ,维护方便。

这是一个普通的列表页 在后台管理系统中这种页面数不胜数
这里以element为例 我想法是二次封装组件,将整个页面看成一个大组件,组件中分为三个模块,一个filterHeader、Xtabel(包含footer分页)、
附加代码
<template>
<div class="x-table">
<el-table border ref="multipleTable" :data="tableData" tooltip-effect="dark" style="width: 100%" @select="handleSelectRow" @select-all="handleSelectAll" @selection-change="handleSelectionChange" @filter-change="handleFilterChange">
<el-table-column type="selection" width="55" v-if="isSelection"></el-table-column>
<el-table-column v-for="item in columns" :key="item.label" :label="item.label" :prop="item.prop" :width="item.width ? item.width : ''" :column-key="item.label" :filter-multiple='!item.fitersType' :filters="item.filters" filter-placement="" :fixed="item.fixed">
<template slot-scope="scope">
<template class="operate-btn" v-if="item.operates">
<el-button size="mini" v-for="btn in item.operates" :key="btn.event" :type="btn.type ? btn.type : ''" v-permission="btn.permission" v-show="showBtn(scope.row.isShow, btn.text)" @click="handleRowOperate(scope.$index, scope.row, btn.event,btn.text)">{{btn.text}}</el-button>
</template>
<template v-else>
<el-input class="edit-input" size="small" v-model="scope.row[item.prop]" v-if="item.cellEdit === 'input'" />
<el-cascader v-else-if="item.cellEdit==='cascader'" @change='changeel($event, scope.row, item.prop)' :options="scope.row.serverUserList" v-model='scope.row.echoUserList' :props="props" clearable></el-cascader>
<el-select placeholder="请选择" v-model="scope.row[item.prop]" @change="handleCellChange($event, scope.row, item.prop)" @focus="handleCellFocus($event, scope.row, item.prop)" v-else-if="item.cellEdit === 'select'">
<el-option v-for="(options,index) in item.options" :key="index" :label="options.label" :value="options.value">
</el-option>
</el-select>
<el-date-picker v-model="scope.row[item.prop]" type="date" value-format="yyyy-MM-dd" placeholder="请选择时间" v-else-if="item.cellEdit === 'date'" />
<img v-else-if="item.cellEdit === 'img'" :src="scope.row[item.prop]" alt="" style="width:80px;height:80px;" />
<span v-else>{{ scope.row[item.prop] }}</span>
<slot :name="scope.row['slot']" v-if="item.prop === scope.row['slot']"></slot>
</template>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
// import Sortable from 'sortablejs'
export default {
name: "x-table",
data() {
return {
props: {
multiple: true
},
};
},
props: {
showSelect: {
type: Boolean,
default: false
},
isSelection: {
type: Boolean,
default: false
},
tableData: {
type: Array,
default: function () {
return [
// {
// id: "1",
// userName: '12345',
// },
// {
// id: "2",
// userName: '12345',
// },
// {
// id: "3",
// userName: '12345',
// }
]
}
},
columns: {
type:Array,
default: function () {
return [
{
label: '用户名',//表格头
prop: 'userName'//绑定的字段
},
{
label: '用户id',
prop: 'id'
},
]
}
}
},
created() {},
components: {},
mounted() {},
methods: {
// 除权限外的特殊显示隐藏需求
showBtn(show, text) {
if (show === 0) {
return text !== '审批' && text !== '收款'
} else {
return true
}
},
// 列筛选条件
handleFilterChange(filterObj) {
this.$emit('filter', filterObj)
},
// 选择行
handleSelectionChange(val) {
this.$emit('select', val)
// console.log(val)
},
handleSelectRow(selection, row) {
this.$emit('row-select', selection, row)
},
handleSelectAll(val) {
this.$emit('all-select', val)
},
// 操作行
handleRowOperate(index, row, event, text) {
// console.log(text);
// console.log(text);
// console.log(text);
this.$emit('edit', event, row, index, text)
// this.$router.push('/order-detail/index')
},
// 操作格子
handleCellFocus(val, row, prop) {
this.$emit('handleCellFocus', val, row, prop)
},
handleCellChange(val, row, prop) {
// console.log(val, row)
this.$emit('cellChange', val, row, prop)
},
changeel(val, row, prop) {
// console.log(val, row)
this.$emit('changeel', val, row, prop)
},
toggleRowSelection(row) {
console.log('测试', row)
this.$refs.multipleTable.clearSelection();
this.tableData.forEach(row => {
if (row.select == 1) {
this.$refs.multipleTable.toggleRowSelection(row);
}
})
},
rowDrop() {
const tbody = document.querySelector('.el-table__body-wrapper tbody')
const _this = this
Sortable.create(tbody, {
onEnd({
newIndex,
oldIndex
}) {
const currRow = _this.tableData.splice(oldIndex, 1)[0]
_this.tableData.splice(newIndex, 0, currRow)
}
})
},
// columnDrop() {
// const _this = this
// const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
// this.sortable = Sortable.create(wrapperTr, {
// animation: 180,
// delay: 0,
// onEnd: evt => {
// console.log(evt)
// const oldItem = this.columns[evt.oldIndex]
// this.columns.splice(evt.oldIndex, 1)
// this.columns.splice(evt.newIndex, 0, oldItem)
// }
// })
// }
}
};
</script>
<style scoped>
.x-table {
/* max-width: 70%; */
}
.demo-table-expand {
font-size: 0;
}
.demo-table-expand label {
width: 90px;
color: #99a9bf;
}
.demo-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 35%;
}
</style>
<template>
<!-- filterHeader 组件 -->
<el-form :inline="true" class="demo-form-inline">
<el-form-item :label="item.label"
v-for="item in filterOptions"
:key="item.label"
>
<el-input
v-model="item.value"
:placeholder="item.placeholder"
v-if="item.type === 'input'" />
<el-select
v-model="item.value"
:placeholder="item.placeholder"
:filterable="item.filterable"
@change="onItemChange($event, item.label)"
v-if="item.type === 'select'">
<el-option
v-for="options in item.options"
:key="options.label"
:label="options.label"
:value="options.value" />
</el-select>
<el-date-picker
v-model="item.value"
type="date"
value-format="yyyy-MM-dd"
:placeholder="item.placeholder"
v-if="item.type === 'date'" />
<el-date-picker
v-model="item.value"
type="month"
value-format="yyyy-MM"
:placeholder="item.placeholder"
v-if="item.type === 'month'" />
<el-date-picker
v-model="item.value"
type="daterange"
range-separator="—"
value-format="yyyy-MM-dd"
start-placeholder="开始时间"
end-placeholder="结束时间"
v-if="item.type === 'daterange'" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onFilter">查询</el-button>
<el-button @click="onReset">重置</el-button>
</el-form-item>
</el-form>
</template>
<script>
export default {
name: 'filter-header',
data () {
return {
}
},
props: {
filterOptions: Array
},
components: {},
mounted () {
},
methods: {
onFilter() {
this.$emit('filter')
},
onReset() {
this.$emit('reset')
},
onItemChange(val, prop) {
this.$emit('item-change', val, prop)
}
},
}
</script>
<style scoped>
</style>
<template>
<div class="order">
<filter-header v-if="filterOptions && filterOptions.length" :filterOptions="filterOptions" @item-change="onFilterItemChange" @filter="onConditionalQuery" @reset="onConditionalReset" />
<el-row type="flex" justify="end" class="order-operate">
<!-- <el-button type="primary" @click="onDownload" >下载</el-button>
<el-button type="primary" @click="onPrint">打印</el-button>-->
<el-button :loading="isExporting" type="primary" @click="onExport">导出</el-button>
<el-button type="primary" @click="onAdd" >添加</el-button>
</el-row>
<x-table :showSelect="showSelect2" :columns="columns" :tableData="tableData" @changeel='changel' @edit="onItemEdit" @filter="onColumnsFilter" @cellChange="onCellChange" @handleCellFocus="handleCellFocus" />
<el-row type="flex" justify="end" class="pagination-wrap">
<el-pagination background layout="prev, pager, next" :current-page.sync="currentPage" :total="totalSize" @current-change="onPageChange" />
</el-row>
</div>
</template>
<script>
import FilterHeader from "@/components/FilterHeader";
import XTable from "@/components/XTable";
export default {
data() {
return {
currentPage: 1,
isSelection: true,
radio: null
};
},
props: {
showSelect2: {
type: Boolean,
default: false
},
isExport: {
type: Boolean,
default: true,
},
isRadio: {
type: Boolean,
default: false,
},
isExporting: {
type: Boolean,
default: false,
},
totalSize: Number,
filterOptions: Array,
columns: Array,
tableData: Array,
tableOperate: Array,
},
components: {
FilterHeader,
XTable,
},
created() {},
methods: {
tohelp() {
this.$emit('toHelp', '')
},
radioChange(val) {
console.log(val)
this.$emit("radioChange", val);
},
handleCellFocus(val, row) {
this.$emit("handleCellFocus", val, row);
},
onCellChange(val, row, prop) {
console.log(row);
this.$emit("cell-change", val, row, prop);
},
changel(val, row, prop) {
this.$emit("changel", val, row, prop);
},
onFilterItemChange(val, prop) {
this.$emit("filter-item-change", val, prop);
},
onConditionalQuery() {
this.$emit("conditional-query");
},
onConditionalReset() {
this.$emit("conditional-reset");
},
onColumnsFilter(val) {
this.$emit("columns-filter", val);
console.log("列筛选", val);
},
onItemEdit(event, row, index, text) {
// console.log(text);
this.$emit(event, row, index, text);
},
onPageChange(page) {
this.$emit("page-change", page);
},
onDownload() {
console.log("download");
},
onPrint() {
console.log("print");
},
onExport() {
this.$emit("export");
},
onSetting() {
this.$router.push({
name: "table-setting",
query: {
formType: this.formType
},
});
},
onAdd() {
this.$emit("add");
console.log("add");
},
},
};
</script>
<style scoped>
.order-operate {
margin-bottom: 30px;
}
.pagination-wrap {
margin-top: 30px;
}
</style>
最后是完整的tabelPage的代码
一套操作下来以后每个列表页只需要两分钟搞定 方便快捷
再配合 mixin混入下复用新高的函数(比如:分页 查询 重置 getlist 直接就想起来了)
版权声明:本文为weixin_46744852原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。