- 功能列表
- 全量引入
- 按需引入
- 项目级配置
- CustomizeTable组件
- CustomizePagination组件
- CustomizeSearchBar组件
- CustomizeSwitch组件
- CustomizeForm组件
- CustomizeDialogForm组件
- CustomizePage组件
- CustomizeFormBuilder组件
- 辅助函数
- 常用增删改查页面完整事例(无弹窗)
- 常用增删改查页面完整事例(带弹窗)
- 常用增删改查页面完整事例(带弹窗)单页
功能列表
组件
CustomizeTable, CustomizePagination, CustomizeSearchBar, CustomizeSwitch, CustomizeForm, CustomizeDialogForm, CustomizePage, CustomizeFormBuilder
辅助函数
isEmpty, clean, setValue, deepClone, formatDate, sleep, deepMerge,
自定义样式
select, input, el-radio-group, el-checkbox-group [round]属性
input [no-border]属性
全量引入
import Customize from 'vue-element-customize';
Vue.use(Customize);
传入配置项
Vue.use(Customize, {
CustomizeTable: {},
CustomizePagination: {},
CustomizeSearchBar: {},
CustomizeSwitch: {},
CustomizeForm: {},
CustomizeDialogForm: {},
CustomizeFormBuilder: {},
});
按需引入
组件引入
import { CustomizeTable, CustomizePagination, CustomizeSearchBar, CustomizeSwitch, CustomizeForm, CustomizeDialogForm, CustomizePage, CustomizeFormBuilder } from 'vue-element-customize';
Vue.use(CustomizeTable, {});
Vue.use(CustomizePagination, {});
Vue.use(CustomizeSearchBar, {});
Vue.use(CustomizeSwitch, {});
Vue.use(CustomizeForm, {});
Vue.use(CustomizeDialogForm, {});
Vue.use(CustomizePage);
Vue.use(CustomizeFormBuilder);
辅助函数引入
辅助函数全量引入
import { CustomizeUtils } from 'vue-element-customize';
Vue.use(CustomizeUtils);
辅助函数按需引入
import { isEmpty, clean, setValue, deepClone, formatDate, sleep, deepMerge } from 'vue-element-customize';
Vue.prototype._isEmpty = isEmpty;
Vue.prototype._clean = clean;
Vue.prototype._setValue = setValue;
Vue.prototype._deepClone = deepClone;
Vue.prototype._formatDate = formatDate;
Vue.prototype._sleep = sleep;
Vue.prototype._deepMerge = deepMerge;
自定义样式引入
import 'vue-element-customize/lib/styles/index.scss'
项目级配置
CustomizeTable配置
stripe: Boolean, // true
border: Boolean, // false
size: String, // medium
headerCellStyle: Object, // { backgroundColor: '#f5f7fa', color: '#909399', borderBottom: 0, height: '50px', },
cellStyle: Object, // { borderBottom: 0 },
className: String,
align: String,
CustomizePagination配置
pageSizes: Array, // [10,20,50,100]
layout: String, // 'total, sizes, prev, pager, next, jumper'
align: String, // right
className: String,
pageSize: Number, // 10
CustomizeSearchBar配置
size: String, // medium
className: String, //''
blockButtons: Boolean, // false
showResetButton: Boolean, // true
openEnterSearch: Boolean, // false
searchButtonName: String, // 查询
optionAllName: String, // 全部
CustomizeSwitch配置
defaultColor: Array, // 默认的[打开背景色, 关闭背景色]
className: String,
CustomizeForm配置
size: String, // medium
className: String, //''
showSubmitButton: Boolean, // true
showResetButton: Boolean, // true
submitButtonName: String, // 提交
resetButtonName: String, // 重置
openEnterSubmit: Boolean, // false
optionAllName: String, // 全部
labelWidth: String, // 120px
clearable: Boolean, // true
hideOptionAll: Boolean, // true
CustomizeDialogForm配置
form: Object, // 弹窗内form的配置,同CustomizeForm
size: String, // medium
closeButtonShow: [Boolean, String], // true
closeButtonName: String, // 关闭
className: String, // dialog自定义class
CustomizeTable组件
组件配置
props
data: Array, // 渲染的数据
column: Array, // 表格配置
{
prop: String, // 渲染数据的key值
label: String, // key值对应的表头名
width: String, //宽度
sortable: Function, //排序
formatter: Function, //(row, column, cellValue, index) {}
slot: String, // 传入的slot名
}
size: String,
type: String, // 'index'
headerCellStyle: Function, // ({row, column, rowIndex, columnIndex}) {} '表头样式'
cellStyle: Object,
sortable: Boolean,
stripe: Boolean,
border: Boolean,
className: String,
maxHeight: [String, Number],
align: String, // 'center'
emit
@sortChange //排序
@selectionChange
ref
ref: 'table'
slot
slot before // 默认slot 前
slot after // 默认slot 最后
example
<customize-table
:data="tableData"
:column="tableColumn"
v-loading="tableLoading"
>
<template #slotName>
<el-table-column label="slot-slotName" align="center">
<template #default="{ row }">
<span>{{ _isEmpty(row.status) }}</span>
</template>
</el-table-column>
</template>
<template #after>
<el-table-column label="操作" align="center">
<template #default="{ row }">
<el-button type="primary" size="mini" @click="handleEdit(row.id)">编辑</el-button>
</template>
</el-table-column>
</template>
</customize-table>
data() {
return {
tableLoading: false,
tableData: [],
tableColumn: [
// { type: 'index', index: (index) => (this.current - 1) * this.size + index + 1 },
{ label: '名称', prop: 'name' },
{ label: '属性', prop: 'aaa', width: '100px', w: '100px' },
{ label: '状态', prop: 'status', formatter(row, column, cellValue, index) {
const Enum = {
0: '暂停',
1: '启用',
}
return Enum[cellValue] || '--';
}},
{ slot: 'slotName' }
],
}
},
CustomizePagination组件
组件配置
props
current.sync: [Number, String], // 当前页
size.sync: [Number, String], // 当前每页个数
total: [Number, String], // 总个数
pageSizes: Array, // 每页显示个数选择器的选项设置
layout: String, // 组件布局 'sizes, prev, pager, next, jumper, ->, total, slot',
align: String, // 组件位置 text-align
className: String,
emit
@change
example
<customize-pagination
:current.sync="current"
:total="total"
:size.sync="size"
@change="handleChangePage"
style="padding-bottom: 30px;"
></customize-pagination>
data() {
return {
current: 1,
total: 0,
size: 10,
}
},
methods: {
handleChangePage({ current, size }) {
this.fetchData();
},
},
CustomizeSearchBar组件
组件配置
props
loading.sync: false, // 搜索按钮loading状态
setting: [{
type: String, // input/select
label: String // 表单label名
prop: String, // 提交的字段名 必填
placeholder: String, // 默认为请输入/选择 label
default: Any, // 默认值
width: String, // style中width
rules: Array, // 替换默认rule
required: Boolean, // true/false
msg: String, // 错误提示信息
prefixIcon: String, // type input时,输入框icon
className: String, // type input时,el-form-item的class
slot: String, // slot #slot="{ form }"
enum: Array | Object, // 直接传入枚举或数组 label value
enumProp: String, // select时,enum中传入的枚举属性值
hideOptionAll: true, // select时,隐藏‘全部’选项传入true
optionAllName: String, // select,全部显示label名,默认全部
}],
enum: {
[enumProp]: [{ label: '', prop: '' }]
}
validate: Boolean, // 开启表单验证 配合rules
inlineButtons: Boolean // 按钮不换行
size: String, // 表单size
className: String, // form自定义class
blockButtons: Boolean, // 是否将按钮组换行展示,默认false
showResetButton: Boolean, // 是否展示重置按钮,默认true
openEnterSearch: Boolean, // 是否开启input的回车搜索,默认false
searchButtonName: String, // 查询按钮文案
full-width: Boolean, // inline模式铺满宽度,输入框宽度自适应
inline: Boolean, // inline 默认true
margin: String, // el-form-item margin-right '10px'
marginLeft: String, // el-form-item margin-right设为0,margin-left为该px
showSearchButton: Boolean, // 是否显示搜索按钮 默认true
immediate: Boolean, // select/date,是否值改变时立即触发搜索,默认false
optionAllName: String, // select全部选项的名称,默认全部
emit
@submit // emit所有表单参数
slot
#after="form"
ref
ref: form
example
<customize-search-bar
:loading.sync="searchBarLoading"
@submit="handleSubmitSearch"
:setting="searchBarSetting"
:Enum="searchBarEnum"
></customize-search-bar>
data() {
return {
searchBarLoading: false,
searchBarSetting: [
{ type: 'input', label: '名称', prop: 'name' },
{ type: 'select', label: '分类', prop: 'type', enumProp: 'allList' },
{ slot: 'type', prop: 'type' },
],
searchBarEnum: {
allList: [],
},
}
},
methods: {
fetchData() {
this.searchBarLoading = false;
},
handleSubmitSearch(searchParams) {
this.current = 1;
this.fetchParams = { ...searchParams };
this.fetchData();
},
async searchBarInit() {
const { data } = await GetList({
pageNo:1,
paeSize: 100,
});
let allList = data.itemInfos || [];
allList = allList.map(n => ({
label: n.name,
value: n.id,
}))
this.$set(this.searchBarEnum, 'allList', allList);
},
},
slot example
<template #type="{ form }">
<el-form-item label="分类">
<el-select v-model="form.type" placeholder="请选择分类" @change="handleChange">
<el-option label="全部" value=""></el-option>
<el-option
v-for="item in allList"
:label="item.name"
:value="item.id"
:key="item.id"
></el-option>
</el-select>
</el-form-item>
</template>
CustomizeSwitch组件
组件配置
props
type: String, // inside/right
mode: String, // 同type
value/v-model: [Number, String, Boolean],
values: Array, // [打开时value, 关闭时value]
text: Array, // [打开时文案, 关闭时文案]
icon: Array, // [打开时图标, 关闭时图标] 开启后覆盖text
color: Array, // [打开时背景色, 关闭时背景色]
disabled: Boolean, // 默认false,
width: Number, // element中宽度,默认40
name: String,
validateEvent: Boolean, // 改变后是否触发表单验证
activeTextColor: String, // type为inside时文字颜色
className: String,
size: String, // medium/small/mini
emit
@change
ref
ref: switch
example 双向绑定
<customize-switch
v-model="switchValue"
:text="['开启', '关闭']"
:values="[1, 0]"
></customize-switch>
data() {
return {
switchValue: 1,
}
},
example 非双向绑定
<customize-switch
:value="switchValue"
:disabled="switchDisabled"
:text="['开启', '关闭']"
:values="[1, 0]"
@change="handleSwitchChange"
></customize-switch>
data() {
return {
switchValue: 1,
switchDisabled: false,
}
},
methods: {
async handleSwitchChange(value) {
try {
this.switchDisabled = true;
await this._sleep(1);
this.switchValue = value;
this.$message.success('操作成功');
} catch (error) {
}
this.switchDisabled = false;
},
},
example type="inside"
<customize-switch
:value="switchValue"
:disabled="switchDisabled"
:text="['开启', '关闭']"
:values="[1, 0]"
@change="handleSwitchChange"
type='inside'
:width="54"
:color="['#67C23A', '#909399']"
active-text-color="#fff"
size="small"
></customize-switch>
CustomizeForm组件
组件配置
props
loading.sync: false, // 搜索按钮loading状态
setting: [{
type: String, // input/textarea/inputNumber/select/text/date/datepicker/switch/image/object/array/
label: String // 表单label名
prop: String, // 提交的字段名 必填
placeholder: String, // 默认为请输入/选择 label
default: Any, // 默认值
width: String, // style中width
rules: Array, // 替换默认rule
required: Boolean, // true/false
msg: String, // 错误提示信息
validType: String, // rules type, url/email/date
prefixIcon: String, // type input时,输入框icon
className: String, // type input时,el-form-item的class
labelWidth: String, // label-width
slot: String, // slot #slot="{ form }"
slotInside: String, // 插入至el-form-item内
enum: Array | Object, // 直接传入枚举或数组 label value
enumProp: String, // select时,enum中传入的枚举属性值
enumKey: Array, // select时,enum的key值,默认['label', 'value']
hideOptionAll: true, // select时,隐藏‘全部’选项传入true
optionAllName: String, // select,全部显示label名,默认全部
clearable: Boolean, // date时,el-date-picker的 clearable,默认true
disabled: Boolean, // disabled状态,默认false
dataType: Number/Boolean, // 数据类型,默认String
inputNumber: Boolean, // true且type number时显示el-input-number
visible: Array | Function, // [属性名, 属性值] 设置后 当某属性为该值时,渲染该条。为function时return true时显示
}],
enum: {
[enumProp]: [{ label: '', prop: '' }]
}
validate: Boolean, // 开启表单验证 配合rules
size: String, // 表单size
className: String, // form自定义class
showSubmitButton: Boolean, // 是否展示提交按钮,默认true
showResetButton: Boolean, // 是否展示重置按钮,默认true
submitButtonName: String, // 提交按钮文案,默认提交
resetButtonName: String, // 重置按钮文案,默认重置
openEnterSearch: Boolean, // 是否开启input的回车搜索,默认false
margin: String, // el-form-item margin-bottom
immediate: Boolean, // select/date,是否值改变时立即触发搜索,默认false
optionAllName: String, // 下拉选择全部的名称,默认全部
labelWidth: String, // el-form label-width,默认120px
itemWidth: String, // form-item的宽度,默认auto
clearable: Boolean, // el-date-picker clearable,默认true
hideOptionAll: Boolean, // select时,隐藏‘全部’选项传入true
hideOperate: Boolean, // 隐藏操作el-form-item
cleanProps: Boolean, // submit时仅传出setting中有的属性,删除其它属性
fn: Array, // 传入的函数 配合image中fnName
emit
@submit // emit所有表单参数
slot
#button-before
#button
slot-scope
#after="form"
ref
ref: form
example
<template>
<customize-form
:loading.sync="formLoading"
@submit="handleSubmit"
:setting="formSetting"
:Enum="formEnum"
validate
></customize-form>
</template>
<script>
export default {
data() {
return {
formLoading: false,
formSetting: [
{ type: 'input', label: '名称', prop: 'name', disabled: true },
{ type: 'select', label: '分类', prop: 'type', enumProp: 'allList', enumKey: ['label', 'value'], default: '' },
{ slot: 'slotName', prop: 'slotName' },
{ type: 'text', label: '啊啊', default: 'text' },
{ type: 'radio', label: '单选', prop: 'radio', enum: {
1: 'a',
2: 'b',
} },
{ type: 'checkbox', label: '多选', prop: 'checkbox', enum: [
{ label: 'aa', value: 11 },
{ label: 'bb', value: 22 },
{ label: 'cc', value: 33 },
{ label: 'dd', value: 44 },
{ label: 'ee', value: 55 },
], default: [] },
{ type: 'switch', label: '开关', prop: 'switch', text: ['开启', '关闭'], values: [1, 0], default: 0 },
{ type: 'switch', label: '开关', prop: 'switch', text: ['开启', '关闭'], values: [1, 0], default: 0 },
{ type: 'object', label: '对象', prop: 'obj', default: {}, children: [
{ type: 'input', label: '名称', prop: 'name', required: true },
{ type: 'select', label: '分类', prop: 'type', enum: { 1: 'a', 2: 'b' }, default: '1' },
] },
{ type: 'array', label: '数组', prop: 'arr', len: 3, default: [], children: [
{ type: 'input', label: '名称', prop: 'name' },
{ type: 'input', label: '名称2', prop: 'name2', required: true },
{ type: 'select', label: '分类', prop: 'type', enum: { 1: 'a', 2: 'b' }, default: '1' },
] },
{ type: 'image', label: '图片', prop: 'image', fn: this.uploadFn },
],
formEnum: {
allList: [],
},
}
},
methods: {
async handleSubmit(form) {
console.log(form)
/* 提交表单 */
await this._sleep(1);
this.$message.success('提交成功');
this.formLoading = false;
},
async uploadFn() {
const url = '';
await this._sleep(1);
return Promise.resolve(url);
},
async formInit() {
const data = {
itemInfos: [
{ name: 'a', id: 1 },
{ name: 'b', id: 2 },
{ name: 'c', id: 3 },
],
};
await this._sleep(1);
let allList = data.itemInfos || [];
allList = allList.map(n => ({
label: n.name,
value: n.id,
}))
this.$set(this.formEnum, 'allList', allList);
},
},
created() {
this.formInit();
},
}
</script>
slot example
<template #slotName="{ form }">
<el-form-item label="分类">
<el-select v-model="form.type" placeholder="请选择分类" @change="handleChange">
<el-option label="全部" value=""></el-option>
<el-option
v-for="item in allList"
:label="item.name"
:value="item.id"
:key="item.id"
></el-option>
</el-select>
</el-form-item>
</template>
CustomizeDialogForm组件
组件配置
props
visible.sync: Boolean, // 弹窗是否显示
editData: Any, // 以编辑进入时回显数据
title: [String, Array], // 弹窗标题,为数组时[新建title, 编辑title]
top: String, // el-dialog top
width: String, // el-dialog width
size: String, // medium
closeButtonShow: [Boolean, String], // 是否展示关闭弹窗按钮,默认展示。传入String时控制slot(button-before, button)
closeButtonName: String, // 关闭弹窗按钮名称,默认关闭
className: String, // dialog自定义class
其他prop同CustomizeForm
emit
@submit form
slot
同CustomizeForm
#button-before
#button
slot-scope
同CustomizeForm
#after="form"
ref
ref: dialog
example
<customize-dialog-form
title='123'
:visible.sync="dialogVisible"
@submit="handleSubmitDialog"
:loading.sync="submitLoading"
:setting="formSetting"
:Enum="formEnum"
validate
></customize-dialog-form>
<script>
export default {
/* 作为单独组件引入时 */
// props: {
// visible: Boolean,
// },
data() {
return {
submitLoading: false,
formSetting: [
{ type: 'input', label: '名称', prop: 'name', default: '1', required: true },
{ type: 'select', label: '分类', prop: 'type', enumProp: 'allList' },
{ slot: 'type', prop: 'type' },
],
formEnum: {
allList: [],
},
editData: null,
dialogVisible: false,
}
},
computed: {
/* 作为单独组件引入时,外部 :visible.sync */
// dialogVisible: {
// get() {
// return this.visible;
// },
// set(val) {
// this.$emit('update:visible', val);
// },
// },
},
methods: {
async handleSubmitDialog(form) {
console.log(form);
try {
/* 提交表单 */
await this._sleep(1)
this.$message.success('提交成功');
this.dialogVisible = false;
} catch (error) {
console.log('submitDialogError', error);
}
this.submitLoading = false;
},
handleCreate() {
// 以创建进入
this.editData = null
this.dialogVisible = true;
},
handleEdit() {
// 以编辑进入 同步数据
this.editData = {
name: 'name',
type: 2,
}
this.dialogVisible = true;
},
async handleEditAsync() {
// 以编辑进入 异步数据
this.editData = null
this.dialogVisible = true;
await this._sleep(1);
this.editData = {
name: 'name2',
type: 3,
}
},
async formInit() {
const data = {
itemInfos: [
{name:'a',id:1},
{name:'b',id:2},
{name:'c',id:3},
]
}
this._sleep(2)
let allList = data.itemInfos || [];
allList = allList.map(n => ({
label: n.name,
value: n.id,
}))
this.$set(this.formEnum, 'allList', allList);
},
}
}
</script>
CustomizePage组件
example
<template>
<customize-page
:pageSetting="pageSetting"
:searchBarProps="searchBarProps"
:dialogProps="dialogProps"
:Enum="Enum"
:tableProps="tableProps"
:tableDataFn="tableDataFn"
:editDataFn="editDataFn"
:submitFn="submitFn"
>
<template #slotName>
<el-table-column label="slot" prop="slotName">
<template #default="{ row }">
{{ row.id }}
</template>
</el-table-column>
</template>
<template #tableButton="{ id }">
<el-button type="danger" size="mini" @click="handleDelete(id)">删除</el-button>
</template>
</customize-page>
</template>
<script>
export default {
data() {
return {
pageSetting: [
{ label: 'ID', prop: 'id', width: '100px' },
{ type: 'input', label: '名称', prop: 'name', required: true, msg: '321' },
{ type: 'select', label: '分类', prop: 'type', enumProp: 'allSelectList', enumKey: ['label', 'value'], default: '', rules: [
{ required: true, message: 'message' }
], formatter: (row, column, cellValue, index) => (this.Enum.allSelectList.find(n => n.value == cellValue) || {})['label'] || '' },
{ type: 'text', label: '啊啊', default: 'text', prop: 'text' },
{ type: 'radio', label: '单选', prop: 'radio', enum: {
1: 'a',
2: 'b',
}, disabled: true },
{ type: 'checkbox', label: '多选', prop: 'checkbox', enum: [
{ label: 'aa', value: 11 },
{ label: 'bb', value: 22 },
{ label: 'cc', value: 33 },
{ label: 'dd', value: 44 },
{ label: 'ee', value: 55 },
], default: [] },
{ type: 'switch', label: '开关', prop: 'switch', text: ['开启', '关闭'], values: [1, 0], default: 0 },
{ slot: 'slotName', prop: 'slotName' },
],
Enum: {
allSelectList: [],
},
searchBarProps: ['name', 'type'],
dialogProps: ['name', 'type', 'text', 'radio', 'checkbox', 'switch'],
tableProps: ['id', 'name', 'type', 'slotName'],
}
},
methods: {
async tableDataFn(form) {
console.log(form);
/* 获取列表 */
const data = [
{ id: '1', name: 'aaa', type: 1 },
{ id: '2', name: 'bbb', type: 2 },
{ id: '3', name: 'ccc', type: 3 },
{ id: '4', name: 'ddd', type: 1 },
];
const total = 100;
await this._sleep(1);
return Promise.resolve({ data, total });
},
async editDataFn(id) {
/* 获取详情 */
const data = {
id,
name: '1',
type: 2,
checkbox: [22, 33],
switch: 1,
}
this._sleep(1);
return Promise.resolve(data);
},
async submitFn(form) {
console.log(form);
/* 提交表单 */
await this._sleep(1);
return Promise.resolve();
},
async init() {
const allSelectList = [
{ label: 'a', value: 1 },
{ label: 'b', value: 2 },
{ label: 'c', value: 3 },
];
await this._sleep(1);
this.$set(this.Enum, 'allSelectList', allSelectList);
},
handleDelete(id) {
this.$alert(`删除 ${id}`);
},
},
created() {
this.init();
},
}
</script>
<style>
html, body {
margin: 0;
}
</style>
CustomizeFormBuilder组件
组件配置
props
debug: Boolean, // 实时显示formSetting数据
operate: Array, // 操作区展示的按钮 ['import', 'clear', 'preview', 'schema', 'code']
event
getSchema, // 获取当前配置转码的schema
setSchema, // 设置schema字符串并重新渲染
slot
#operate-title 操作区域标题名
#operate-before 操作区域前置按钮
#operate-after 操作区域后置按钮
example
<template>
<customize-form-builder ref="formBuilder"></customize-form-builder>
</template>
<script>
export default {
methods: {
getSchema() {
const result = this.$refs.formBuilder.getSchema();
console.log(result)
},
setSchema() {
const schemaStr = `{"$schema":"http://json-schema.org/draft-04/schema#","type":"object","properties":{"input_1588506741033":{"type":"input","label":"单行文本","prop":"input_1588506741033","key":1588506741033}}}`
this.$refs.formBuilder.setSchema(schemaStr);
},
},
}
</script>
辅助函数
_isEmpty
判断是否不为空
@return { Boolean }
_clean
删除对象中值为空的属性
@param { Object }
@return { Object }
_setValue
值不为空直接返回,为空返回默认值
@param { Any, Any } 需判断的值,默认值
@return { Any }
_formatDate
时间格式化
@params { [String, Number, Date], String } 时间,格式(默认 yyyy-MM-dd hh:mm:ss)
@return { String }
_deepClone
深拷贝
@params { Object }
@return { Object }
_sleep
延迟几秒后继续执行
@params { Number } 延迟秒数
@return { Promise } resolve
_deepMerge
对象深度合并
@params { Object, Object } 延迟秒数
@return { Object }
_deepMerge(a, b, [..option])
_deepMerge.all([a, b, c], [..option])
常用增删改查页面完整事例(无弹窗)
<template>
<div class="home">
<customize-search-bar
:loading.sync="searchBarLoading"
@submit="handleSubmitSearch"
:setting="searchBarSetting"
></customize-search-bar>
<customize-table
:data="tableData"
:column="tableColumn"
v-loading="tableLoading"
>
<template #slotName>
<el-table-column label="slot-slotName" align="center">
<template #default="{ row }">
<span>_isEmpty {{ _isEmpty(row.status) }}</span>
</template>
</el-table-column>
</template>
<template #after>
<el-table-column label="操作" align="center">
<template #default="{ row }">
<el-button type="primary" size="mini" @click="handleEdit(row.id)">编辑</el-button>
</template>
</el-table-column>
</template>
</customize-table>
<customize-pagination
:current.sync="current"
:total="total"
:size.sync="size"
@change="handleChangePage"
style="padding-bottom: 30px;"
></customize-pagination>
</div>
</template>
<script>
export default {
name: 'home',
data() {
return {
/* 列表请求参数 */
fetchParams: {},
/* 搜索相关 */
searchBarLoading: false,
searchBarSetting: [
{ type: 'input', label: '名称', prop: 'name' },
{ type: 'select', label: '分类', prop: 'type', enum: {
0: '暂停',
1: '启用',
} },
{ slot: 'type', prop: 'type' },
],
/* 表格相关 */
tableLoading: false,
tableData: [],
tableColumn: [
// { type: 'index', index: (index) => (this.current - 1) * this.size + index + 1 },
{ label: '名称', prop: 'name' },
{ label: '属性', prop: 'aaa', width: '100px', w: '100px' },
{ label: '状态', prop: 'status', formatter(row, column, cellValue, index) {
const Enum = {
0: '暂停',
1: '启用',
}
return Enum[cellValue] || '--';
}},
{ slot: 'slotName' }
],
/* 分页相关 */
current: 1,
total: 0,
size: 10,
}
},
methods: {
/* 请求数据 */
async fetchData() {
this.tableLoading = true;
try {
const response = await new Promise(resolve => {
setTimeout(_ => {
console.log(this._clean({
...this.fetchParams,
page: this.current,
size: this.size,
}))
const response = {
data: [
{ name: 'a', aaa: 2, status: 0 },
{ name: 'b', aaa: 3, status: null },
{ name: 'c', aaa: 4, status: 1 },
{ name: 'd', aaa: 5, status: 0 },
],
total: 100,
}
resolve(response);
}, 1111)
})
// const response = await GetList(this._clean({
// ...this.fetchParams,
// page: this.current,
// size: this.size,
// }))
this.tableData = response.data || [];
this.total = response.total || 0;
} catch (error) {
this.tableData = [];
this.total = 0;
}
this.tableLoading = false;
this.searchBarLoading = false;
},
/* 搜索相关 */
handleSubmitSearch(searchParams) {
this.current = 1;
this.fetchParams = searchParams;
this.fetchData();
},
/* 分页相关 */
handleChangePage() {
this.fetchData();
},
},
created() {
this.fetchData();
},
}
</script>
常用增删改查页面完整事例(带弹窗)
<template>
<div class="home">
<customize-search-bar
:loading.sync="searchBarLoading"
@submit="handleSubmitSearch"
:setting="searchBarSetting"
>
<template #button>
<el-button type="primary" @click="handleAdd">新建</el-button>
</template>
</customize-search-bar>
<customize-table
:data="tableData"
:column="tableColumn"
v-loading="tableLoading"
>
<template #slotName>
<el-table-column label="slot-slotName" align="center">
<template #default="{ row }">
<span>_isEmpty {{ _isEmpty(row.status) }}</span>
</template>
</el-table-column>
</template>
<template #after>
<el-table-column label="操作" align="center">
<template #default="{ row }">
<el-button type="primary" size="mini" @click="handleEdit(row.id)">编辑</el-button>
</template>
</el-table-column>
</template>
</customize-table>
<customize-pagination
:current.sync="current"
:total="total"
:size.sync="size"
@change="handleChangePage"
style="padding-bottom: 30px;"
></customize-pagination>
<dialog-create
:editId="editId"
:visible.sync="dialogVisible"
@submit="handleSubmitDialog"
></dialog-create>
</div>
</template>
<script>
import DialogCreate from './DialogCreate';
export default {
components: {
DialogCreate,
},
data() {
return {
/* 列表请求参数 */
fetchParams: {},
/* 搜索相关 */
searchBarLoading: false,
searchBarSetting: [
{ type: 'input', label: '名称', prop: 'name' },
{ type: 'select', label: '分类', prop: 'type', enum: {
0: '暂停',
1: '启用',
} },
{ slot: 'type', prop: 'type' },
],
/* 表格相关 */
tableLoading: false,
tableData: [],
tableColumn: [
// { type: 'index', index: (index) => (this.current - 1) * this.size + index + 1 },
{ label: '名称', prop: 'name' },
{ label: '属性', prop: 'aaa', width: '100px', w: '100px' },
{ label: '状态', prop: 'status', formatter(row, column, cellValue, index) {
const Enum = {
0: '暂停',
1: '启用',
}
return Enum[cellValue] || '--';
}},
{ slot: 'slotName' }
],
/* 分页相关 */
current: 1,
total: 0,
size: 10,
/* 弹窗相关 */
dialogVisible: false,
editId: null,
}
},
methods: {
/* 请求数据 */
async fetchData() {
this.tableLoading = true;
try {
const response = await new Promise(resolve => {
setTimeout(_ => {
const response = {
data: [
{ id: 1, name: 'a', aaa: 2, status: 0 },
{ id: 2, name: 'b', aaa: 3, status: null },
{ id: 3, name: 'c', aaa: 4, status: 1 },
{ id: 4, name: 'd', aaa: 5, status: 0 },
],
total: 100,
}
resolve(response);
}, 222)
// const response = await GetList(this._clean({
// ...this.fetchParams,
// page: this.current,
// size: this.size,
// }))
this.tableData = response.data || [];
this.total = response.total || 0;
})
} catch (error) {
this.tableData = [];
this.total = 0;
}
this.tableLoading = false;
this.searchBarLoading = false;
},
/* 搜索相关 */
handleSubmitSearch(searchParams) {
this.current = 1;
this.fetchParams = searchParams;
this.fetchData();
},
/* 分页相关 */
handleChangePage() {
this.fetchData();
},
/* 弹窗相关 */
handleAdd() {
this.editId = null;
this.dialogVisible = true;
},
handleEdit(id) {
this.editId = id;
this.dialogVisible = true;
},
handleSubmitDialog() {
console.log('handleDialog');
this.fetchData();
},
},
created() {
this.fetchData();
},
}
</script>
<template>
<el-dialog
title="title"
top="15vh"
width="600px"
:visible.sync="dialogVisible"
@close="handleClosed"
>
<el-form :model="form" :rules="rules" ref="form" label-width="180px" size="small">
<el-form-item label="名称:" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit" :loading="loading">提交</el-button>
<el-button @click="handleCancel">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script>
const DEFAULT_FORM = () => ({
name: '',
});
export default {
props: {
visible: Boolean,
editId: {},
},
data() {
return {
dialogVisible: false,
form: DEFAULT_FORM(),
rules: {
name: { required: true, message: '请输入名称' },
},
loading: false,
}
},
methods: {
handleClosed() {
// reset here
this.$refs.form.resetFields();
this.form = DEFAULT_FORM();
this.$emit('update:visible', false);
},
async handleSubmit() {
console.log(this.form);
try {
await this.$refs.form.validate();
await this.$confirm(`是否确定提交`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
});
this.loading = true;
let params = this._deepClone(this.form);
if (!!this.editId) {
params.id = this.editId;
await Update(params);
}else{
await Save(params);
}
this.$message.success(`${!!this.editId ? '编辑' : '新增'}成功`);
this.dialogVisible = false;
this.$emit('submit');
} catch (error) {
console.log(error);
}
this.loading = false;
},
handleCancel() {
this.dialogVisible = false;
},
},
watch: {
visible: {
handler(newVal, oldVal) {
this.dialogVisible = newVal;
},
immediate: true,
}
},
}
</script>
<style lang='scss' scoped>
</style>
常用增删改查页面完整事例(带弹窗)单页
<template>
<div class="home">
<customize-search-bar
:loading.sync="searchBarLoading"
@submit="handleSubmitSearch"
:setting="searchBarSetting"
>
<template #button>
<el-button type="primary" @click="handleAdd">新建</el-button>
</template>
</customize-search-bar>
<customize-table
:data="tableData"
:column="tableColumn"
v-loading="tableLoading"
>
<template #slotName>
<el-table-column label="slot-slotName" align="center">
<template #default="{ row }">
<span>_isEmpty {{ _isEmpty(row.status) }}</span>
</template>
</el-table-column>
</template>
<template #after>
<el-table-column label="操作" align="center">
<template #default="{ row }">
<el-button type="primary" size="mini" @click="handleEdit(row.id)">编辑</el-button>
</template>
</el-table-column>
</template>
</customize-table>
<customize-pagination
:current.sync="current"
:total="total"
:size.sync="size"
@change="handleChangePage"
style="padding-bottom: 30px;"
></customize-pagination>
<customize-dialog-form
:editData="editData"
title='title'
:visible.sync="dialogVisible"
@submit="handleSubmitDialog"
:loading.sync="formLoading"
:setting="formSetting"
:Enum="formEnum"
validate
></customize-dialog-form>
</div>
</template>
<script>
export default {
data() {
return {
/* 列表请求参数 */
fetchParams: {},
/* 搜索相关 */
searchBarLoading: false,
searchBarSetting: [
{ type: 'input', label: '名称', prop: 'name' },
{ type: 'select', label: '分类', prop: 'type', enum: {
0: '暂停',
1: '启用',
} },
{ slot: 'type', prop: 'type' },
],
/* 表格相关 */
tableLoading: false,
tableData: [],
tableColumn: [
// { type: 'index', index: (index) => (this.current - 1) * this.size + index + 1 },
{ label: '名称', prop: 'name' },
{ label: '属性', prop: 'aaa', width: '100px', w: '100px' },
{ label: '状态', prop: 'status', formatter(row, column, cellValue, index) {
const Enum = {
0: '暂停',
1: '启用',
}
return Enum[cellValue] || '--';
}},
{ slot: 'slotName' }
],
/* 分页相关 */
current: 1,
total: 0,
size: 10,
/* 弹窗相关 */
formLoading: false,
formSetting: [
{ type: 'input', label: '名称', prop: 'name', required: true, msg: '321' },
{ type: 'select', label: '分类', prop: 'type', enumProp: 'allList', enumKey: ['label', 'value'], default: '', rules: [
{ required: true, message: 'message' }
] },
{ slot: 'slotName', prop: 'slotName' },
{ type: 'text', label: '啊啊', default: 'text' },
{ type: 'radio', label: '单选', prop: 'radio', enum: {
1: 'a',
2: 'b',
}, disabled: true },
{ type: 'checkbox', label: '多选', prop: 'checkbox', enum: [
{ label: 'aa', value: 11 },
{ label: 'bb', value: 22 },
{ label: 'cc', value: 33 },
{ label: 'dd', value: 44 },
{ label: 'ee', value: 55 },
], default: [] },
{ type: 'switch', label: '开关', prop: 'switch', text: ['开启', '关闭'], values: [1, 0], default: 0 },
],
formEnum: {
allList: [],
},
dialogVisible: false,
editData: null,
}
},
methods: {
/* 请求数据 */
async fetchData() {
const params = this._clean({
...this.fetchParams,
current: this.current,
size: this.size,
});
console.log(params);
this.tableLoading = true;
try {
const response = {
data: [
{ id: 1, name: 'a', aaa: 2, status: 0 },
{ id: 2, name: 'b', aaa: 3, status: null },
{ id: 3, name: 'c', aaa: 4, status: 1 },
{ id: 4, name: 'd', aaa: 5, status: 0 },
],
total: 100,
}
await this._sleep(1);
this.tableData = response.data || [];
this.total = response.total || 0;
} catch (error) {
this.tableData = [];
this.total = 0;
}
this.tableLoading = false;
this.searchBarLoading = false;
},
/* 搜索相关 */
handleSubmitSearch(searchParams) {
this.current = 1;
this.fetchParams = searchParams;
this.fetchData();
},
/* 分页相关 */
handleChangePage() {
this.fetchData();
},
/* 弹窗相关 */
handleAdd() {
this.editData = null
this.dialogVisible = true;
},
async handleEdit(id) {
this.dialogVisible = true;
await this._sleep(1);
const editData = {
id,
name: '1',
type: 2,
checkbox: [22, 33],
switch: 1,
}
this.editData = editData;
},
async handleSubmitDialog(form) {
console.log(form)
/* 提交表单 */
await this._sleep(1);
this.$message.success('提交成功');
this.formLoading = false;
this.dialogVisible = false;
this.editData = null;
},
async formInit() {
const data = {
itemInfos: [
{ name: 'a', id: 1 },
{ name: 'b', id: 2 },
{ name: 'c', id: 3 },
],
};
await this._sleep(1);
let allList = data.itemInfos || [];
allList = allList.map(n => ({
label: n.name,
value: n.id,
}))
this.$set(this.formEnum, 'allList', allList);
},
},
created() {
this.fetchData();
this.formInit();
},
}
</script>