在使用vue-element开发时遇到的需求、问题,对应的解决方案。

1.如何动态添加/删除某个表单项

如上图,点击加号就会生成一行表单,第一行不可以删除,不显示删除按钮,从第二行开始显示删除按钮。(需要注意的是目前实现的功能暂不支持从中间插入一行,比如你在第一行和第二行之间想插入一行,点击第一行的添加按钮,新的一行永远是加在最后的)

  • 解决方案:
<div v-for="(item, index) in temp.applyItem" :key="'applyItem'+index">
    <el-card class="box-card ml-10 mt-7 mr-10">
        <el-row>
            <el-form-item
                label="检查部位"
                :prop="'applyItem.' + index + '.examPartCode'"
            >
            <el-select v-model.trim="item.examPartCode" class="w-160" filterable clearable placeholder="请选择">
                <el-option
                v-for="(item,index) in examPartOptions"
                :key="'examPartCode'+index"
                :label="item.label"
                :value="item.id">
                </el-option>
            </el-select>
            </el-form-item>
            <el-form-item
                label="检查方法"
                :prop="'applyItem.' + index + '.examMethodCode'"
            >
            <el-select v-model.trim="item.examMethodCode" class="w-160" filterable clearable placeholder="请选择">
                <el-option
                    v-for="(item,index) in examMethodOptions"
                    :key="'examMethodCode'+index"
                    :label="item.label"
                    :value="item.id">
                </el-option>
            </el-select>
            </el-form-item>
            <el-form-item
                label="检查项目"
                :prop="'applyItem.' + index + '.itemCode'"
            >
            <el-select v-model.trim="item.itemCode" class="w-160" filterable clearable placeholder="请选择">
                <el-option
                v-for="(item,index) in examItemOptions"
                :key="'itemCode'+index"
                :label="item.label"
                :value="item.id">
                </el-option>
            </el-select>
            </el-form-item>

            <i class="el-icon-circle-plus"
                style="font-size: 20px; color: #0a76a4; vertical-align: middle; margin-top: 5px; margin-left: 5px"
                @click="addItem">
            </i>
            <i class="el-icon-delete"
                style="font-size: 20px; color: #CB0526; vertical-align: middle; margin-top: 5px; margin-left: 5px"
                @click="deleteItem(item, index)"
                v-if="index > 0">
            </i>
        </el-row>
    </el-card>
</div>

删除按钮的显示使用v-if判断就好了,使用 v-if="index > 0" 判断它不是第一行数据就好了

注意:prop的写法, :prop="'applyItem.' + index + '.examPartCode'"   applyItem是一个数组,具体定义如下代码片段。prop是以数组.下标.属性的形式拼接的   这两个 “点” 一定不能忽略,v-model直接绑定当前遍历对象的对应属性

data() {
    return {
        temp: {
          /* 其他字段 */
          applyItem: [{  //数组
            examMethodCode: "",
            examMethodName: "",
            examPartCode: "",
            examPartName: "",
            itemCode: "",
            itemName: ""
          }], //检查项目数组
        },
    };
},

下面是删除和添加一行表单的方法

methods: {
     
      //新增表单的检查项目
      addItem() {
        this.temp.applyItem.push({
          examPartCode: "",
          examPartName: "",
          itemCode: "",
          itemName: "",
          examMethodCode: "",
          examMethodName: "",
        });
      },
      //删除表单项目
      deleteItem(item, index) {
        this.temp.applyItem.splice(index, 1);
      },
      
}

添加只需要把这几个push进去就可以了,删除使用splice删除一个就好了,要注意如果你也是使用下拉形式,在提交时,把对应的name做赋值。  如果你用的input,则可以忽略下面的处理,其中examPartOptions等几个Options的定义为

examPartOptions: [
    {id: 1, label: "选项1"},
    {id: 2, label: "选项2"},
    {id: 3, label: "选项3"},
    // ......
]

 

