引言
????????在前文中,我們?cè)钊胩接懥嗽谛薷臄?shù)據(jù)后跨頁(yè)時(shí)提醒用戶可能丟失數(shù)據(jù)的問(wèn)題。雖然這種方式對(duì)于一些場(chǎng)景是足夠的,但當(dāng)涉及選擇框時(shí),我們需要更為智能和高效的解決方案。在本文中,我們將分享一種基于 Element UI 的實(shí)際案例,旨在實(shí)現(xiàn)跨頁(yè)保存選中項(xiàng)與禁選特定項(xiàng)的需求。通過(guò)以下詳細(xì)討論,你將了解到這一方案的實(shí)現(xiàn)原理及其用戶體驗(yàn)效果。
問(wèn)題背景
????????在許多 Web 應(yīng)用中,數(shù)據(jù)分頁(yè)是常見的操作方式。當(dāng)用戶在一個(gè)頁(yè)面中選擇了一些數(shù)據(jù)項(xiàng),然后切換到另一頁(yè)時(shí),保持之前選中的項(xiàng)通常是用戶友好的體驗(yàn)。同時(shí),可能存在一些需要禁選的執(zhí)行項(xiàng),例如在某些狀態(tài)下,用戶不應(yīng)該選擇或執(zhí)行某些操作:如當(dāng)數(shù)據(jù)可以進(jìn)行執(zhí)行相關(guān)操作,并且需要消耗一定時(shí)間時(shí),我們?yōu)榱巳蝿?wù)的完整執(zhí)行,會(huì)在任務(wù)執(zhí)行期間,禁止選中該任務(wù)的選擇框(可以預(yù)防用戶進(jìn)行刪除等操作),后續(xù)執(zhí)行完畢可以恢復(fù)初始選中狀態(tài),也可以放棄選中狀態(tài)。
方案設(shè)計(jì)與實(shí)現(xiàn)
????????在 Element UI 中,表格(Table)組件提供了豐富的特性和事件。可以利用這些特性和事件來(lái)實(shí)現(xiàn)跨頁(yè)保存選中項(xiàng)和禁選執(zhí)行項(xiàng)的需求。
實(shí)現(xiàn)
????????1.跨頁(yè)保存
????????在許多 Web 應(yīng)用中,數(shù)據(jù)分頁(yè)是常見的操作方式。當(dāng)用戶在一個(gè)頁(yè)面中選擇了一些數(shù)據(jù)項(xiàng),然后切換到另一頁(yè)時(shí),保持之前選中的項(xiàng)通常是用戶友好的體驗(yàn)。
????????模板
<el-table
ref="multipleTable"
:data="tableData"
@select="handleSelectionChange"
@select-all="handleSelectionAll"
>
<el-table-column type="selection" align="center"></el-table-column>
<el-table-column prop="name" label="name" align="center"></el-table-column>
<el-table-column prop="age" label="age" align="center"></el-table-column>
</el-table>
<el-pagination
:background="true"
:current-page.sync="queryParams.page"
:page-size.sync="queryParams.pageSize"
layout="total,prev,pager,next,sizes"
:total="total"
:page-sizes="[5, 10, 20, 40]"
@size-change="getList"
@current-change="getList" />
????????腳本
data() {
return {
total: void 0,
queryParams: {
page: 1,
pageSize: 10,
},
allData: [],
tableData: [],
multipleSelection: [],
listId: [],
};
},
mounted() {
this.getList();
},
methods: {
getList() {
this.allData = [
{ name: 'A', age: 1 },
{ name: 'B', age: 2 },
{ name: 'C', age: 3 },
{ name: 'D', age: 4 },
{ name: 'E', age: 5 },
{ name: 'F', age: 6 },
{ name: 'G', age: 7 },
{ name: 'H', age: 8 },
{ name: 'I', age: 9 },
{ name: 'J', age: 10 },
{ name: 'K', age: 11 },
{ name: 'L', age: 12 },
{ name: 'M', age: 13 },
{ name: 'N', age: 14 },
{ name: 'O', age: 15 },
{ name: 'P', age: 16 },
{ name: 'Q', age: 17 },
{ name: 'R', age: 18 },
{ name: 'S', age: 19 },
{ name: 'T', age: 20 },
{ name: 'U', age: 21 },
{ name: 'V', age: 22 },
{ name: 'W', age: 23 },
{ name: 'X', age: 24 },
{ name: 'Y', age: 25 },
{ name: 'Z', age: 26 },
];
this.total = this.allData.length;
let currentPageIndex = (this.queryParams.page - 1) * this.queryParams.pageSize;
let currentPageSize = this.queryParams.pageSize;
this.tableData = this.allData.slice(currentPageIndex, currentPageIndex + currentPageSize);
this.listId = [];
this.tableData.forEach(item => this.listId.push(item.name));
this.$nextTick(() => {
this.tableData.forEach((item, index) => {
if (this.multipleSelection.findIndex(v => v == item.name) >= 0) {
this.$refs.multipleTable.toggleRowSelection(this.$refs.multipleTable.data[index], true);
}
});
});
},
// 全選
handleSelectionAll(val) {
if (val.length) {
const result = [];
this.listId.forEach(id => {
if (this.multipleSelection.every(item => item !== id)) result.push(id);
});
this.multipleSelection.push(...result);
} else {
this.listId.forEach(id => {
this.multipleSelection = this.multipleSelection.filter(item => item !== id);
});
}
},
// 單選
handleSelectionChange(rows, row) {
if (this.multipleSelection.find(item => item === row.name)) this.multipleSelection = this.multipleSelection.filter(item => item != row.name); // 過(guò)濾(刪除)
else this.multipleSelection.push(row.name);
},
}
? ? ? ? 解析
getList
方法:
- 發(fā)送 HTTP GET 請(qǐng)求,獲取數(shù)據(jù)(
/.../
是請(qǐng)求的地址,queryParams
是請(qǐng)求參數(shù))。- 在請(qǐng)求成功的回調(diào)中,判斷返回?cái)?shù)據(jù)的狀態(tài)是否為200,如果是,將返回的數(shù)據(jù)賦值給?
tableData
。- 構(gòu)建?
listId
?數(shù)組,存儲(chǔ)?tableData
?中每一項(xiàng)的?id
。- 利用?
$nextTick
,確保在 Vue 更新 DOM 后執(zhí)行,遍歷?tableData
,對(duì)于已經(jīng)在?multipleSelection
?中的項(xiàng),在表格中選中對(duì)應(yīng)的行。
handleSelectionAll
方法:
- 接受一個(gè)參數(shù)?
val
,即當(dāng)前頁(yè)選中的所有行數(shù)據(jù)。- 如果?
val.length
?大于 0,表示當(dāng)前頁(yè)有選中的行,遍歷?listId
,將不在?multipleSelection
?中的項(xiàng)添加到?multipleSelection
?中。- 如果?
val.length
?為 0,表示當(dāng)前頁(yè)沒有選中的行,遍歷?listId
,將在?multipleSelection
?中的項(xiàng)從中移除。
handleSelectionChange
方法:
- 接受兩個(gè)參數(shù),
rows
?是當(dāng)前頁(yè)選中的所有行數(shù)據(jù),row
?是當(dāng)前操作的行數(shù)據(jù)。- 如果?
multipleSelection
?中已經(jīng)存在?row.id
,則將其從?multipleSelection
?中移除,否則將其添加到?multipleSelection
?中。
????????這些方法共同實(shí)現(xiàn)了跨頁(yè)保存選中狀態(tài)的功能,通過(guò)維護(hù) multipleSelection
數(shù)組來(lái)保存用戶選擇的行的 id
,從而在表格分頁(yè)切換時(shí)保持選中狀態(tài)。
????????2.禁選執(zhí)行項(xiàng)
????????數(shù)據(jù)擁有執(zhí)行狀態(tài)之類的字段,并且需要消耗一定時(shí)間時(shí),我們?yōu)榱巳蝿?wù)的完整執(zhí)行,會(huì)在任務(wù)執(zhí)行期間,禁止選中該任務(wù)的選擇框(以避免刪除等操作)。執(zhí)行完畢后可以恢復(fù)初始選中狀態(tài),也可以放棄選中狀態(tài)。
? ? ? ? ?以下代碼選擇的是后者,即在重新開始運(yùn)行時(shí),禁用該項(xiàng)選擇框并且執(zhí)行完畢后不重新選中。如果希望保留,在對(duì)應(yīng)執(zhí)行的函數(shù)(下述為 reloadTask
)中不刪除 multipleSelection
中對(duì)應(yīng)的id即可。
? ? ? ? 模板
<el-table
ref="multipleTable"
:data="tableData"
@select="handleSelectionChange"
@select-all="handleSelectionAll"
>
<el-table-column type="selection" align="center" :selectable="selectable"></el-table-column>
<el-table-column prop="name" label="name" align="center"></el-table-column>
<el-table-column prop="age" label="age" align="center"></el-table-column>
<el-table-column label="status">
<template slot-scope="scope">
<span
style="margin-right:10px; cursor: pointer;"
:class="scope.row.status !== '執(zhí)行中' ? 'el-icon-caret-right' : 'el-icon-loading'"
size="small"
:disabled="scope.row.status === '執(zhí)行中'"
@click="reloadTask(scope.row)"></span>
<el-tag :type="scope.row.status !== '執(zhí)行中' ? '' : 'info'">{{scope.row.status}}</el-tag>
</template>
</el-table-column>
</el-table>
<el-pagination
:background="true"
:current-page.sync="queryParams.page"
:page-size.sync="queryParams.pageSize"
layout="total,prev,pager,next,sizes"
:total="total"
:page-sizes="[5, 10, 20, 40]"
@size-change="getList"
@current-change="getList" />
? ? ? ? 腳本
data() {
return {
total: void 0,
queryParams: {
page: 1,
pageSize: 10,
},
allData: [],
tableData: [],
multipleSelection: [],
listId: [],
loadingSelection: new Set(),
};
},
mounted() {
this.getList();
},
methods: {
getList(flag = false) {
if (!flag) {
this.allData = [
{ name: 'A', age: 1, status: '執(zhí)行完畢' },
{ name: 'B', age: 2, status: '執(zhí)行中' },
{ name: 'C', age: 3, status: '執(zhí)行完畢' },
{ name: 'D', age: 4, status: '未執(zhí)行' },
{ name: 'E', age: 5, status: '未執(zhí)行' },
{ name: 'F', age: 6, status: '執(zhí)行中' },
{ name: 'G', age: 7, status: '執(zhí)行中' },
{ name: 'H', age: 8, status: '執(zhí)行中' },
{ name: 'I', age: 9, status: '執(zhí)行中' },
{ name: 'J', age: 10, status: '未執(zhí)行' },
{ name: 'K', age: 11, status: '未執(zhí)行' },
{ name: 'L', age: 12, status: '未執(zhí)行' },
{ name: 'M', age: 13, status: '未執(zhí)行' },
{ name: 'N', age: 14, status: '未執(zhí)行' },
{ name: 'O', age: 15, status: '未執(zhí)行' },
{ name: 'P', age: 16, status: '未執(zhí)行' },
{ name: 'Q', age: 17, status: '未執(zhí)行' },
{ name: 'R', age: 18, status: '未執(zhí)行' },
{ name: 'S', age: 19, status: '未執(zhí)行' },
{ name: 'T', age: 20, status: '未執(zhí)行' },
{ name: 'U', age: 21, status: '未執(zhí)行' },
{ name: 'V', age: 22, status: '未執(zhí)行' },
{ name: 'W', age: 23, status: '未執(zhí)行' },
{ name: 'X', age: 24, status: '未執(zhí)行' },
{ name: 'Y', age: 25, status: '未執(zhí)行' },
{ name: 'Z', age: 26, status: '未執(zhí)行' },
];
}
this.total = this.allData.length;
let currentPageIndex = (this.queryParams.page - 1) * this.queryParams.pageSize;
let currentPageSize = this.queryParams.pageSize;
this.tableData = this.allData.slice(currentPageIndex, currentPageIndex + currentPageSize);
this.listId = [];
this.tableData.forEach(item => this.listId.push(item.name));
this.$nextTick(() => {
this.tableData.forEach((item, index) => {
if (this.multipleSelection.findIndex(v => v == item.name) >= 0) {
this.$refs.multipleTable.toggleRowSelection(this.$refs.multipleTable.data[index], true);
}
});
});
},
// 執(zhí)行任務(wù)
reloadTask(row) {
this.multipleSelection = this.multipleSelection.filter(item => item !== row.name);
row.status = '執(zhí)行中';
this.getList(true);
},
// 判斷可選性
selectable(row) {
if (row.status !== '執(zhí)行中') {
if (this.loadingSelection.has(row.name)) this.loadingSelection.delete(row.name);
return true;
} else {
this.loadingSelection.add(row.name);
return false;
}
},
// 全選
handleSelectionAll(val) {
if (val.length) {
const result = [];
this.listId.forEach(id => {
if (this.multipleSelection.every(item => item !== id) && !this.loadingSelection.has(id)) result.push(id);
});
this.multipleSelection.push(...result);
} else {
this.listId.forEach(id => {
this.multipleSelection = this.multipleSelection.filter(item => item !== id);
});
}
},
// 單選
handleSelectionChange(rows, row) {
if (this.multipleSelection.find(item => item === row.name)) this.multipleSelection = this.multipleSelection.filter(item => item != row.name); // 過(guò)濾(刪除)
else this.multipleSelection.push(row.name);
},
},
? ? ? ? ?解析
????????這部分代碼經(jīng)過(guò)修改后主要涉及到對(duì)行的可選性(selectable
方法)以及全選處理(handleSelectionAll
方法)。下面是對(duì)修改部分代碼的詳細(xì)解釋:
selectable
方法:
selectable
?方法用于確定給定行?row
?是否可選。如果行的狀態(tài)?status
?不是 '執(zhí)行中',則認(rèn)為該行可選。- 如果行不可選,而且?
loadingSelection
?集合中已經(jīng)存在該行的?id
,則將其從?loadingSelection
?中刪除,表示加載完成。- 如果行可選,將其?
id
?添加到?loadingSelection
?集合中,表示正在加載中,并返回?false
?表示不可選;否則,返回?true
?表示可選。
handleSelectionAll
方法:
- 該方法用于處理全選操作。接收參數(shù)?
val
,即當(dāng)前頁(yè)選中的所有行數(shù)據(jù)。- 如果有選中的行,遍歷?
listId
,將不在?multipleSelection
?中且不在?loadingSelection
?中的項(xiàng)添加到?multipleSelection
?中。- 如果沒有選中的行,遍歷?
listId
,將在?multipleSelection
?中的項(xiàng)從中移除。
????????這些修改主要增加了對(duì)行的可選性的判斷,以及對(duì)加載狀態(tài)的管理,通過(guò) loadingSelection
集合來(lái)標(biāo)記哪些行正在加載中。這樣可以更好地控制在某些條件下禁止選擇或在加載中時(shí)保持選擇狀態(tài)。
實(shí)現(xiàn)效果
跨頁(yè)保存
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-762902.html
禁選某些狀態(tài)
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-762902.html
到了這里,關(guān)于Element UI 實(shí)戰(zhàn):跨頁(yè)保存表格選中狀態(tài)與判斷狀態(tài)可選性的高效方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!