一、代码分析
1.html代码
<a-select
v-model="filevalues"
@change="fileSelectchange"
label-in-value
mode="multiple"
:options="fileoptions"
allowClear
ref="fileselect"
>
<div slot="dropdownRender" slot-scope="menu">
<v-nodes :vnodes="menu" />
<a-divider style="margin: 4px 0;" />
<div style="padding: 4px 8px; cursor: pointer;" @mousedown="e => e.preventDefault()">
<a-button type="link" style="color:#1890ff" @click="selectAll">All</a-button>
<a-button type="link" style="color:#1890ff" @click="clearAll">Clear</a-button>
</div>
</div>
</a-select>
2.添加shift按键事件
window.addEventListener('keydown', code => {
if (code.keyCode === 16 && code.shiftKey) { // 判断是否按住shift键,是就把pin赋值为true
this.pin = true
}
})
window.addEventListener('keyup', code => {
if(code.keyCode === 16){ // 判断是否松开shift键,是就把pin赋值为false
this.pin = false
}
})
3.select选择事件函数
fileSelectchange(val) {
if(this.pin){
// 获取所有数据
let data = [];
this.fileoptions.filter((item,index) => {
data.push({
key: item.value,
label: item.label,
});
});
const origin = this.origin // 起点数 从-1开始
const endIdx = val.length === 0 ? -1 : val[val.length - 1].key // 终点数
let flag = false;
val.forEach((item)=>{
if(origin !=-1 && item.key == data[origin].key){
flag=true;
}
})
if(flag) {
const sum = Math.abs(origin - endIdx) + 1 // 这里记录终点
const min = Math.min(origin, endIdx) // 这里记录起点
let i = 0
while (i < sum) {
const index = min + i
const flagIdx = this.filevalues.indexOf(data[index]) // 判断区间内的数据是否已选中
if (flagIdx === -1 && index != origin && index!= endIdx) { // 值为-1表示未选中
this.filevalues.push(data[index])
}
i++
}
this.videoform.videolist = this.filevalues.map((item) => {
return item.label;
});
this.videoform.videolist = this.videoform.videolist.join(",");
}
}else{
if(val.length > 0){
this.origin = val[0].key;
}
this.videoform.videolist = val.map((item) => {
return item.label;
});
this.videoform.videolist = this.videoform.videolist.join(",");
}
console.log(this.videoform.videolist);
}
4.全选和反选
selectAll(){
this.filevalues = [];
this.videoform.videolist = "";
this.fileoptions.forEach(item => {
this.filevalues.push({
key: item.value,
label: item.label
});
});
this.videoform.videolist = this.filevalues.map((item) => {
return item.label;
});
this.videoform.videolist = this.videoform.videolist.join(",");
},
clearAll(){
this.filevalues = [];
this.videoform.videolist = "";
}
5.按键优化(可选)
keydown在键盘按下后会不断触发,为了减少消耗,可以加上防抖函数,设置每间隔一段时间才触发事件。
a.防抖函数
/**
* 防抖函数
* @param func 用户传入的防抖函数
* @param wait 等待的时间
* @param immediate 是否立即执行
*/
export const debounce = function(func, wait = 50, immediate = false) {
// 缓存一个定时器id
let timer = null
let result
const debounced = function(...args) {
// 如果已经设定过定时器了就清空上一次的定时器
if (timer) {
clearTimeout(timer)
}
if (immediate) {
const callNow = !timer
// 等待wait的时间间隔后,timer为null的时候,函数才可以继续执行
timer = setTimeout(() => {
timer = null
}, wait)
// 未执行过,执行
if (callNow) result = func.apply(this, args)
} else {
// 开始一个定时器,延迟执行用户传入的方法
timer = setTimeout(() => {
// 将实际的this和参数传入用户实际调用的函数
func.apply(this, args)
}, wait)
}
return result
}
debounced.cancel = function() {
clearTimeout(timer)
timer = null
}
// 这里返回的函数时每次用户实际调用的防抖函数
return debounced
}
b.引用
import { debounce } from '@/common/debounce' // 引入防抖函数
// 在methods中
// 监听按下键盘事件
handleKeyDown: debounce(function(code) {
if (code.keyCode === 16 && code.shiftKey) { // 判断是否按住shift键,是就把pin赋值为true
this.pin = true
}
}, 500, true),
handleKeyUp: debounce(function(code) {
if (code.keyCode === 16) { // 判断是否松开shift键,是就把pin赋值为false
this.pin = false
}
}, 500, true)
// 在mounted中
mounted() {
window.addEventListener('keydown', code => this.handleKeyDown(code)) // 监听键盘按下事件
window.addEventListener('keyup', code => this.handleKeyUp(code)) // 监听键盘松开事件
},
// 在beforeDestroy中
beforeDestroy() {
// 销毁监听键盘事件
window.removeEventListener('keydown', code => this.handleKeyDown(code))
window.removeEventListener('keyup', code => this.handleKeyUp(code))
}