口腔医院网站源码,网站建设与维护里面的个人简历,wordpress程序代码优化,ip地址域名解析前言
element-plus表格提供了多选功能#xff0c;可单击勾选一条数据#xff0c;可全选。 现在有个很合理的需求#xff0c;希望实现类似于文件系统中shift连续选择功能#xff0c;并且在表格排序后#xff0c;依照排序后的顺序连选。 一、el-table 多选表格基本使用
1、…前言
element-plus表格提供了多选功能可单击勾选一条数据可全选。 现在有个很合理的需求希望实现类似于文件系统中shift连续选择功能并且在表格排序后依照排序后的顺序连选。 一、el-table 多选表格基本使用
1、el-table 相关事件、方法
插入多选项
el-table-column typeselection /
表格事件
事件名说明回调参数select当用户手动勾选数据行的 Checkbox 时触发的事件selection, rowselect-all当用户手动勾选全选 Checkbox 时触发的事件selectionselection-change当选择项发生变化时会触发该事件selection
表格方法
方法名说明参数clearSelection用于多选表格清空用户的选择-getSelectionRows返回当前选中的行toggleRowSelection用于多选表格切换某一行的选中状态 如果使用了第二个参数则可直接设置这一行选中与否row, selectedtoggleAllSelection用于多选表格切换全选和全不选-
table-column 属性
selectable: 仅对 typeselection 的列有效类型为 FunctionFunction 的返回值用来决定这一行的 CheckBox 是否可以勾选。类型function(row, index)
2、el-table 多选表格示例
templateel-table:datatableDataselection-changehandleSelectionChangeel-table-column typeselection /!-- other columns --/el-table
/template
script setup
import { ref, onMounted } from vue
import { getTableData } from /api/demo.jsconst tableData ref([])
const selectedRows ref([])onMounted(() {getData()
})const getData () {getTableData().then(res {tableData.value res.data ?? []})
}const handleSelectionChange (selection) {selectedRows.value selection
}
/script二、实现
由于该功能可能会应用到很多页面中最好是提供一个统一的公共方法在页面中引入使用
1、分析
基本过程 记录上一次点击的数据记录 shift 状态 组件挂载后监听 shift 键的 keydown, keyup 事件更新 shift 状态组件销毁前取消相关监听 监听 el-tableselect 事件对比上一次点击与本次点击计算待连选数据列表后使用 toggleRowSelection 方法进行连续勾选
2、实现
根据分析初步创建方法 注意: 为了方便理解思路下面的示例中仅包含关键代码完整代码在最后
el-table-multi-select.js:
import { ref, readonly, watch, onMounted, onBeforeUnmount } from vueexport function elTableMultiSelect(tableEl) {// 表格数据const tableData ref([])// 选中数据列表const selectedRows ref([])// 下标记录const lastIdx ref(-1)// shift标识const shiftFlag ref(false)onMounted(() {// el-table 表格排序不会体现在绑定的数据列表上// 监听 el-table 组件内部状态存储中的表格数据(避免表格排序后连选不连续的bug)watch(tableEl.store?.states?.data, (newVal) {tableData.value newVal.map((item,idx) {item.index idxreturn item})}, { immediate: true })// Shift监听/取消监听document.addEventListener(keydown, handleKeyDown)document.addEventListener(keyup, handleKeyUp)})// 取消Shift监听onBeforeUnmount(() {document.removeEventListener(keydown, handleKeyDown)document.removeEventListener(keyup, handleKeyUp)})// Shift事件处理function handleKeyDown({ key }) {if(key ! Shift) returnif(shiftFlag.value) returnshiftFlag.value true}function handleKeyUp({ key }) {if(key ! Shift) returnif(!shiftFlag.value) returnshiftFlag.value falselastIdx.value -1}// el-tableselectfunction handleTbSelect(selection, row) {updateSelection(selection)// 若未按 shift更新 lastIdxif(!shiftFlag.value) {if(selection.find(r r.index row.index)) lastIdx.value row.indexreturn}// 若 lastIdx 无有效值记录本次下标if(lastIdx.value -1) {lastIdx.value row.indexreturn}// 若 lastIdx 有值自动勾选中间rowslet [start, end] [lastIdx.value, row.index]if(start end) [start, end] [end, start]// TODO: toggleRowSelection// ...}// el-tableselection-changefunction handleTbSelectionChange(selection) {updateSelection(selection)}// 更新 selectedRowsfunction updateSelection(selection) {selectedRows.value selection}return {selectedRows: readonly(selectedRows),handleTbSelect,handleTbSelectionChange}
}组件中引入使用 demo.vue:
templateel-table:datatableDataselecthandleTbSelectselection-changehandleTbSelectionChangerefdemoTableel-table-column typeselection /!-- other columns --/el-table
/template
script setup
import { ref, onMounted } from vue
import { getTableData } from /api/demo.js
import { elTableMultiSelect } from /use/el-table-multi-selectconst demoTable ref()
const tableData ref([])
// const selectedRows ref([]) // 从公共方法中导出const {selectedRows,handleTbSelect,handleTbSelectionChange
} elTableMultiSelect(demoTable)onMounted(() {getData()
})const getData () {getTableData().then(res {tableData.value res.data ?? []})
}// 从公共方法中导出
// const handleSelectionChange (selection) {
// selectedRows.value selection
// }3、小结
注意在下面的完整代码中本人监听了 el-table 组件内部状态存储信息tableEl.store.states.data未公布在官网。随着版本的更新有失效的风险。建议锁定 element-plus 版本号或者确定所使用的版本仍有效。
不监听表格绑定的数据本身是因为el-table排序后不会体现在绑定的数据上也就是说排序后连选功能还是按照排序前的顺序来进行连选的。
三、代码与演示
在线演示
工具方法完整代码
import { ref, readonly, watch, onMounted, onBeforeUnmount, nextTick } from vue/*** 工具类: el-table 可多选表格增加shift连选功能* * param {string|Element} tableRef 选项式API中传表格ref字符串setup中传表格对象* param {Function} [checkRowSelectable] 禁选方法(可选)对应el-table-column selectable属性值* returns {Object} {* selectedRows: 多选结果列表,* handleTbSelect: el-tableselect,* handleTbSelectionChange: el-tableselection-change,* clearSelection: 清空多选结果列表* }* example* // 一、引入* * import { elTableMultiSelect } from /use/el-table-multi-select* * // 二、template* * // el-table 相关属性方法* selecthandleTbSelect* selection-changehandleTbSelectionChange* refmultiSelectTable* * // 三、方法调用* * ------------------------1、选项式API------------------------* * // data() 相关变量声明:* selectedRows: [],* handleTbSelect: undefined,* handleTbSelectionChange: undefined* * // created() 中解构赋值:* ;({* selectedRows: this.selectedRows,* handleTbSelect: this.handleTbSelect,* handleTbSelectionChange: this.handleTbSelectionChange* } elTableMultiSelect.call(this, multiSelectTable, this.enableSelection)) // 传表格ref字符串* // methods:* enableSelection(row, rowIndex) {* return !row.suspected_detection_seq* }* * ------------------------2、组合式API------------------------* * const multiSelectTable ref()* const {* selectedRows, handleTbSelect, handleTbSelectionChange* } elTableMultiSelect(multiSelectTable, enableSelection) // 传表格ref对象* * function enableSelection(row, rowIndex) {* return !row.suspected_detection_seq* }*/
export function elTableMultiSelect(tableRef, checkRowSelectable) {// 表格数据const tableData ref([])// 选中数据列表const selectedRows ref([])// 下标记录const lastIdx ref(-1)// shift标识const shiftFlag ref(false)let tableEl // 表格对象const tbFlag ref(false) // 标识:表格挂载完毕const mountedFlag ref(false) // 标识:组件挂载完毕const isSetup typeof(tableRef) ! stringisSetup watch(tableRef, (newVal) {if(newVal) {tableEl newValtbFlag.value true}}, { deep: true, immediate: true })onMounted(() {mountedFlag.value trueif(!isSetup) {tbFlag.value truetableEl this.$refs[tableRef]}// Shift监听/取消监听document.addEventListener(keydown, handleKeyDown)document.addEventListener(keyup, handleKeyUp)})// 取消Shift监听onBeforeUnmount(() {document.removeEventListener(keydown, handleKeyDown)document.removeEventListener(keyup, handleKeyUp)})// Shift事件处理function handleKeyDown({ key }) {if(key ! Shift) returnif(shiftFlag.value) returnshiftFlag.value true}function handleKeyUp({ key }) {if(key ! Shift) returnif(!shiftFlag.value) returnshiftFlag.value falselastIdx.value -1}// 表格挂载 组件挂载 后, 添加 tableData 监听事件const tbMountedWatcher watch([tbFlag, mountedFlag], ([tf, mf]) {if(tf mf) {// el-table 表格排序不会体现在绑定的数据列表上// 监听 el-table 组件内部状态存储中的表格数据(避免表格排序后连选不连续的bug)watch(tableEl.store?.states?.data, (newVal) {// console.log(watch el-table store, newVal.length)tableData.value newVal.map((item,idx) {item.index idxreturn item})}, { immediate: true })tbMountedWatcher() // 取消监听}})// toggleRowSelection 会触发 handleTbSelectionChange// onprogress 控制shift多选时只触发一次 handleTbSelectionChange// (handleTbSelectionChange 为同步执行方法)const onprogress ref(false)/*** 当选择项发生变化时会触发该事件* param {Array} selection selected rows*/function handleTbSelectionChange(selection) {if(!onprogress.value) updateTbSelection(selection)}/*** 当用户手动勾选数据行的 Checkbox 时触发的事件* param {Array} selection selected rows* param {Object} row table row data* returns */function handleTbSelect(selection, row) {updateTbSelection(selection)if(!shiftFlag.value) {if(selection.find(r r.index row.index)) lastIdx.value row.indexreturn}// lastIdx为-1时记录本次下标if(lastIdx.value -1) {lastIdx.value row.indexreturn}// lastIdx 有值自动勾选中间rowslet [start, end] [lastIdx.value, row.index]if(start end) [start, end] [end, start]nextTick(() {const temp []for(let i start; i end; i) {const tmp tableData.value[i]if(selectedRows.value.find(r r.index tmp.index)) continueif(!checkRowSelectable1(tmp)) continuetemp.push(tmp)}onprogress.value truefor(let i 0, len temp.length; i len; i) {if(i len - 1) onprogress.value falsetableEl.toggleRowSelection(temp[i], true)}})}// 更新 selectedRowsfunction updateTbSelection(selection) {selectedRows.value selection}// 清空 selectedRowsfunction clearSelection() {selectedRows.value []}function checkRowSelectable1(row, rowIndex) {return typeof(checkRowSelectable) function? checkRowSelectable(row, rowIndex): true}return {selectedRows: readonly(selectedRows),handleTbSelect,handleTbSelectionChange,clearSelection}
}