赞
踩
更新于:2021-07-29 15:30
功能:input,select,搜索select,textarea,各种年月日,时分秒,switch,单选,多选,文件上传,按钮,text查看只读,富文本编辑器,百度地图(可选)
详解:element的form表单二次封装也很简单,写一个form表单你会发现不一样的地方只是form-item里面的组件类型而已。所以把form-item里面的内容可变化就行了。父级也只需通过一个数组(form-item里面组件类型数组),一个对象(form表单数据对象)控制就行了!为什么要多一个对象,是为了方便数据提交,以及数据验证。这次封装多加了el-col,也没有直接放进弹出框,是为了更加灵活可变!
1、form表单子组件代码(富文本编辑器,可根据项目需求,不引入也行)引入了自己单独二次封装一下
- <template>
- <el-form :model="formData" class="demo-ruleForm" ref="ruleForm" label-position="left" label-width="120px">
- <el-col v-for=" (formobj,index) in formObj" v-show="!formobj.notShow" :key="index" :span="formobj.width ? formobj.width : 24">
- <el-form-item :label="formobj.label" :prop="formobj.prop" :rules="formobj.rules">
- <!-- inupt输入框 -->
- <el-input v-if="formobj.input" v-model="formData[formobj.prop]" size="small" :disabled="formobj.disabled" :placeholder="formobj.placeholder" @input="inputINPUT($event,index,formobj.prop)" @change="inputChange($event,index,formobj.prop)" />
- <!-- textarea输入框 -->
- <el-input v-if="formobj.textarea" v-model="formData[formobj.prop]" size="small" type="textarea" :rows="formObj.rows" :disabled="formobj.disabled" :placeholder="formobj.placeholder" />
- <!-- select选择器 -->
- <el-select v-if="formobj.select" v-model="formData[formobj.prop]" size="small" :disabled="formobj.disabled" :placeholder="formobj.placeholder" @change="selectChange($event,index,formobj.prop)">
- <el-option v-for="(options, sIndex) in formobj.options" :key="sIndex" :label="options.label" :value="options.value" />
- </el-select>
- <!-- select搜索框 -->
- <el-select v-if="formobj.searchSelect" v-model="formData[formobj.prop]" size="small" :disabled="formobj.disabled" filterable remote reserve-keyword :placeholder="formobj.placeholder" :remote-method="(query)=>remoteMethod(query,index,formobj.prop)" :loading="searchSelectLoading" @change="selectChange($event,index,formobj.prop)">
- <el-option v-for="(item,ssIndex) in formobj.options" :key="ssIndex" :label="item.label" :value="item.value" />
- </el-select>
- <!-- 年月日时分秒选择器 -->
- <el-date-picker v-if="formobj.dateTime" v-model="formData[formobj.prop]" value-format="yyyy-MM-dd HH:mm:ss" type="datetime" size="small" :disabled="formobj.disabled" :placeholder="formobj.placeholder" />
- <!-- 年月日时分秒,开始和结束时间 -->
- <el-date-picker v-if="formobj.dateTimeRange" v-model="formData[formobj.prop]" value-format="yyyy-MM-dd HH:mm:ss" format="yyyy-MM-dd HH:mm:ss" size="small" type="datetimerange" :disabled="formobj.disabled" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" />
- <!-- 时分秒选择器 -->
- <el-time-picker v-if="formobj.timePicker" v-model="formData[formobj.prop]" value-format="HH:mm:ss" format="HH:mm:ss" size="small" :disabled="formobj.disabled" :placeholder="formobj.placeholder" :picker-options="formobj.options" />
- <!-- 时分秒选择器,开始和结束时间 -->
- <el-time-picker v-if="formobj.timePickerIsRange" v-model="formData[formobj.prop]" value-format="HH:mm:ss" format="HH:mm:ss" is-range size="small" :disabled="formobj.disabled" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" placeholder="选择时间范围" />
- <!-- 年月日选择器 -->
- <el-date-picker v-if="formobj.datePicker" v-model="formData[formobj.prop]" value-format="yyyy-MM-dd" size="small" :disabled="formobj.disabled" :placeholder="formobj.placeholder" />
- <!-- 年月日选择器,开始和介绍年月日 -->
- <el-date-picker v-if="formobj.datePickerIsRange" v-model="formData[formobj.prop]" value-format="yyyy-MM-dd" type="daterange" size="small" :disabled="formobj.disabled" :placeholder="formobj.placeholder" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" />
- <!-- switch开关 -->
- <el-switch v-if="formobj.switch" v-model="formData[formobj.prop]" size="small" :disabled="formobj.disabled" @change="formSwitchChange($event,index,formobj.prop)" />
- <!-- radio单选框 -->
- <el-radio-group v-if="formobj.radio" v-model="formData[formobj.prop]" :disabled="formobj.disabled">
- <el-radio v-for="(options, rIndex) in formobj.options" :key="rIndex" :label="options.label" :value="options.value" />
- </el-radio-group>
- <!-- checkbox复选框 -->
- <el-checkbox-group v-if="formobj.checkbox" v-model="formData[formobj.prop]" :disabled="formobj.disabled">
- <el-checkbox v-for="options in formobj.options" :key="options.value" :label="options.label" />
- </el-checkbox-group>
-
- <!-- 文件上传 -->
- <!-- 如果对象有值就回显,没有值就为空 -->
- <el-upload v-if="formobj.upload" :ref="formobj.prop"
- :accept="formobj.accept ? formobj.accept : 'PNG,JPEG'"
- :file-list=" formData[formobj.prop] ? formData[formobj.prop] : []"
- :action="`${uploadUrl}${formobj.uploadObj.fileType ? formobj.uploadObj.fileType : '' }`"
- :limit="formobj.uploadObj.limit"
- :class="{'hide':formobj.uploadObj.hideUpload || formData[formobj.prop].length==formobj.uploadObj.limit}"
- :on-preview="handlePictureCardPreview"
- :on-remove="(file,fileList)=>handleRemove(file,fileList,formobj.uploadObj.limit,formobj.prop,index)"
- :on-success="(response,file,fileList)=>uploadSuccess(response,file,fileList,formobj.uploadObj.limit,formobj.prop,index)"
- list-type="picture-card" :auto-upload="true">
- <i slot="default" class="el-icon-plus" />
- </el-upload>
- <el-dialog v-if="formobj.upload" :visible.sync="dialogVisible" :append-to-body="true" width="40%">
- <img width="100%" :src="dialogImageUrl" alt="">
- </el-dialog>
-
- <!-- 按钮 -->
- <el-button v-if="formobj.button" size="small" :disabled="formobj.disabled" :loading="formobj.loading" :type="formobj.buttonType || 'primary'" @click="buttonClick(formobj.prop,index)">
- {{ formobj.placeholder }}
- </el-button>
- <!-- text展示 -->
- <span v-if="formobj.text" v-text="formData[formobj.prop]" />
- <!-- 计量单位 -->
- <span v-if="formobj.unit" class="left10">{{ formobj.unit }}</span>
-
- <!-- 高德地图 -->
- <!-- <div class="amap_div" v-if="formobj.aMap">
- <el-input size="small" v-model="formData[formobj.prop]" @input="aMapInput($event,formobj.prop)"></el-input>
- <ul v-show="searchShow==formobj.prop" class="sreach_ul">
- <li @click="selectVal(sval,formobj.prop,index)" v-for=" (sval, index) in setSearchVal" :key="index">{{sval.name}}
- <span style="color:#8591A6 ;font-size: 12px;">{{sval.district}}</span>
- </li>
- </ul>
- <aMap :ref="'aMap'+formobj.prop" :aMapId="'aMapId'+formobj.prop" :location="formData[formobj.prop+'location']" @cbSearch="cbSearch($event,formobj.prop)"></aMap>
- </div> -->
- <quillEditor v-if="formobj.quillEditor" :quill="formData[formobj.prop]"></quillEditor>
-
- </el-form-item>
- </el-col>
- </el-form>
- </template>
- <!-- zoutiancong封装,date:20210429,详细使用见根目录@/views/home/testForm/testForm.vue,———————————————————————————————————————————————————————————————————————————————— -->
- <script>
- // import aMap from '../../map/aMap.vue'
- import quillEditor from '@/components/quillEditor/quillEditor.vue'
- export default {
- components:{
- quillEditor
- },
- props: {
- formObj: {
- type: Array,
- required: true
- },
- formData: {
- type: Object,
- required: true
- },
- searchSelectOptionsCb:{
- type:Array,
- }
- },
- data() {
- let uploadFileUrl = this.$store.state.user.uploadFileUrl;
- return {
- uploadUrl:uploadFileUrl,
- dialogImageUrl: '',
- searchSelectLoading:false,
- dialogVisible: false,
- disabled: false,
- searchShow: '', //高德地图input收索联想
- setSearchVal: [], //高德地图赋值搜索内容
- };
- },
- created() {
- },
- watch:{
- },
- methods: {
- //select变化调用
- selectChange(value, index, prop) {
- this.$emit('selectChange', value, index, prop);
- },
- // input的input事件
- inputINPUT(value, index, prop){
- this.$emit('inputINPUT', value, index, prop);
- },
- // input的change事件
- inputChange(value, index,prop){
- this.$emit('inputChange', value,index, prop);
- },
- // 搜索类型select搜索
- remoteMethod(query,index,prop) {
- if (query) {
- this.searchSelectLoading = true;
- this.$emit('querySelectValue',query,index,prop);
- setTimeout(() => {
- this.formObj[index].options = this.searchSelectOptionsCb;
- this.searchSelectLoading = false;
- }, 500)
- } else {
- this.searchSelectOptios = [];
- }
- },
- //switch变化
- formSwitchChange(val,index,prop){
- this.$emit("formSwitchChange",val,index,prop);
- },
- //按钮点击事件
- buttonClick(prop,index){
- this.$emit("buttonClick",prop,index);
- },
-
- //文件上传成功回调
- uploadSuccess(response,file,fileList,limit,prop,index) {
- this.formObj[index].uploadObj.hideUpload=fileList.length==limit;//文件列表变化后判断当前文件列表长度是否等于限制长度。目的,当长度相等时隐藏文件上传按钮
- this.pushUpload(file,fileList,limit,prop);
- },
- //文件删除
- handleRemove(file,fileList,limit,prop,index) {
- this.formObj[index].uploadObj.hideUpload=fileList.length==limit;//文件删除后判断当前文件列表长度是否等于限制长度。目的,当长度相等时隐藏文件上传按钮
- this.pushUpload(file,fileList,limit,prop);
- },
- // 文件预览
- handlePictureCardPreview(file) {
- this.dialogImageUrl = file.url;
- this.dialogVisible = true;
- },
-
- //提交时验证表单,直接在父级调用
- submitForm() {
- let formValidate=Boolean;
- this.$refs.ruleForm.validate((valid) => {
- if (valid) {
- formValidate=true;
- } else {
- this.$message.warning("请把信息填写完整!");
- formValidate = false;
- }
- });
- return formValidate;
- },
- /* 清空表单
- 逻辑:
- 1 、如果要清空文件上传列表,要传入要清空的upload的字段名,假如多个upload用for循环,调用清空方法!
- 2、清空upload之后,还要把upload上传框展示出来,通过字段名比对,获取到在formObj中的下标,通过下标操作对象属性,进行展示
- */
- resetForm(uploadArr) {
- this.$refs.ruleForm.resetFields();
- if(uploadArr){
- for(let i=0;i<uploadArr.length;i++){
- this.$refs[uploadArr[i]][0].clearFiles();
- let index=this.formObj.findIndex(item=>item.prop==uploadArr[i]);
- this.formObj[index].uploadObj.hideUpload=false;
- }
- }
- },
- // 单个字段验证
- validateFieldProp(prop){
- let formValidate=Boolean;
- this.$refs.ruleForm.validateField(prop,valid => {
- if (!valid) {
- formValidate=true;
- } else {
- formValidate = false;
- }
- });
- return formValidate;
- },
- // 对文件上传,删除进行赋值,调用form验证
- pushUpload(file, fileList,limit,prop){
- if(fileList.length>0){
- this.formData[prop]=fileList;
- }else{
- // 表示没有数据,把字段置空
- this.formData[prop]="";
- }
- this.$refs.ruleForm.validateField(prop);//调用验证form表单的文件上传
- },
- //地图input的input事件
- aMapInput(value, prop) {
- this.$refs[`aMap${prop}`][0].getSearch(value);
- },
- //子组件返回地图搜索值
- cbSearch(val,prop) {
- this.setSearchVal = val.tips; //子组件
- this.searchShow = prop; //显示input输入联想
- },
- //选中地图值
- selectVal(val,prop,index) {
- // 赋值的时候,拿到键,及formobj的下标,进行赋值
- this.formData[prop] = val.name; //input输入框赋值
- this.formData.district = val.district; //传入省市区
- let lngLat = {
- lng: val.location.lng,
- lat: val.location.lat
- };
- this.formData[`${prop}location`] = lngLat;
- this.searchShow = ''; //隐藏input输入联想
- },
-
- }
- }
- </script>
-
- <style lang="less" scoped>
- @width: 220px;
-
- form {
- overflow: hidden;
- }
-
- /deep/.el-input {
- width: @width;
- }
-
- /deep/.el-select {
- width: @width;
- }
-
- /deep/.el-date-editor.el-input {
- width: @width;
- }
- /deep/.el-date-editor .el-range-separator{
- width: 20px !important;
- }
- /deep/.el-range-editor--small.el-input__inner{
- width: 400px;
- }
-
- .el-textarea {
- width: 400px;
- }
-
- .hide {
- /deep/ .el-upload--picture-card {
- display: none;
- }
- }
- .amap_div {
- overflow: hidden;
- height: 400px;
- width: 600px;
- position: relative;
-
- .sreach_ul {
- position: absolute;
- top: 1;
- background-color: white;
- z-index: 9;
- min-width: 210px;
- float: auto;
- height: 200px;
- overflow: auto;
- padding: 0 20px;
- line-height: 24px;
- }
- }
- </style>
2、父组件调用
- <template>
- <div>
- <el-button type="primary" @click="dialog = true" size="mini">点击打开 Dialog</el-button>
- <el-dialog title="提示" :visible.sync="dialog" width="1200px" :modal-append-to-body="false">
- <publicForm ref="publicForm" :formObj="formObj" :formData="formData"
- :searchSelectOptionsCb="searchSelectOptionsCb" @selectChange="selectChange" @inputINPUT="inputINPUT"
- @inputChange="inputChange" @querySelectValue="querySelectValue" @formSwitchChange="formSwitchChange"
- @buttonClick="buttonClick">
- </publicForm>
- <span slot="footer" class="dialog-footer">
- <el-button type="primary" @click="dialogOK">确认</el-button>
- <el-button @click="dialog=false">取 消</el-button>
- </span>
- </el-dialog>
- </div>
-
- </template>
-
- <script>
- import formJs from './js/testForm.js'
- export default {
- components: {},
- data() {
- return {
- dialog: false, //弹出框
- formObj: formJs.formObj,
- formData: formJs.formData,
- searchSelectOptionsCb: [], //form表单搜索select返回值
- };
- },
- watch: {
- dialog(newVal, oldVal) {
- if (!newVal) {
- this.$refs.publicForm.resetForm(); //窗口关闭清空表单
- }
- },
- },
- methods: {
- // select选择框变化
- selectChange(value, index, prop) {
- console.log(value, index, prop)
- },
- // inpuit变化
- inputINPUT(value, index, prop) {
- console.log(value, index, prop)
- },
- // inpuit Change
- inputChange(value, index, prop) {
- console.log(value, index, prop)
- },
- // select 搜索值
- querySelectValue(value, index, prop) {
- console.log(value, index, prop)
- let arr = [{
- label: '搜索返回1号',
- value: 1
- }, {
- label: '搜索返回2号',
- value: 2
- }];
- this.searchSelectOptionsCb = arr;
- },
- // form表单switch变化
- formSwitchChange(val, index, prop) {
- console.log(val, index, prop)
- },
- // 按钮点击
- buttonClick(index, prop) {
- console.log(index, prop)
- },
- dialogOK() {
- //判断表单验证是否通过
- if (this.$refs.publicForm.submitForm()) {
- console.log("success");
- console.log(this.formData)
- } else {
- console.log("error")
- }
- },
- }
- }
- </script>
-
- <style lang="less" scoped>
-
- </style>
3、父组件js(正则表达式js可以不用,或者自己封装)
- import regex from '../../../../utils/regex.js' // 正则表达式
- export default {
- formObj: [{
- input: true, //是input
- label: "input+正则", //字段
- prop: "input", //字段名
- placeholder: "请填写手机号", //提示内容
- width: 12, //参考el-col
- disabled: false, //是否禁用
- unit:'单位',
- rules: [{
- required: true,
- message: '联系方式'
- }, { //可以自己写utils,封装正则验证
- validator: (rule, value, callback) => {
- if (!value || !regex.isPhone(value)) {
- callback(new Error());
- } else {
- callback();
- }
- },
- message: "联系方式不对",
- }] //验证
- }, {
- textarea: true, //是input
- label: "输入框", //字段
- prop: "textearea", //字段名
- placeholder: "请填写输入框", //提示内容
- width: 12, //参考el-col
- disabled: false, //是否禁用
- rules: [{
- required: true,
- message: '输入框'
- }, ] //验证
- },
- {
- select: true,
- label: "选择框",
- prop: "select",
- placeholder: "请选择",
- width: 12, //参考el-col
- disabled: false,
- options: [{
- label: "options1",
- value: "1"
- }, {
- label: "options2",
- value: "2"
- }, ],
- rules: [{
- required: true,
- message: '选择框不能为空!'
- }]
- }, {
- searchSelect: true,
- label: "select搜索框",
- prop: "searchSelect",
- placeholder: "请选择",
- width: 12, //参考el-col
- disabled: false,
- options: [],
- rules: [{
- required: true,
- message: 'select搜索框!'
- }]
- }, {
- dateTimeRange: true,
- label: "年月日时分秒开",
- prop: "dateTimeRange",
- width: 12, //参考el-col
- disabled: false,
- options: {
- selectableRange: '18:30:00 - 20:30:00'
- },
- rules: [{
- required: true,
- message: '年月日时分秒开'
- }, ]
- }, {
- timePicker: true,
- label: "时分秒选择器",
- prop: "timePicker",
- placeholder: "请选择",
- width: 12, //参考el-col
- disabled: false,
- options: "",
- rules: [{
- required: true,
- message: '时分秒选择器'
- }, ]
- }, {
- timePickerIsRange: true,
- label: "时分秒开始结束",
- prop: "timePickerIsRange",
- placeholder: "请选择",
- width: 12, //参考el-col
- disabled: false,
- options: "",
- rules: [{
- required: true,
- message: '时分秒开始结束'
- }, ]
- }, {
- datePicker: true,
- label: "年月日选择器",
- prop: "datePicker",
- placeholder: "请选择",
- width: 12, //参考el-col
- disabled: false,
- options: "",
- rules: [{
- required: true,
- message: '年月日选择器'
- }, ]
- }, {
- datePickerIsRange: true,
- label: "年月日开始结束",
- prop: "datePickerIsRange",
- placeholder: "请选择",
- width: 12, //参考el-col
- disabled: false,
- options: "",
- rules: [{
- required: true,
- message: '年月日开始结束'
- }, ]
- }, {
- dateTime: true,
- label: " 年月日时分秒",
- prop: "dateTime",
- placeholder: "请选择",
- width: 12, //参考el-col
- disabled: false,
- options: "",
- rules: [{
- required: true,
- message: ' 年月日时分秒'
- }, ]
- }, {
- switch: true,
- label: "switch",
- prop: "switch",
- placeholder: "请选择",
- width: 12, //参考el-col
- disabled: false,
- rules: [{
- required: true,
- message: 'switch'
- }, ]
- }, {
- radio: true,
- label: "单选框",
- prop: "radio",
- placeholder: "请选择",
- width: 12, //参考el-col
- disabled: false,
- options: [{
- label: "单选框1",
- value: "1"
- }, {
- label: "单选框2",
- value: "2"
- }, ],
- rules: [{
- required: true,
- message: '单选框不能为空'
- }, ]
- }, {
- checkbox: true,
- label: "复选框",
- prop: "checkbox",
- disabled: false,
- width: 12, //参考el-col
- options: [{
- label: "复选框1",
- value: "1"
- }, {
- label: "复选框2",
- value: "2"
- }, {
- label: "复选框3",
- value: "3"
- }, ],
- rules: [{
- required: true,
- message: '复选框不能为空'
- }, ]
- },
- {
- upload: true,
- label: "文件上传",
- prop: "upload",
- disabled: false,
- uploadObj: {
- fileType: "2001",
- limit: 1, //上传长度限制
- hideUpload: false, //是否隐藏上传框
-
- },
- rules: [{
- required: true,
- message: '文件上传'
- }, ]
- },
- {
- button: true,
- label: "按钮",
- prop: "buttona",
- placeholder:"发送验证码",
- width: 12, //参考el-col
- disabled: false,
- },
- {
- text: true,
- label: "文本",
- prop: "text",
- width: 12, //参考el-col
- disabled: false,
- },
- {
- quillEditor: true,
- label: "富文本",
- prop: "quill",
- disabled: false,
- },
- ],
- formData: {
- input: "",
- textearea: "",
- select: "",
- searchSelect: "",
- dateTimeRange: [],
- timePicker: "",
- timePickerIsRange: [],
- datePicker: "",
- datePickerIsRange: [],
- dateTime: "",
- date1: "",
- switch: false,
- radio: "",
- checkbox: [],
- upload: [],
- text:"这是一段文本,用于预览",
- quill:{
- content:""
- }
- },
- }
4、效果图预览
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。