<!-- --> <template> <el-dialog :visible.sync="defaultConfigDialogAdd.dialogVisible" :width="defaultConfigDialogAdd.width" :center="defaultConfigDialogAdd.isCenter" > <!-- 如果t写了插槽,外面使用其实是没必要传title属性。--> <div slot="title" class="dialog-title"> <slot name="title"> <h2 class="default-title">{{defaultConfigDialogAdd.title}}</h2> </slot> </div> <el-form :model="addUserForm" :rules="rules" ref="addUserForm" label-width="100px"> <el-form-item label="用户名" prop="username"> <el-input v-model="addUserForm.username"></el-input> </el-form-item> <el-form-item label="姓名" prop="truename"> <el-input v-model="addUserForm.truename"></el-input> </el-form-item> <el-form-item label="手机号" prop="phone"> <el-input v-model.number="addUserForm.phone"></el-input> </el-form-item> <el-form-item label="是否启用" prop="status"> <el-radio-group v-model="addUserForm.status"> <el-radio label="禁用"></el-radio> <el-radio label="启用"></el-radio> </el-radio-group> </el-form-item> <el-form-item label="角色" prop="role"> <el-checkbox-group v-model="addUserForm.role"> <el-checkbox label="系统管理员"></el-checkbox> <el-checkbox label="信息管理员"></el-checkbox> <el-checkbox label="用户管理员"></el-checkbox> </el-checkbox-group> </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="handleCancel('addUserForm')">取 消</el-button> <el-button type="primary" @click="submitForm('addUserForm')">立即创建</el-button> </span> </el-dialog> </template> <script> import validate from "@/utils/validate"; const { checkAge } = validate; export default { name: "DialogAdd", props: { configDialogAdd: { type: Object, required: true } }, data() { return { defaultConfigDialogAdd: { dialogVisible: false, //弹框默认不可见 title: "提示", //默认标题 "30%", //默认宽度 isCenter: false //是否对头部和底部采用居中布局 }, addUserForm: { username: "", truename: "", phone: "", status: "", role: [] }, rules: { username: [ { required: true, message: "请输入活动名称", trigger: "blur" }, { min: 2, max: 10, message: "长度在 3 到 5 个字符", trigger: "blur" } ], truename: [ { required: true, message: "请输入活动名称", trigger: "blur" }, { min: 2, max: 19, message: "长度在 2 到 10个字符", trigger: "blur" } ], phone: [{ required: true, validator: checkAge, trigger: "blur" }], status: [ { required: true, message: "请选择是否启用", trigger: "change" } ], role: [ { type: "array", required: true, message: "请至少选择一个角色", trigger: "change" } ] } }; }, methods: { initDefaultConfigDialogAdd() { this.defaultConfigDialogAdd = { ...this.defaultConfigDialogAdd, ...this.configDialogAdd }; }, submitForm(formName) { this.$refs[formName].validate(async valid => { if (!valid) return this.$message.error("数据验证不通过"); //错误优先 // 发送网络请求 if (valid) { this.$refs[formName].resetFields(); this.defaultConfigDialogAdd.dialogVisible = false; this.$message.success("增加用户成功"); } }); }, handleCancel(formName) { // 重置输入框 this.$refs[formName].resetFields(); this.defaultConfigDialogAdd.dialogVisible = false; } }, created() { // 初始化弹框配置项的数据 this.initDefaultConfigDialogAdd(); }, watch: { // 外面的值变化,改变里面 "configDialogAdd.dialogVisible": { handler(val) { this.defaultConfigDialogAdd.dialogVisible = val; } }, // 里面的值发生变化,改变外面 "defaultConfigDialogAdd.dialogVisible": { handler(val) { this.configDialogAdd.dialogVisible = val; } } } }; </script> <style lang="scss" scoped> .dialog-title { color: #000; font-size: 20px; font-weight: 700; } </style>
使用
封装
mininx/userAdd.js
/** * 表单支持输入框,数字输入框,单选按钮, 多选按钮,下拉选择器 switch开关 * 每次增加一个数据formItems里面的一个项目。都要配套的增加该项目的rule 验证规则,和watch监听属性,往params网络请求参数里面赋值。 * formITtems里面的数据项也有可能是经过一次网络请求获取来的, 就需要在此mixins文件中定义methods网络请求方法,去获取formItems数据,这个时候也需要在做另外一件事件: * 在DialogAdd.vue中去监听这些网络数据请求回来的数据。 */ import validate from "@/utils/validate"; const { checkAge } = validate; export default { data() { return { // 增加用户弹框组件数据选项 configDialogAdd: { dialogVisible: false, //弹框默认不可见 title: "新增用户", //默认标题 如果写了#title插槽,title可以省略不传 "40%", //默认宽度 addUserForm: { formName: "addUserForm", //表单名 labelWidth: '120px', labelPosition: 'left', formItems: [ //表单选项 { label: "用户名", prop: "username", type: "input" }, //type是表单控件类型 { label: "姓名", prop: "truename", type: "input" }, { label: "手机号", prop: "phone", type: "numberInput" }, { label: "是否启用", prop: "status", type: "radio", values: ["禁用", "启用"] }, { label: "是否启用形式2", prop: "status1", type: "switch", }, { label: "角色", prop: "role", type: "checkbox", values: ["系统管理员", "信息管理员", "用户管理员"] }, { label: "角色形式2", prop: "role1", type: "select", options: [{ value: 'admin', label: '系统管理员' }, { value: 'info', label: '信息管理员' }, { value: 'user', label: '用户管理员' }], }, { label: "Cascader", prop: "cascader", type: "Cascader", options: [{ value: 'zhinan', label: '指南', children: [{ value: 'shejiyuanze', label: '设计原则' }] }, { value: 'daohang', label: '导航', children: [{ value: 'cexiangdaohang', label: '侧向导航' }, { value: 'dingbudaohang', label: '顶部导航' }] } ], handleChange: this.handleChange } ], data: { //绑定的数据 username: "", truename: "", phone: "", status: "", status1: false, role: [], role1: '', cascader: [], }, rules: { username: [ { required: true, message: "请输入用户名", trigger: "blur" }, { min: 2, max: 10, message: "长度在 3 到 5 个字符", trigger: "blur" } ], truename: [ { required: true, message: "请输入名字", trigger: "blur" }, { min: 2, max: 19, message: "长度在 2 到 10个字符", trigger: "blur" } ], phone: [{ required: true, validator: checkAge, trigger: "blur" }], status: [ { required: true, message: "请选择是否启用", trigger: "change" } ], status1: [ { required: true, message: "请选择是否启用形式1", trigger: "change" } ], role: [ { type: "array", required: true, message: "请至少选择一个角色", trigger: "change" } ], role1: [ { required: true, message: "请至少选择一个角色1", trigger: "change" }], cascader: [ { required: true, message: "请至少选择一个级联选择器", trigger: "change" }], }, }, requestApi: { apiName: "userAdd", params: {} } } } }, methods: { handleChange(val) { console.log(111); console.log(val); } }, created() { }, mounted() { }, watch: { // 逻辑处理在外部,由用户控制参数 'configDialogAdd.addUserForm.data.username': { handler(newVal) { this.configDialogAdd.requestApi.params.username = newVal }, }, 'configDialogAdd.addUserForm.data.truename': { handler(newVal) { this.configDialogAdd.requestApi.params.truename = newVal }, }, 'configDialogAdd.addUserForm.data.phone': { handler(newVal) { this.configDialogAdd.requestApi.params.phone = newVal }, }, 'configDialogAdd.addUserForm.data.status': { handler(newVal) { if (!newVal) this.configDialogAdd.requestApi.params.status = '' else this.configDialogAdd.requestApi.params.status = newVal === '禁用' ? '0' : '1' }, }, 'configDialogAdd.addUserForm.data.role': { handler(newVal) { const obj = { "系统管理员": 'admin', '信息管理员': 'info', '用户管理员': 'user' } let resArr = [] newVal.forEach(item => resArr.push(obj[item])) this.configDialogAdd.requestApi.params.role = resArr.join(',') }, }, 'configDialogAdd.addUserForm.data.status1': { handler(newVal) { this.configDialogAdd.requestApi.params.status1 = newVal }, }, 'configDialogAdd.addUserForm.data.role1': { handler(newVal) { this.configDialogAdd.requestApi.params.role1 = newVal }, }, 'configDialogAdd.addUserForm.data.cascader': { handler(newVal) { this.configDialogAdd.requestApi.params.cascader = newVal }, }, }, }
DialogAdd.vue
<!-- --> <template> <el-dialog :visible.sync="defaultConfigDialogAdd.dialogVisible" :width="defaultConfigDialogAdd.width" :center="defaultConfigDialogAdd.isCenter" > <!-- 如果t写了插槽,外面使用其实是没必要传title属性。--> <div slot="title" class="dialog-title"> <slot name="title"> <h2 class="default-title">{{defaultConfigDialogAdd.title}}</h2> </slot> </div> <el-form :model="defaultConfigDialogAdd.addUserForm.data" :rules="defaultConfigDialogAdd.addUserForm.rules" :ref="defaultConfigDialogAdd.addUserForm.formName" :label-width="defaultConfigDialogAdd.addUserForm.labelWidth||'100px'" :label-position="defaultConfigDialogAdd.addUserForm.labelPosition" > <el-form-item v-for="item in defaultConfigDialogAdd.addUserForm.formItems" :key="item.prop" :label="item.label" :prop="item.prop" > <!-- 输入框 --> <template v-if="item.type==='input'"> <el-input v-model="defaultConfigDialogAdd.addUserForm.data[item.prop]"></el-input> </template> <template v-else-if="item.type==='numberInput'"> <el-input v-model.number="defaultConfigDialogAdd.addUserForm.data[item.prop]"></el-input> </template> <!-- --> <template v-else-if="item.type==='radio'"> <el-radio-group v-model="defaultConfigDialogAdd.addUserForm.data[item.prop]"> <el-radio v-for="item in item.values" :key="item" :label="item"></el-radio> </el-radio-group> </template> <template v-else-if="item.type==='switch'"> <el-switch v-model="defaultConfigDialogAdd.addUserForm.data[item.prop]"></el-switch> </template> <!-- 复选框 --> <template v-else-if="item.type==='checkbox'"> <el-checkbox-group v-model="defaultConfigDialogAdd.addUserForm.data[item.prop]"> <el-checkbox v-for="(item, index) in item.values" :key="index" :label="item"></el-checkbox> </el-checkbox-group> </template> <!-- 下拉框 --> <template v-else-if="item.type==='select'"> <el-select v-model="defaultConfigDialogAdd.addUserForm.data[item.prop]" placeholder="请选择"> <el-option v-for="item in item.options" :key="item.value" :label="item.label" :value="item.value" ></el-option> </el-select> </template> <!-- 级联选择器 --> <template v-else-if="item.type==='Cascader'"> <el-cascader v-model="defaultConfigDialogAdd.addUserForm.data[item.prop]" :options="item.options" @change="handleChange" ></el-cascader> </template> </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="handleCancel(defaultConfigDialogAdd.addUserForm.formName)">取 消</el-button> <el-button type="primary" @click="submitForm(defaultConfigDialogAdd.addUserForm.formName)" >立即创建</el-button> </span> </el-dialog> </template> <script> export default { name: "DialogAdd", props: { configDialogAdd: { type: Object, required: true } }, data() { return { defaultConfigDialogAdd: { dialogVisible: false, //弹框默认不可见 title: "提示", //默认标题 "30%", //默认宽度 isCenter: false, //是否对头部和底部采用居中布局 addUserForm: { formName: "", //表单名 labelWidth: "", //'100px' 长度 labelPosition: "right", //label对齐方式 left right top 默认是right formItems: [], data: {}, rules: {} }, requestApi: { apiName: "", params: {} } } }; }, methods: { async _request() { let { apiName, params } = this.defaultConfigDialogAdd.requestApi; try { return await this.$api[apiName](params); } catch (error) { throw error; //这里抛出异常,下面catch一定要捕获异常 } }, initDefaultConfigDialogAdd() { this.defaultConfigDialogAdd = { ...this.defaultConfigDialogAdd, ...this.configDialogAdd }; }, submitForm(formName) { this.$refs[formName].validate(async valid => { if (!valid) return this.$message.error("数据验证不通过"); //错误优先 // 发送网络请求_ this._request() .then(this.submitsuccess) .catch(err => err); }); }, // 增加用户网络行为成功之后的动作 submitsuccess() { //请求成功后的行为 this.$message.success("增加用户成功"); this.$refs[formName].resetFields(); this.defaultConfigDialogAdd.dialogVisible = false; }, handleCancel(formName) { // 重置输入框 this.$refs[formName].resetFields(); this.defaultConfigDialogAdd.dialogVisible = false; }, // 级联选择器的选择事件 (也可以放在最外面minix里面处理,当作事件参数传进来) handleChange(val) { console.log(val, 222); } }, created() { // 初始化弹框配置项的数据 this.initDefaultConfigDialogAdd(); }, watch: { // 外面的值变化,改变里面 "configDialogAdd.dialogVisible": { handler(val) { this.defaultConfigDialogAdd.dialogVisible = val; } }, // 里面的值发生变化,改变外面 "defaultConfigDialogAdd.dialogVisible": { handler(val) { this.configDialogAdd.dialogVisible = val; } } } }; </script> <style lang="scss" scoped> .dialog-title { color: #000; font-size: 20px; font-weight: 700; } </style>