前言
我司最近在搭建一款后盾管理系统,应用的是Vue全家桶配合Element-ui,遇到一个问题,须要解决很多的表单,所以想到的解决方案是通过后盾配置生成动静表单,这对于我来说也算是新的挑战,波及的性能有动静表单渲染和验证,那么一起来学习一下我是如何实现的吧!
本文仅仅代表笔者本人的思路,如果您有更好的实现形式,能够在下方留下您贵重的倡议。笔者将非常感激
开发筹备
须要储备的知识点
- 理解Element ui表单
- 理解Vue中的$set(target,key,value)办法
- 理解vant中的表单组件
本我的项目是基于vue-cli2.0搭建的脚手架,在这里默认大家搭建好了,谁赞成,谁拥护!
动态表单数据筹备
后盾返回的数据是这样的,这里咱们拿一个json数据举例
{ "showName": "姓名", // 名称 "showValue": null, //值 "htmlElements": "输入框", // 表单类型 "fieldLength": 99, // 字段长度 "requiredOrNot": 1, // 是否必填}
而后类型的话大略有以下几种
- 输入框
- 文本域
- 日历控件
- 下拉框
- 单选框
- 复选框
咱们为每一种类型生成一种组件,Test.vue组件外面
data(){ return{ fieldArray:[],// 表单字段汇合 fieldObj:{}, sex:[{ // 性别 name:'男', value:"male" },{ name:"女", value:"female" } ], hobbies:[ // 喜好 { name:"吃饭", value:"吃饭" },{ name:"玩游戏", value:"玩游戏" },{ name:"打豆豆", value:"打豆豆" }, ], job:[{ // 职业 name:"医生", value:"doctor" },{ name:"老师", value:"teacher" },{ name:"司机", value:"driver" } ] }}
这里筹备多种日历控件是因为后续手机端应用vant组件的时候须要用到
因为vue中的数据是双向绑定的,所以只有在data外面的数据是能够实现双向绑定的,从新向data外面增加的数据无奈达到双向绑定的成果,官网为咱们提供了一个set办法。
作为靓仔的我,必定很贴心的为大家筹备了官网链接
官网链接
这里就不过多解说,官网比拟权威,本篇博客的重点是动静表单。
Vue.set(target,propertyName/index,value)
参数:
{Object | Array} target
{string | number} propertyName/index
{any} value
- 返回值:设置的值。
用法:
向响应式对象中增加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上增加新 property,因为 Vue 无奈探测一般的新增 property (比方 this.myObject.newProperty = 'hi'
)
留神对象不能是 Vue 实例,或者 Vue 实例的根数据对象。
Element-ui表单元素
官网链接
动静表单渲染
这里应用axios申请本地json数据,static/json/form.json
{ "data":[ { "showName": "姓名", "showValue": null, "htmlElements": "输入框", "fieldLength": 10, "requiredOrNot": 1, "desc":"请输出姓名" }, { "showName": "形容", "showValue": null, "htmlElements": "文本域", "fieldLength": 99, "requiredOrNot": 1, "desc":"请输出形容" }, { "showName": "喜好", "showValue": null, "htmlElements": "复选框", "requiredOrNot": 1, "desc":"请抉择喜好" }, { "showName": "性别", "showValue": null, "htmlElements": "单选框", "requiredOrNot": 1 }, { "showName": "出生日期", "showValue": null, "htmlElements": "日历控件", "requiredOrNot": 1, "desc":"请抉择出生日期" }, { "showName": "结婚工夫", "showValue": null, "htmlElements": "日历控件", "requiredOrNot": 1, "desc":"请抉择结婚工夫" }, { "showName": "职业", "showValue": null, "htmlElements": "下拉框", "requiredOrNot": 1, "desc":"请抉择职业" } ]}
Test.vue文件
<template> <div> <h2>测试动静表单</h2> <el-form :model="fieldObj" ref="ruleForm" label-width="180px" class="demo-ruleForm"> <template v-for="(item,index) of fieldArray"> <template v-if="item.htmlElements==='输入框'"> <el-form-item :label="item.showName"> <el-input v-model="fieldObj[item.showName]" :max="item.fieldLength" :placeholder="item.desc" show-word-limit></el-input> </el-form-item> </template> <template v-if="item.htmlElements==='文本域'"> <el-form-item :label="item.showName"> <el-input type="textarea" rows="4" :placeholder="item.desc" v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit></el-input> </el-form-item> </template> <template v-if="item.htmlElements==='日历控件'"> <el-form-item :prop="item.showName" :label="item.showName"> <el-date-picker v-model="fieldObj[item.showName]" :name="item.showName" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" :placeholder="item.desc" ></el-date-picker> </el-form-item> </template> <template v-if="item.htmlElements==='下拉框'"> <el-form-item :label="item.showName"> <el-select v-model="fieldObj[item.showName]" :placeholder="item.describe"> <el-option v-for="items in job" :key="items.name" :label="items.name" :value="items.value"> </el-option> </el-select> </el-form-item> </template> <template v-if="item.htmlElements==='单选框'"> <el-form-item :label="item.showName"> <template v-for="(child,index) in sex"> <el-radio v-model="fieldObj[item.showName]" :label="child.value">{{child.name}}</el-radio> </template> </el-form-item> </template> <template v-if="item.htmlElements==='复选框'"> <el-form-item :label="item.showName"> <el-checkbox-group v-model="fieldObj[item.showName]"> <template v-for="(child,index) of hobbies"> <el-checkbox :label="child.name"></el-checkbox> </template> </el-checkbox-group> </el-form-item> </template> </template> </el-form> </div></template><script> import axios from 'axios' export default { name: "Test", data(){ return{ fieldArray:[],// 表单字段汇合 fieldObj:{}, sex:[{ // 性别 name:'男', value:"male" },{ name:"女", value:"female" } ], hobbies:[ // 喜好 { name:"吃饭", value:"吃饭" },{ name:"玩游戏", value:"玩游戏" },{ name:"打豆豆", value:"打豆豆" }, ], job:[{ // 职业 name:"医生", value:"doctor" },{ name:"老师", value:"teacher" },{ name:"司机", value:"driver" } ] } }, mounted(){ this.getFieldData(); }, methods:{ getFieldData(){ // 获取动静表单数据 axios.get("../static/json/form.json").then(data=>{ let response=data.data.data; this.fieldArray=response; for(let i=0;i<response.length;i++){ let item=response[i]; if(item.htmlElements==='复选框'){ this.$set(this.fieldObj,item.showName,[]); }else { this.$set(this.fieldObj,item.showName,item.showValue); } } }) } } }</script><style scoped></style>
当初的话,表单曾经全副渲染结束了,也实现了双向绑定,当初须要做的是如何实现动静表单验证。
官网解释:Form 组件提供了表单验证的性能,只须要通过 rules
属性传入约定的验证规定,并将 Form-Item 的 prop
属性设置为需校验的字段名即可,
- prop字段
- rules
- model
在这里rules设置为动静的,而不是放在data外面提前写好,这里须要晓得每一种类型的触发模式
- 输入框/文本域 trigger: 'blur'
- 单选框/复选框/日历控件/下拉框 trigger: 'change'
动静表单验证
对于表单中的每一种验证模式都理解之后,Test.vue外面的文件就变成了
<template> <div> <h2>测试动静表单</h2> <el-form :model="fieldObj" ref="ruleForm" label-width="180px" class="demo-ruleForm"> <template v-for="(item,index) of fieldArray"> <template v-if="item.htmlElements==='输入框'"> <el-form-item :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: '请输出'+item.showName, trigger: 'blur' }]:[]"> <el-input v-model="fieldObj[item.showName]" :max="item.fieldLength" :placeholder="item.desc" show-word-limit ></el-input> </el-form-item> </template> <template v-if="item.htmlElements==='文本域'"> <el-form-item :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: '请输出'+item.showName, trigger: 'blur' }]:[]"> <el-input type="textarea" rows="4" :placeholder="item.desc" v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit></el-input> </el-form-item> </template> <template v-if="item.htmlElements==='日历控件'"> <el-form-item :prop="item.showName" :label="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: '请抉择'+item.showName, trigger: 'change' }]:[]"> <el-date-picker v-model="fieldObj[item.showName]" :name="item.showName" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" :placeholder="item.desc" ></el-date-picker> </el-form-item> </template> <template v-if="item.htmlElements==='下拉框'"> <el-form-item :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: '请抉择'+item.showName, trigger: 'change' }]:[]"> <el-select v-model="fieldObj[item.showName]" :placeholder="item.describe"> <el-option v-for="items in job" :key="items.name" :label="items.name" :value="items.value"> </el-option> </el-select> </el-form-item> </template> <template v-if="item.htmlElements==='单选框'"> <el-form-item :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: '请抉择'+item.showName, trigger: 'change' }]:[]"> <template v-for="(child,index) in sex"> <el-radio v-model="fieldObj[item.showName]" :label="child.value">{{child.name}}</el-radio> </template> </el-form-item> </template> <template v-if="item.htmlElements==='复选框'"> <el-form-item :label="item.showName" :prop="item.showName" :rules="item.requiredOrNot==1?[{ required: true, message: '请抉择'+item.showName, trigger: 'change' }]:[]"> <el-checkbox-group v-model="fieldObj[item.showName]"> <template v-for="(child,index) of hobbies"> <el-checkbox :label="child.name"></el-checkbox> </template> </el-checkbox-group> </el-form-item> </template> </template> <div class="text-align"> <el-button type="primary" @click="submitForm('ruleForm')">立刻创立</el-button> <el-button @click="resetForm('ruleForm')">重置</el-button> </div> </el-form> </div></template><script> import axios from 'axios' export default { name: "Test", data(){ return{ fieldArray:[],// 表单字段汇合 fieldObj:{}, sex:[{ // 性别 name:'男', value:"male" },{ name:"女", value:"female" } ], hobbies:[ // 喜好 { name:"吃饭", value:"吃饭" },{ name:"玩游戏", value:"玩游戏" },{ name:"打豆豆", value:"打豆豆" }, ], job:[{ // 职业 name:"医生", value:"doctor" },{ name:"老师", value:"teacher" },{ name:"司机", value:"driver" } ] } }, mounted(){ this.getFieldData(); }, methods:{ getFieldData(){ // 获取动静表单数据 axios.get("../static/json/form.json").then(data=>{ let response=data.data.data; this.fieldArray=response; for(let i=0;i<response.length;i++){ let item=response[i]; if(item.htmlElements==='复选框'){ this.$set(this.fieldObj,item.showName,[]); }else { this.$set(this.fieldObj,item.showName,item.showValue); } } }) }, submitForm(formName){ // 提交验证 this.$refs[formName].validate((valid) => { if (valid) { console.log('提交数据'); } else { return false; } }); }, resetForm(formName) { // 重置表单 this.$refs[formName].resetFields(); } } }</script><style scoped></style>
新增的内容有:
- el-form-item新增了:prop="item.showName"
- el-form-item新增了:rules="item.requiredOrNot==1?[{ required: true, message: '请抉择'+item.showName, trigger: 'change' }]:[]"
- el-form-item新增了:rules="item.requiredOrNot==1?[{ required: true, message: '请输出'+item.showName, trigger: 'blur' }]:[]"
- methods外面新增了验证办法和重置表单的办法
vant动静表单验证
因为pc端和手机端是配套应用的,所以手机端咱们也实现动静表单的性能,
废话不多说上号!
还是拿Test.vue组件来举例子,对于挪动端的话,首先须要装置vant依赖,默认大家曾经装置好了。
vant官网
动静表单渲染
因为手机端没有下拉框这个组件,而是应用Picker选择器来代替,那么就须要思考一个问题,多个picker的话怎么实现一一对应呢?该怎么解决?
form.json外面新增一个对象-城市,之前的代码还是能够复用
{ "showName": "城市", "showValue": null, "htmlElements": "下拉框", "requiredOrNot": 1, "desc":"请抉择职业"}
这样一来就有多个下拉框,从而来解决多个picker的问题。
Test.vue的代码
html代码区
<template> <div> <h2 class="title">测试vant动静表单</h2> <van-form @submit="submitClaim"> <template v-for="(item,index) of fieldArray"> <template v-if="item.htmlElements==='输入框'"> <van-field :maxlength="item.fieldLength" show-word-limit v-model="fieldObj[item.showName]" :name="item.showName" :label="item.showName"/> </template> <template v-if="item.htmlElements==='文本域'"> <van-field rows="2" autosize :label="item.showName" :name="item.showName" type="textarea" v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit/> </template> <template v-if="item.htmlElements==='日历控件'"> <van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" /> </template> <template v-if="item.htmlElements==='复选框'"> <van-field :name="item.showName" :label="item.showName"> <template #input> <van-checkbox-group v-model="fieldObj[item.showName]" direction="horizontal"> <template v-for="(child,index) of hobbies"> <van-checkbox :name="child.value">{{child.name}}</van-checkbox> </template> </van-checkbox-group> </template> </van-field> </template> <template v-if="item.htmlElements==='单选框'"> <van-field :name="item.showName" :label="item.showName"> <template #input> <van-radio-group v-model="fieldObj[item.showName]" direction="horizontal"> <template v-for="(child,index) of sex"> <van-radio :name="child.value">{{child.name}}</van-radio> </template> </van-radio-group> </template> </van-field> </template> <template v-if="item.htmlElements==='下拉框'"> <van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]"/> </template> </template> </van-form> </div></template>
JavaScript代码区
import axios from 'axios' export default { name: "Test", data(){ return{ fieldArray:[],// 表单字段汇合 fieldObj:{}, sex:[{ // 性别 name:'男', value:"male" },{ name:"女", value:"female" } ], hobbies:[ // 喜好 { name:"吃饭", value:"吃饭" },{ name:"玩游戏", value:"玩游戏" },{ name:"打豆豆", value:"打豆豆" }, ], } }, mounted(){ this.getFieldArray(); }, methods:{ getFieldArray(){ // 获取本地动静表单配置json数据 axios.get("../../static/json/form.json").then(data=>{ let response=data.data.data; this.fieldArray=response; for(let i=0;i<response.length;i++){ let item=response[i]; if(item.htmlElements==='复选框'){ this.$set(this.fieldObj,item.showName,[]); }else { this.$set(this.fieldObj,item.showName,item.showValue); } } }) }, submitClaim(taskInfo){ } } }
当初的话根本实现了输入框,文本域,单选框,复选框的值双向绑定,下一步是解决多个日历框和下拉框的取值一一对应。
日历框和弹出层都是通过v-model来管制显示和暗藏,所以只需晓得日历框和弹出层的个数,而后循环遍历解决就能够了,getFieldArray办法重新处理
axios.get("../../static/json/form.json").then(data=>{ let response=data.data.data; this.fieldArray=response; for(let i=0;i<response.length;i++){ let item=response[i]; if(item.htmlElements==='复选框'){ this.$set(this.fieldObj,item.showName,[]); }else if(item.htmlElements==='日历控件'){ this.$set(this.dateObj,item.showName,false); // 日历控件全副先暗藏 this.$set(this.fieldObj,item.showName,item.showValue); }else if(item.htmlElements=='下拉框'){ this.$set(this.fieldObj,item.showName,item.showValue); this.$set(this.dropDownObj,item.showName,false); // 弹出层全副先暗藏 }else { this.$set(this.fieldObj,item.showName,item.showValue); } }})
data数据外面新增 dateObj对象
dateObj:{},// 管制日期的显示暗藏
解决日历控件
页面html新增相干内容
<van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" @click="dateObj[item.showName]=true"/><template v-for="(item,key,index) of dateObj"> <van-calendar v-model="dateObj[key]" @confirm="(date)=>onConfirmTime(date,item,key)"/> </template>
methods新增办法
onConfirmTime(date,item,key){ // 日历控件 this.fieldObj[key]=this.formatDate(date); this.dateObj[key]=false;},formatDate(date) { // 格式化日期 let year=date.getFullYear(); let month=date.getMonth()+1; let day=date.getDate(); if(month<10){ month='0'+month; } if(day<10){ day='0'+day; } return `${year}-${month}-${day}`;},
应用v-model绑定提前写好的日期对象dateObj,而后遍历对象来管制每一个日历控件的显示暗藏。
绑定对应的key值,这样就能够达到获取每一个日历对象点击之后对应的值。
解决下拉框
data外面新增dropDownObj对象,dropDownTempObj对象,dropDownMap map对象
dropDownObj:{},// 管制下拉框的显示暗藏dropDownTempObj:{},// 下拉框对象,用于picker外面的值dropDownMap:new Map(),
mounted生命周期外面新增
this.dropDownMap.set("职业",["医生","老师","司机"]);this.dropDownMap.set("城市",["北京","上海","广州","深圳"])
页面新增html内容
<van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" @click="dropDownObj[item.showName]=true"/><template v-for="(item,key,index) of dropDownObj"> <van-popup v-model="dropDownObj[key]" position="bottom" :style="{width: '100%'}"> <van-picker show-toolbar @confirm="(value)=>onConfirmDropdown(value,key)" @cancel="dropDownObj[key]=false" :columns="handleData(dropDownTempObj[key])"/> </van-popup></template>
methods新增相干办法
onConfirmDropdown(value,key){ // 下拉框选中数据 this.dropDownObj[key]=false; this.fieldObj[key]=value;},handleData(key){ // 下拉框获取每一个配置项 return this.dropDownMap.get(key);},
getFieldArray办法重写
axios.get("../../static/json/form.json").then(data=>{ let response=data.data.data; this.fieldArray=response; for(let i=0;i<response.length;i++){ let item=response[i]; if(item.htmlElements==='复选框'){ this.$set(this.fieldObj,item.showName,[]); }else if(item.htmlElements==='日历控件'){ this.$set(this.dateObj,item.showName,false); // 日历控件全副先暗藏 this.$set(this.fieldObj,item.showName,item.showValue); }else if(item.htmlElements=='下拉框'){ this.$set(this.fieldObj,item.showName,item.showValue); this.$set(this.dropDownObj,item.showName,false); // 弹出层全副先暗藏 this.$set(this.dropDownTempObj,item.showName,item.showName); }else { this.$set(this.fieldObj,item.showName,item.showValue); } }})
最终实现成果
能够看到最终所有的数据都实现了双向绑定,提交到后盾的数据就是表单外面的数据,也能够全副获取到,最初须要实现的就是表单的验证的性能。
动静表单验证
对于输入框和文本域的验证比较简单,只须要增加required和rules验证规定就能够
输入框和文本域
<van-field :required="item.requiredOrNot==1?true:false":maxlength="item.fieldLength" show-word-limit v-model="fieldObj[item.showName]" :name="item.showName" :label="item.showName" :rules="[{ required: true, message: '请填写'+item.showName }]"/>
这样一来就根本实现了输入框和文本域的验证,至于其它的form表单类型的验证笔者还在钻研当中
vant动静表单解决全副代码
html代码片段
<van-form @submit="submitClaim"> <template v-for="(item,index) of fieldArray"> <template v-if="item.htmlElements==='输入框'"> <van-field :maxlength="item.fieldLength" show-word-limit v-model="fieldObj[item.showName]" :name="item.showName" :label="item.showName"/> </template> <template v-if="item.htmlElements==='文本域'"> <van-field rows="2" autosize :label="item.showName" :name="item.showName" type="textarea" v-model="fieldObj[item.showName]" :maxlength="item.fieldLength" show-word-limit/> </template> <template v-if="item.htmlElements==='日历控件'"> <van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" @click="dateObj[item.showName]=true"/> </template> <template v-if="item.htmlElements==='复选框'"> <van-field :name="item.showName" :label="item.showName"> <template #input> <van-checkbox-group v-model="fieldObj[item.showName]" direction="horizontal"> <template v-for="(child,index) of hobbies"> <van-checkbox :name="child.value">{{child.name}}</van-checkbox> </template> </van-checkbox-group> </template> </van-field> </template> <template v-if="item.htmlElements==='单选框'"> <van-field :name="item.showName" :label="item.showName"> <template #input> <van-radio-group v-model="fieldObj[item.showName]" direction="horizontal"> <template v-for="(child,index) of sex"> <van-radio :name="child.value">{{child.name}}</van-radio> </template> </van-radio-group> </template> </van-field> </template> <template v-if="item.htmlElements==='下拉框'"> <van-field :name="item.showName" is-link :label="item.showName" :readonly="true" v-model="fieldObj[item.showName]" @click="dropDownObj[item.showName]=true"/> </template> </template> <van-button type="info" round native-type="submit" :style="{width:'100%',marginTop:'15px'}">提交</van-button></van-form><template v-for="(item,key,index) of dateObj"> <van-calendar v-model="dateObj[key]" @confirm="(date)=>onConfirmTime(date,item,key)"/></template><template v-for="(item,key,index) of dropDownObj"> <van-popup v-model="dropDownObj[key]" position="bottom" :style="{width: '100%'}"> <van-picker show-toolbar @confirm="(value)=>onConfirmDropdown(value,key)" @cancel="dropDownObj[key]=false" :columns="handleData(dropDownTempObj[key])"/> </van-popup></template>
JavaScript代码片段
import axios from 'axios'export default { name: "Test", data(){ return{ fieldArray:[],// 表单字段汇合 fieldObj:{}, sex:[{ // 性别 name:'男', value:"male" },{ name:"女", value:"female" } ], hobbies:[ // 喜好 { name:"吃饭", value:"吃饭" },{ name:"玩游戏", value:"玩游戏" },{ name:"打豆豆", value:"打豆豆" }, ], dateObj:{ // 管制日期的显示暗藏 }, dropDownObj:{ // 管制下拉框的显示暗藏 }, dropDownTempObj:{ // 下拉框对象,用于picker外面的值 }, dropDownMap:new Map(), } }, mounted(){ this.getFieldArray(); this.dropDownMap.set("职业",["医生","老师","司机"]); this.dropDownMap.set("城市",["北京","上海","广州","深圳"]) }, methods:{ getFieldArray(){ // 获取本地动静表单配置json数据 axios.get("../../static/json/form.json").then(data=>{ let response=data.data.data; this.fieldArray=response; for(let i=0;i<response.length;i++){ let item=response[i]; if(item.htmlElements==='复选框'){ this.$set(this.fieldObj,item.showName,[]); }else if(item.htmlElements==='日历控件'){ this.$set(this.dateObj,item.showName,false); // 日历控件全副先暗藏 this.$set(this.fieldObj,item.showName,item.showValue); }else if(item.htmlElements=='下拉框'){ this.$set(this.fieldObj,item.showName,item.showValue); this.$set(this.dropDownObj,item.showName,false); // 弹出层全副先暗藏 this.$set(this.dropDownTempObj,item.showName,item.showName); }else { this.$set(this.fieldObj,item.showName,item.showValue); } } }) }, onConfirmTime(date,item,key){ // 日历控件 this.fieldObj[key]=this.formatDate(date); this.dateObj[key]=false; }, onConfirmDropdown(value,key){ // 下拉框选中数据 this.dropDownObj[key]=false; this.fieldObj[key]=value; }, handleData(key){ // 下拉框获取每一个配置项 return this.dropDownMap.get(key); }, formatDate(date) { // 格式化日期 let year=date.getFullYear(); let month=date.getMonth()+1; let day=date.getDate(); if(month<10){ month='0'+month; } if(day<10){ day='0'+day; } return `${year}-${month}-${day}`; }, submitClaim(taskInfo){ console.log(taskInfo); } }}
总结
整体来说动静表单的解决综合难度不算很大,须要的是如何对数据进行解决,当然还有不足之处是没有做到对文件上传的解决,代码的优化水平没有做好,v-for外面写了很多v-if,是否能够应用独自的组件进行解决,这些都是有待须要思考的问题。
结尾
如果感觉本篇博客对您有帮忙的话,记得给作者三连,点赞,关注,珍藏,您的反对就是我写作路上最大的能源,咱们下篇文章见。