一.表格(el-table)。
1. 多个table的数据互串、混淆。
-
说明:同一组件上存在多个table进行tabs和v-if/v-show切换时,多表格的数据会相互混淆,串在一起,引发bug。
-
解决办法:为每个table指定对应且唯一的key属性。
-
核心代码:
<div class="crud__table" v-if="receiverType!=3">
<el-table ref="table"
key="table"
header-row-class-name="crud-table-header"
cell-class-name="crud-table-cell"
row-key="id"
border
stripe
highlight-current-row
height="100%"
style="min-height:405px"
v-loading="loading"
:data="tableData"
>
<el-table-column type="selection" width="45" v-if="receiverType==1"/>
<el-table-column type="index" fixed :index="indexMethod" label="序号" width="50" align='center'/>
<el-table-column label="名称" prop="name" show-overflow-tooltip
:render-header="setTableColumnWidth"/>
<el-table-column label="邮箱" prop="email" :render-header="setTableColumnWidth"/>
<el-table-column label="手机" prop="phoneNo" :render-header="setTableColumnWidth"/>
<el-table-column label="状态" prop="userStateName" :render-header="setTableColumnWidth"/>
</el-table>
</div>
<div class="crud__table" v-if="receiverType==3">
<el-table ref="groupTable"
key="groupTable"
header-row-class-name="crud-table-header"
cell-class-name="crud-table-cell"
border
stripe
highlight-current-row
height="100%"
:max-height="tabelHeight"
style="min-height:405px"
v-loading="loading"
:data="groupTableData">
<el-table-column type="selection" width="45"/>
<el-table-column type="index" fixed :index="indexMethod" label="序号" width="50" align='center'/>
<el-table-column label="名称" prop="name" show-overflow-tooltip :render-header="setTableColumnWidth"/>
<el-table-column label="创建时间" prop="createTime" :render-header="setTableColumnWidth"/>
<el-table-column label="操作" width="290">
<template slot-scope="{row}">
<el-button type="text" @click="openUser(row)">查看用户</el-button>
</template>
</el-table-column>
</el-table>
</div>
- 实例:图一为未加key的效果;图二为加了唯一key的效果。
2.为table的每一行的操作按钮设置独立的loading状态。
-
说明:table的操作栏的操作按钮(比如:授权、删除等)是请求接口联动的时候,为每一行的操作添加上相对独立的loading状态是非常有用户体验感和人性化的设计。
-
解决办法:在接口拉取表格数据赋值后,为表格数据的每一项通过this.$set(item, 'xxLoading', false); 设置各自的loading状态控制。
-
核心代码:
html:
<el-table-column label="操作" width="100">
<template slot-scope="{ row }">
<el-button
v-if="row.status !== 1"
v-loading="row.disposeLoading"
type="primary"
size="small"
@click="dispose(row)"
>处理</el-button
>
</template>
</el-table-column>
js:
//获取列表数据
getList(currentPage = this.currentPage) {
let data = new URLSearchParams();
for (let k in this.search) {
if (this.search[k]) {
data.append(k, this.search[k]);
}
}
}
data.append("current", currentPage);
data.append("size", this.pageSize);
this.loading = true;
API.getList(data)
.then((res) => {
this.loading = false;
if (res.code == 200) {
this.tableData = res.data;
this.total = res.total;
this.currentPage = currentPage;
if(this.tableData && this.tableData.length > 0){
this.tableData.map(i => {
this.$set(i,'disposeLoading',false)
})
}
}
})
.catch((err) => {
this.loading = false;
});
},
//处理
dispose(row) {
let data = new URLSearchParams();
data.append("sn", row.sn);
row.disposeLoading = true;
API.refreshPay(data)
.then((res) => {
row.disposeLoading = false;
if (res.code == 200) {
this.$message({
message: "处理成功!",
type: "success",
showClose: true,
});
this.getList();
} else {
this.getList();
}
})
.catch((err) => {
row.disposeLoading = false;
this.getList();
});
},
- 实例:效果图仅供参考,非代码案例。
3.table表格多选结合分页实现已选中行的记忆功能和实现表格数据和已选数据动态同步更新。
-
说明:el-table在实际业务开发场景中经常会有已选行在翻页前后还保持记忆功能的需求。以下就本需求提供一种解决思路和方法。
-
解决办法:借助element组件的table表格的selection-change方法结合分页组件,自行定义一个用于存储当前页的已勾选数据,一个用于存储所勾选的所有数据(也就是右侧展示已勾选数据),及一个标志位来实现。
-
核心代码及讲解链接:传送门
4.自定义table表格。
-
说明: 要自定义的列表表格展示有将近20个字段(包含操作栏:编辑,查看等功能),每个登录用户对每个表头字段前后排版(列表表头的排序,而非单独一列的行排序)和是否显隐对应字段的列、每个字段的列框、是否有排序功能、是否需转换码值等都是不一样的。还有就是这个自定义列表要和用户关联(当然这是后端童靴的事情)。
-
解决办法:通过以上的需求分析,那么很容易想到实现该需求的重点就是 ---- 动态。那么怎么理解这个动态呢,无疑就是以下两部分。
1.用于实际展示列表的部分 ---- 动态获取已经排好序(列表头排序)和筛选好(是否显示)的表头数据(也就是每个el-table-column的渲染数据),拿到这个数据后通过v-for遍历,之后针对每个el-table-column做每种专门的处理(列宽、是否开启列内行排序、是否转码值等)即可。
2.用于设置动态展示的核心功能部分 ---- 拿到列表的所有字段(列表头)的对应字段(上文1中的el-table-column中对应的prop和label),并根据实际需求情况,同后端童靴商量好列宽、是否展示等字段组成的对象数组。后可以自定义勾选每个展示字段是够显隐和填写每个展示字段的列宽值等操作,字段自定义排序等。最后保存操作后将排好序(列表头排序)和筛选好(是否显示)的对象数组数据传递给后端童靴,保存接口成功后要通知上文1中的展示列表组件去同步更新展示字段和对应排序等信息(友情提示:这里很重要的是,最好把这部分自定义列表功能的核心部分封装成公用组件,用于给上文1中的列表展示组件通讯,1作为父组件,2作为子组件。 )
核心代码及讲解链接:传送门
二.输入框(el-input)。
1.el-input的change、input事件中传递额外参数的实现。
-
说明:el-input的change、input事件都是默认传递了一个参数 -- (value: string | number)。但是很多业务场景,我们都是需要在change、input事件中传递自己定义的额外参数。
-
解决办法:在change、input原有事件中多加一层箭头函数传参即可实现 ---- @change="((val)=>{changeStatus(val, xxx)})"。 (其中,xxx即为所传的自定义参数)。
-
核心代码:
<template>
<div class="about">
<h1>input测试</h1>
<el-input
style="width: 300px; margin-top: 50px"
v-model="value"
clearable
placeholder="请输入内容"
@change="val => changeVal(val,'params')"
></el-input>
</div>
</template>
<script>
export default {
name: "About",
data() {
return {
value: "",
};
},
methods: {
changeVal(val,params){
console.log(val,params);
}
},
};
</script>
- 实例:图一为默认效果;图二为加了一层箭头函数的效果。
三.选择器(el-select)。
1.el-select的change事件中传递额外参数的实现。
-
说明:el-select的change事件都是默认传递了一个参数 -- (目前的选中值)。但是很多业务场景,我们都是需要在change事件中传递自己定义的额外参数。
-
解决办法:在change原有事件中多加一层箭头函数传参即可实现 ---- @change="((val)=>{changeStatus(val, xxx)})"。 (其中,xxx即为所传的自定义参数)。
2.el-select组件的选择项options数据量过大导致页面卡顿时的处理方法。
-
说明:el-table组件在实际开发中,其内的options选项多为后端接口提供,此时若是数据量庞大(譬如:上万条),那么在用户点开el-select选择器时,会异常卡顿,用户体验感巨差。以下就本需求提供一种解决思路和方法。
-
解决办法:从总options中取出固定条目的小option(renderOption)用于页面渲染,利用el-select提供的 filter-method方法进行搜索过滤,在搜索时用过滤结果更新renderOption。
-
核心代码及讲解链接:传送门
3.el-select组件实现既可输入(留存)任意值进行模糊检索也可选中匹配的具名选项进行精确检索。
-
说明:实际开发中会遇到类似input输入框和select选择器“相结合”的使用情形 ---- 也就是既要实现可输入任意值进行模糊搜索也要实现可选中具名选项进行精确检索。
-
解决办法:在el-select组件的基础上加上对应的blur事件,并在该事件中将target上的value值赋值给select选择器的绑定值,最后将对应的值给接口查询即可。
-
核心代码及讲解链接:传送门
四.日期选择器(el-date-picker)。
1.禁用当前日期之前的日期(只能选择今日到今日之后)。
-
解决:利用el-date-picker的picker-options属性筛选日期。
-
核心代码:
<el-date-picker
type="date"
placeholder="请选择时间"
:picker-options="pickerOptions"
v-model="ruleForm.date"
:clearable="false"
></el-date-picker>
pickerOptions: {
// 限制预约时间
disabledDate(time) {
return time.getTime() < Date.now() - 24 * 60 * 60 * 1000
}
},
2.只能选择今日到未来某时间段的日期范围(此处以3个月90天为例)。
-
解决:利用el-date-picker的picker-options属性筛选日期。
-
核心代码:
<el-date-picker
type="date"
v-model="ruleForm.date2"
:picker-options="pickerOptions2"
placeholder="请选择完成日期"
:clearable="false"
></el-date-picker>
pickerOptions2: {
// 限制预约时间
disabledDate(time) {
return (time.getTime() < Date.now() - 24 * 60 * 60 * 1000) || (time.getTime() > Date.now() + 90 * 24 * 60 * 60 * 1000)
}
},
五.表单(el-from)。
1.处理el-from组件在v-if、v-show和自增、自减表单项的时候,会出现表单校验异常或者串项的异常。
-
说明:这里以动态表单为例,处理表单校验异常的情况。
-
解决办法:为每个el-form-item指定对应且唯一的key属性。
-
核心代码:
html:
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="120px"
v-loading="loading"
class="g-form-drawer-main"
>
<template v-for="(item, index) in ruleForm.itemList">
<el-form-item
label="运营商:"
:prop="'itemList.' + index + '.carrier'"
:key="item.key"
:rules="{
required: true,
message: '请选择运营商',
trigger: ['blur', 'change'],
}"
>
<div class="p-form-content">
<el-select
class="w-300 umar-r10"
v-model="item.carrier"
placeholder="请选择运营商"
filterable
clearable
>
<el-option
v-for="i in comList"
:key="i.value"
:label="i.label"
:value="i.value"
>
</el-option>
</el-select>
</div>
</el-form-item>
<el-form-item
label="计划套餐:"
:prop="'itemList.' + index + '.packageId'"
:key="item.key"
:rules="{
required: true,
message: '请选择计划套餐',
trigger: ['blur', 'change'],
}"
>
<div class="p-form-content">
<el-select
class="w-300 umar-r10"
v-model="item.packageId"
placeholder="请先选择运营商后再选择计划套餐"
filterable
clearable
>
<el-option
v-for="i in item.packageList"
:key="i.packageId"
:label="i.name"
:value="i.packageId"
>
</el-option>
</el-select>
</div>
</el-form-item>
<div class="p-form-content bottom-box">
<el-input
type="textarea"
style="width: 300px"
v-model="item.scene"
placeholder="请输入业务类型"
></el-input>
<el-button
v-show="index === 0"
class="p-el-button addbtn"
type="success"
icon="el-icon-plus"
circle
@click="addProcess"
></el-button>
<el-button
v-show="ruleForm.itemList && ruleForm.itemList.length > 1"
class="p-el-button delbtn"
type="danger"
icon="el-icon-delete"
circle
@click="delProcess(index)"
></el-button>
</div>
</template>
</el-form>
js:
data() {
return {
ruleForm: {
itemList: [
{
carrier: "",
packageId: "",
packageList: [],
key: Date.now() //确保唯一性
},
],
},
comList: [],
rules: {},
};
},
methods: {
//新增
addProcess() {
const process = {
carrier: "",
packageId: "",
packageList: [],
key: Date.now() //确保唯一性
};
this.ruleForm.itemList.unshift(process);
},
//删除
delProcess(index) {
if (this.ruleForm.itemList && this.ruleForm.itemList.length > 1) {
this.ruleForm.itemList.splice(index, 1);
} else {
this.$message({
message: "至少需保留一个",
type: "error",
showClose: true,
});
}
},
- 实例:图一为未加key值时的效果(校验失常);图二为加了唯一key的效果(正常)。
- 体会:el-form动态表单,官方的案例是给每一项el-form-item绑定了key值(:key="domain.key"),不过这里有个问题就是domain对象下的key如果是不存在或者是不唯一的,那么就容易造成动态表单各种翻车,所以解决办法就是改写其中的key绑定的值,必须是要存在且唯一性的。
六.分页(el-pagination)。
1.纯前端分页的实现。
-
说明:后台不处理分页,只会在请求的时候一下将所有数据一起返回,这时候就需要前端同学自己处理分页了,这里简述为纯前端分页。
-
解决办法:前端发送请求拿到所有数据 → 对该数据进行处理 → 操作分页组件完成效果。
-
核心代码及讲解链接:传送门