methods: {
    createData() {
        this.$refs["dataForm"].validate((valid) => {
            if (valid) {
                let arr = this.temp.applyItem;
                // 遍历数组,对应赋值
                for (let i = 0; i < arr.length; i++) {
                    let examPart = this.examPartOptions.filter((item) => {
                    return item.id == arr[i].examPartCode;
                    });
                    let examItem = this.examItemOptions.filter((item) => {
                    return item.id == arr[i].itemCode;
                    });
                    let examMethod = this.examMethodOptions.filter((item) => {
                    return item.id == arr[i].examMethodCode;
                    });
                    arr[i].examPartName = examPart.length > 0 ? examPart[0].label : null;
                    arr[i].itemName = examItem.length > 0 ? examItem[0].label : null;
                    arr[i].examMethodName = examMethod.length > 0 ? examMethod[0].label : null;
                }
            // 提交表单的一些代码.......
            },
        }
    }
}
  • 如果需要表单检验怎么办

只需添加   :rules="rules.examPartCode"  然后 rules: {} 正常写就能分别对每一行的数据进行校验。

代码如下,注意与之前的不同,多了:rules

<el-form-item
    label="检查部位"
    :prop="'applyItem.' + index + '.examPartCode'"
    :rules="rules.examPartCode"
>
    <el-select v-model.trim="item.examPartCode" class="w-160" filterable clearable placeholder="请选择">
        <el-option
            v-for="(item,index) in examPartOptions"
            :key="'examPartCode'+index"
            :label="item.label"
            :value="item.id"
        >
        </el-option>
    </el-select>
</el-form-item>
data() {
    return {
        temp: {
          /* 其他字段 */
          applyItem: [{  //数组
            examMethodCode: "",
            examMethodName: "",
            examPartCode: "",
            examPartName: "",
            itemCode: "",
            itemName: ""
          }], //检查项目数组
        },
        // 表单规则
        rules: {
          /* 其他需要检验的表单规则 */
          examPartCode: [
            {
              required: true,
              message: "请选择检查部位",
              trigger: "blur, change",
            },
          ],
          itemCode: [
            {
              required: true,
              message: "请选择检查项目",
              trigger: "blur, change",
            },
          ],
          examMethodCode: [
            {
              required: true,
              message: "请选择检查方法",
              trigger: "blur, change",
            },
          ],
        }, 
    };
},

2.el-select多选时回显,赋值等问题

某些表单需要使用select多选时,在编辑和回显时会出现问题

我们v-model绑定的是temp.appoiMethods

temp中

上面那个仅用于接收后台传回的数据 格式为 1,2,3.....  以逗号分割的字符串

下面带s的是我们v-model绑定的  是一个数组  准确来说应该是number类型的(必须)可以参考vue官方文档关于 el-select 多选的描述

options如下

添加时都是没问题的,编辑回显会有回显问题和选中时没反应的问题,处理方式为

// 弹出编辑框
handleUpdate(row) {
    this.temp = Object.assign({}, row); // copy obj
    // 分割成字符数组
    let splitStr = (row.appoiMethod || "").split(',');
    // 定义一个新数组接收
    let appoiMethodArr = [];
    for (let item in splitStr) {
        // 解析成int,因为el-select 多选时回显需要number类型的数组(可以查阅官方文档)
        appoiMethodArr.push(parseInt(splitStr[item]));
    }
    this.temp.appoiMethods = appoiMethodArr;
    if (splitStr == "" || splitStr == null){  // 避免显示NaN
        row.appoiMethods = "";
        this.temp.appoiMethods = "";
    }
    
    // 其他操作
},

在我们做新增和修改的时候还需要把appoiMethods的值重新拼接成以“逗号”分割的串赋值给appoiMethod

//新增修改前给某些字段赋值
beforeAddOrUpdate() {
    let arr = [];
    for (let i = 0; i<this.temp.appoiMethods.length; i++) {
        arr.push(this.temp.appoiMethods[i])
    }
    // arr数组拼接“逗号”形成字符串,并赋值给appoiMethod 传给后端
    this.temp.appoiMethod = arr.join();
},

然后再新增和修改数据提交之前调用beforeAddOrUpdate方法,处理select多选需要的值

//新增
createData() {
    this.beforeAddOrUpdate();
    this.$refs["dataForm"].validate((valid) => {
    if (valid) {
            xxxxxx.add(this.temp).then((response) => {
                this.list.unshift(response.result);
                this.dialogFormVisible = false;
                this.$notify({
                    title: "成功",
                    message: "创建成功",
                    type: "success",
                    duration: 2000,
                });
            });
        }
    });
},

修改同上调用一下 this.beforeAddOrUpdate(); 即可

最后解决编辑时回显的问题,前面的虽然已经做到了数据的一致,没有差错,也可以正常编辑新增,但是在编辑时回显,虽然数据已经被选择了,但是页面却没动态响应,点了之后没反应,这时候就需要一个@change调用方法强制更新

<el-col :span="12">
    <el-form-item size="small" label="预约方式" prop="appoiMethod">
        <el-select class="filter-item"
                    v-model="temp.appoiMethods"
                    placeholder="请选择预约方式"
                    @change="appoiMethodChange"
                    clearable
                    filterable
                    multiple
        >
            <el-option v-for="(item,index) in appoiMethodOptions"
                        :key="index"
                        :label="item.label"
                        :value="item.key"></el-option>
        </el-select>
    </el-form-item>
</el-col>
appoiMethodChange(item) {
    this.$forceUpdate();
}

3.input表单校验时,规定保留n位小数点,输入多余的自动删除

<el-form-item label="患者身高" prop="patHeight">
    <el-input
        class="w-160"
        @keyup.native="temp.patHeight = oninput(temp.patHeight,2)"
        v-model="temp.patHeight"
        placeholder="请输入"
    ></el-input>
</el-form-item>

 

//oninput 限制输入框小数点位数,多出的过滤掉
oninput(num, limit) {
    let str = num
    let len1 = str.substr(0, 1)
    let len2 = str.substr(1, 1)
    //如果第一位是0,第二位不是点,就用数字把点替换掉
    if (str.length > 1 && len1 === 0 && len2 !== ".") {
        str = str.substr(1, 1)
    }
    //第一位不能是.
    if (len1 === ".") {
        str = ""
    }
    //限制只能输入一个小数点
    if (str.indexOf(".") !== -1) {
        var str_ = str.substr(str.indexOf(".") + 1)
        if (str_.indexOf(".") !== -1) {
        str = str.substr(0, str.indexOf(".") + str_.indexOf(".") + 1)
        }
    }
    //正则替换
    //str = str.replace(/[^\d^\.]+/g, '') // 保留数字和小数点
    str = str.replace(/[^\d^.]+/g, '') // 保留数字和小数点
    if (limit / 1 === 1) {
        str = str.replace(/^\D*([0-9]\d*\.?\d{0,1})?.*$/,'$1') // 小数点后只能输 1 位
    } else {
        str = str.replace(/^\D*([0-9]\d*\.?\d{0,2})?.*$/,'$1') // 小数点后只能输 2 位
    }
    return str
},

4.VUE2分页父子组件传值的问题(props父子组件 实现数据双向绑定)

在vue2中使用element的分页,数据都在父组件中,引用子组件table表格,且分页组件也在子组件,如果直接传分页参数到子组件,控制台会报错。注意(vue2中props属性只能父->子 而不能子->父 也就是说不能双向传值,这也造成无论你点那一页都不会切换,因为子组件的分页参数的值传不回来,父在请求时传的永远是第一次的参数,所以分页失败) 

父组件代码(只考虑本功能,为了避免其他无关数据干预,删除掉其他无关的数据,保证代码看起来清爽) MyTable即为子组件,通过props将分页参数传递给子组件

<template>
    <MyTable
        :listTotal="listTotal"
        :page="temp.page"
        :limit="temp.limit"
        @handleChildFun="handleChildFun"
    ></MyTable>
</template>
data() {
    return {
        list: null, // 页面数据
        listTotal: 0, // 页面数据行数
        loading: true,
        temp: {
            page: 1, // 第几页
            limit: 10, //每页显示几个
        },
    
    };
},
methods: {
    // 获取列表
    getList() {
        this.loading = true;
        xxxxx.getList(this.temp).then((res) => {
            this.listTotal = res.result.count;  //返回的当前列表数据个数赋值给listTotal
        });
    },

     // 处理子组件的方法
    handleChildFun(type, data) {
        // type为方法名, data为操作数据
        this[type](data);
    },

    // 分页事件
    handleCurrentChange(val) {
        this.temp.page = val.page;
        this.temp.limit = val.limit;
        this.getList(); //加载
    },
    // 子组件中watch监听子组件中的listTotal,一旦listToal值变化会立刻调用该方法将值回传,实现子->父传值
    onListTotalChange(val) {
        this.listTotal = val;
    },
    // 子组件中watch监听子组件中的page,一旦page值变化会立刻调用该方法将值回传,实现子->父传值
    onPageChange(val) {
        this.temp.page = val;
    },
    // 子组件中watch监听子组件中的limit,一旦limit值变化会立刻调用该方法将值回传,实现子->父传值
    onLimitChange(val) {
        this.temp.limit = val;
    },
},

子组件代码

<template>
    <div class="app-container">
        <el-table>
        </el-table>
        <pagination
            v-show="curListTotal > 0"
            :total="curListTotal"
            :page.sync="curPage"
            :limit.sync="curLimit"
            @pagination="handleCurrentChange"
        />
    </div>
</template>
export default {
  props: [
    "listTotal",
    "page",
    "limit",
  ],
  data() {
    return {  // 把上面props传来的父组件的值保存到子组件的数据中
      curListTotal: this.listTotal,
      curPage: this.page,
      curLimit: this.limit,
    };
  },
  watch: {
    // 一旦listToal值表动调用curListTotal  curListTotal通过emit 最终调用父组件中onListTotalChange方法,并把改变的值传回父组件  
    listTotal(val) {
      this.curListTotal = val;
    },
    curListTotal(val) {
      this.$emit("handleChildFun", "onListTotalChange", val);
    },

    page(val) {
      this.curPage = val;
    },
    curPage(val) {
      this.$emit("handleChildFun", "onPageChange", val);
    },

    limit(val) {
      this.curLimit = val;
    },
    curLimit(val) {
      this.$emit("handleChildFun", "onLimitChange", val);
    },
  },
  methods: {
    // 分页事件,调用父组件中的handleCurrentChange方法
    handleCurrentChange(val) {
      this.$emit("handleChildFun", "handleCurrentChange", val);
    },
  },
};

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vue-element-admin是一个基于Vue.jsElement UI的开源后台管理系统模板。它提供了一套完整的后台管理系统解决方案,包括基础的登录、权限控制、菜单管理、数据展示等功能模块。 vue-element-admin中文版是在vue-element-admin的基础上进行了中文语言的本地化处理,方便中文用户使用开发。通过使用vue-i18n国际化插件,vue-element-admin中文版能够在页面中进行中文的显示和切换。 vue-element-admin中文版提供了丰富的页面组件和模板,包括表格、表单、图表、地图等,可以快速构建各种类型的后台管理系统。它还提供了可配置的菜单管理模块,方便开发者根据自己的需求进行菜单的添加和调整。 在权限控制方面,vue-element-admin中文版提供了基于角色和路由的权限管理机制。通过配置角色和对应的路由权限,可以实现对用户在系统中的操作权限进行精确控制。 另外,vue-element-admin中文版还集成了常用的工具库和第三方插件,如axios用于进行网络请求,mock.js用于模拟后端接口数据,echarts用于数据可视化等。 总之,vue-element-admin中文版是一个功能强大、易于使用和扩展的后台管理系统模板,可以帮助开发者快速搭建符合自己需求的后台管理系统。无论是初学者还是有经验的开发者,都可以通过vue-element-admin中文版提供的丰富功能和文档资源,轻松构建高质量的后台管理系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值