前序
在后台管理的的系统中,条件的筛选框是少不了的。一开始我以为每个筛选框把UI框架的代码复制过来,然后改下变量就可以的。事实证明,我太无知了,这筛选框也是有一点点要动动脑子的东西。
做这个筛选框的目的
- 这个后台管理之前使用Bootstrap和JQ做的,所以这全部换掉,改为用vue的数据绑定特性,来减少DOM的。
- 之前的版本很多重复的代码没有提取出来做成模块,所以这版本提取组件,进行代码复用。
- 之前版本每次查询或者重新筛选时候,有很多数据需要重置或改变,所以这解决数据管理复杂,维护困难的问题。
理想的效果
- 每选择一个值后,都自己存在Vuex中,不用自己去取值。
- 选择Tab的时候,会自己带有上面筛选框的值去查数据。
- 点击分页时候,会自己带Tab的数据和筛选框的值去查数据。
- 点击查询的时候,数据不变。
分析确定需求
- 其实有些筛选框之间是有关联的,操作后会有哪些值得变换和一些筛选看得触发条件。例如: 上图的省份和市是有关系的,要选了省份才能选区,并且选了省份,区的值要重置。
- 选择完一个值后,要触发下一个筛选框去请求接口,这个主要通过watch来监听。
技术栈
- Vuex:筛选框和Tab的值都存在一个State里面,统一管理状态
- elelmentUI:封装Select组件,统一每次选择后都存在Vuex里面,这组件只适用于筛选框。
代码
Select组件的封装
<el-form-item label="" :ref="fromKey" :prop="fromKey" :key="ramdonkey" :style="'margin-bottom: 5px;width:' + width">
<el-select v-model="value" :placeholder="text" :multiple="multiple" clearable @clear="clearValue" :key="ramdonkey">
<el-option v-for="(item,index) in list" :key="index" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
watch: {
value(n){
let payload = {
setVuex: {}, //设置当前的vuex
setRef: Object.assign({}, this.resetKey), // 设置后面子的value
}
payload.setVuex[this.fromKey] = n;
this.$emit('selectCallBack', payload)
},
},
selectCallBack(payload){
for(let parentRef in payload.setRef){
let childRef = payload.setRef[parentRef];
this.$refs[parentRef].setValue(); // 重置值
this.$refs[parentRef].$refs[childRef].resetField(); // ele框架的重置值函数
let params = {};
params[childRef] = '';
this.SET_SEARCHDATA(params);
}
if(payload.setVuex.type && Object.prototype.toString.call(payload.setVuex.type) === '[object Array]'){
payload.setVuex.type = payload.setVuex.type.join(',');
}
this.SET_SEARCHDATA(payload.setVuex);
},
代码说明
- 第一和第二个代码主要是子组件数据的回调,和对数据的组装,这里主要resetKey这变量:这变量的作用是满足需求1的改变一个值,要重置另外的值。形式:{parentRefKey: childRefKey}
- 第三个代码主要用于设置Vuex和重置值。setValue()函数是重置值
遇到的困难
- 例如有一个筛选框在切换Tab时候是要进行单多选来切换的。但是当我单选切换到多选时候,多选的下拉框不显示。这就是Vue的典型的想同组件不重复渲染问题
解决办法:给组件加随机key。
收获感受
- 重构这个这组件给我感觉我写的代码太少了,这次重构写了两遍,因为第一遍没想好,没有确定好需求,乱写。
- 会思考怎做比较好,对比框架对这系统的好不好用
- 熟悉了element和ivant框架