做后台管理项目期间,有非常多的表格表单的操作,所以想着封装一个组件完成对表格的增删改查操作,目前正在完善中,也请大佬们多多指教,代码如下。
子组件tempale 代码1-1
//子组件template部分
<template>
<div>
<el-table :data="tableList" style="width: 100%" border :header-cell-style="headerCellStyle" empty-text="暂无数据">
<el-table-column v-for="(prop,index) in propsKey" :key="index" :label="!keyLabel[index]?prop:keyLabel[index]" align="center">
<template slot-scope="scope">
<span>{{scope.row[prop]?scope.row[prop]:'暂无数据'}}</span>
</template>
</el-table-column>
<el-table-column v-if="showPermission" align="center">
<template slot-scope="scope">
<el-button v-if="permissionList.indexOf('R')!=-1" size="mini" @click="handleRead(scope.$index, scope.row)">Read</el-button>
<el-button v-if="permissionList.indexOf('D')!=-1" size="mini" @click="handleDelect(scope.$index, scope.row)">Delect</el-button>
<el-button v-if="permissionList.indexOf('U')!=-1" size="mini" @click="handleUpdate(scope.$index, scope.row)">Update</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog title="修改" :visible.sync="dialogVisible" :width="dialogWidth" v-if="dialogVisible" :before-close="dialogCloseHandle">
<el-form :model="emitFrom">
<el-form-item v-for="(item,index) in propsKey" :key="index" :label="!keyLabel[index]?item:keyLabel[index]" :label-width="dialogLabelWidth">
<slot :name="item+'-insert'" :modelKey="emitFrom" :modelValue="item" :dialogInsertWidth="dialogInsertWidth">
<el-input v-model="emitFrom[item]" :style="{width:dialogInsertWidth}"></el-input>
<!-- 插槽,from-item默认是输入框,可自定义from-item-->
</slot>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogCloseHandle">取 消</el-button>
<el-button type="primary" @click="dialogSucceedHandle">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
子组件srcipt 代码1-2
export default {
name: "FullTable",
props: {
tableList: {//接收表单数据
type: Array,
required: true,
},
keyLabel: { //表单key对应的label,用于展示table表头的label
type: Array,
},
permissions: {//可进行的操作,可选CRUD
type: String,
default: "",
},
showExclude: {//需要在展示中排除的数据项,例如后端返回的数据有id,不需要展示,可以排除
type: Array,
default: () => [],
},
permissionExclude: {//在进行增删改查时候不能修改的数据项,例如在dialog中账号可能需要展示,但不能修改
type: Array,
default: () => [],
},
headerCellStyle: {//表头样式 el-table默认属性//还有很多默认属性目前没加,等后续开发
type: Object,
default: () => ({ background: "#f5f7fa", color: "#606266" }),
},
dialogWidth: {//弹窗宽度
type: String,
default: "35%",
},
dialogLabelWidth: {//弹窗内from子项label宽度
type: String,
default: "60px",
},
dialogInsertWidth: {//弹窗内from子项输入框的宽度
type: String,
default: "250px",
},
},
data() {
return {
permissionList: [], //权限列表数组
dialogVisible: false, //dialog状态
emitFrom: "", //弹框From数据
};
},
created() {
this.managePermissions();
},
computed: {
propsKey() {
//props对象数组里面的key,排除不需要展示的key后返回
let res = [];
Object.keys(this.tableList[0]).forEach((key) => {
if (this.showExclude.indexOf(key) == -1) {
res.push(key);
}
});
return res;
},
showPermission() {
return this.permissionList.reduce((status = false, permission) => {
return (status = status || "URD".indexOf(permission) >= 0);
}, "");
},
},
methods: {
managePermissions() {
this.permissionList = this.permissions.toUpperCase().split("");
},
handleRead(index, row) {},
handleDelect(index, row) {
this.$emit("handleDelect", row);
},
handleUpdate(index, row) {
this.emitFrom = JSON.parse(JSON.stringify(row));
this.dialogVisible = true;
},
dialogCloseHandle() {
this.dialogVisible = false;
this.emitFrom = "";
this.dialogKey = [];
},
dialogSucceedHandle() {
this.dialogVisible = false;
this.$emit("handleUpdate", this.emitFrom);
this.emitFrom = "";
this.dialogKey = [];
},
},
};
父组件如下 代码2-1
<template>
<div>
<FullTable :tableList="testTableList" :keyLabel="label" permissions="curd" :showExclude="['id']" @handleDelect="handleDelect" @handleUpdate="handleUpdate">
<template #sex-insert="{modelKey,modelValue,dialogInsertWidth}">
<el-select v-model="modelKey[modelValue]" :style="{'min-width':dialogInsertWidth}" placeholder="请选择">
<el-option v-for="item in options" :key="item" :label="item" :value="item">
</el-option>
</el-select>
</template>
</FullTable>
</div>
</template>
<script>
import FullTable from "@/views/demo/index.vue";
export default {
components: { FullTable },
data() {
return {
options: ["男", "女"],
testTableList: [
{ name: "zsy", age: 18, sex: "男", id: "1029", demo: 10 },
{ name: "zsy", age: 18, sex: "男", id: "1028", demo: 10 },
{ name: "zsy", age: 18, sex: "男", id: "1027", demo: 10 },
{ name: "zsy", age: 18, sex: "男", id: "1024", demo: 10 },
],
label: ["姓名", "年龄", "性别"],
};
},
methods: {
handleDelect(row) {
console.log(row, "---parent component");
},
handleUpdate(row) {
this.testFrom.map((item, index) => {
if (item.id === row.id) {
this.$set(this.testFrom, index, row);
}
return item;
});
console.log(this.testFrom, "---handleUpdate");
},
具体使用大概可以这样:
------在父组件中导入
------传入tableList、权限、tablelist里面的所对应的label
这样最基本的用法就出来了
如你需要在dialog的from-item中使用下拉框等你所需要的输入方式,可以用插槽修改默认的输入框,如代码2-1所示。可用作用域插槽获取子组件绑定的值,用modelKey[modelValue]表示,用v-model绑定这个值就可修改。插槽的名字为你想要自定义的from-item的key 和insert拼起来
eg. 如果你要自定义from-item中 sex的默认修改方式,则该插槽的名字应该改为 sex-insert,如代码2-1 第四行所示
下面展示效果
目前组件还未完善。后续将继续完善