Vue3+ElementUI 多選框中復選框和名字點擊方法效果分離方法
Vue3+ElementUI 多選框中復選框和名字點擊方法效果分離
現在的需求為

比如我點擊了Option A ,觸發(fā)點擊Option A的方法,并且復選框不會取消勾選,分離的方法。
<el-checkbox-group v-model="mapWork.model_checkArray.value">
<div class="naipTypeDom" v-for="item in mapWork.modelList.value" :key="item.id">
<el-checkbox :label="item.id" :disabled="!mapWork.mould_layer_isShow.value">
<span @click.prevent="flyToMould(item.id)">{{ item.modelName }}</span>
</el-checkbox>
</div>
</el-checkbox-group>通過Vue事件處理的方法.prevent來阻止。<!-- 提交事件將不再重新加載頁面 -->
VUE-Element組件 CheckBox多選框
一、用法說明:
1、el-checkbox標簽內的內容,綁定點擊事件,點擊的時候會觸發(fā)選中/不選中,如果不希望事件冒泡,可以使用
event.preventDefault();
如我:
<el-checkbox-group v-model="codes">
<template v-for="(item, index) in allCodes">
<el-checkbox
:label="item.value"
:key="item.value"
@click.native="handleCheckRegion($event, item.value)"
>{{ item.value }}
<a class="detail-btn" :key="index" @click="clickToDetail($event, item.value)"
>詳情</a
>
</el-checkbox>
</template>
</el-checkbox-group>
clickToDetail(e, code) {
if (e.target.tagName !== 'A') return;
//阻止選中
e.preventDefault();
//你的邏輯
}2、在checkBox中加上按鈕:
<el-checkbox-group v-model="checkedRoleCodes" @change="handleCheckedRoleChange">
<template v-for="(role, index) in allRoles">
<el-checkbox
:label="role.value"
:key="role.value"
@click.native="handleCheckRole($event, role)"
:indeterminate="role.indeterminate"
>{{ role.text }}
<a class="detail-btn" @click="clickRoleToRegionDetail($event, role)" :key="index">詳情</a>
</el-checkbox>
</template>
</el-checkbox-group>
現在希望按鈕統(tǒng)一排列在最有側:給按鈕加上右浮動,并修改.el-checkbox__label的display屬性使按鈕的浮動生效即可:

/deep/ .el-checkbox__label {
display: inline;
padding-left: 10px;
line-height: 19px;
font-size: 14px;
}
.detail-btn {
float: right;
}二、舉例
1、例1,現有通訊錄,點擊出現通訊錄選擇彈框。彈框右側為選擇的用戶列表,可以點擊刪除,左側默認為角色列表,可以勾選角色,也可以點擊角色進入角色詳情頁勾選具體的用戶。還可以在左側上方搜索用戶名或者賬號出來用戶列表來勾選。其中,角色列表復選框、搜索用戶列表復選框、選中的用戶列表復選框,三者的選中狀態(tài)需要關聯(不勾選、半選、全選)。


代碼實現:
父組件:
<div class="user-div" @click="openSelectUserDialog">
<template v-for="(item, index) in formValidate.sendUers">
<span class="user-item" :title="item" :key="index">{{
item.userName + '(' + item.userAccount + ')'
}}</span></template
>
</div>
<!--彈框-->
<div>
<SelectUser
:selectUserDialogVisible="selectUserDialogVisible"
:initUers="formValidate.sendUers"
v-if="selectUserDialogVisible"
@cancelSelectUser="cancelSelectUser"
@changeSelectUser="changeSelectUser"
></SelectUser>
</div>
//選擇用戶彈框
openSelectUserDialog() {
this.selectUserDialogVisible = true;
},
//關閉用戶選擇彈框
cancelSelectUser() {
this.selectUserDialogVisible = false;
},
//選擇用戶
changeSelectUser(users) {
this.formValidate.sendUers = users;
this.cancelSelectUser();
},子組件:
<!-- @format -->
<template>
<div>
<el-dialog title="通訊錄" :visible.sync="dialogVisible" width="60%" @close="cancel">
<el-row class="user-row">
<el-col :span="12" class="department-user-col scoll-col">
<div class="header-query">
<el-input v-model="userNameOrAccount"
><i class="el-icon-search" slot="suffix" @click="queryUser"></i
></el-input>
</div>
<div class="department-user">
<!--用戶列表復選框-->
<template v-if="queryUsers && queryUsers.length > 0">
<el-checkbox
:indeterminate="userIsIndeterminate"
@change="handleCheckAllUserChange"
v-model="userCheckAll"
>全選</el-checkbox
>
<el-checkbox-group v-model="checkedUserAccounts">
<el-checkbox
v-for="user in queryUsers"
:label="user.userAccount"
:key="user.userAccount"
@click.native="clickUser($event, user)"
>{{ user.userName + '(' + user.userAccount + ')' }}</el-checkbox
>
</el-checkbox-group>
</template>
<!--角色復選框-->
<template v-else>
<el-checkbox :indeterminate="roleIsIndeterminate" @change="handleCheckAllRole" v-model="roleCheckAll"
>全選</el-checkbox
>
<el-checkbox-group v-model="checkedRoleCodes" @change="handleCheckedRoleChange">
<template v-for="(role, index) in allRoles">
<el-checkbox
:label="role.value"
:key="role.value"
@click.native="clickRole($event, role)"
:indeterminate="role.indeterminate"
>{{ role.text }}
<a class="detail-btn" @click="clickToRoleDetail($event, role)" :key="index">詳情</a>
</el-checkbox>
</template>
</el-checkbox-group>
</template>
</div>
</el-col>
<!--右側-->
<el-col :span="12" class="user-col scoll-col">
<!--選中的用戶列表-->
<div class="user-item" v-for="(user, index) in addUsers" :key="index">
{{ user.userName + '(' + user.userAccount + ')' }}
<a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="deleteAddUser(index)" class="delete-icon">X</a>
</div>
</el-col>
</el-row>
<span slot="footer" class="dialog-footer">
<el-button @click="cancel()">取 消</el-button>
<el-button type="primary" @click="ok()">確 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
props: {
selectUserDialogVisible: {},
//初始化的用戶列表
initUers: {}
},
data() {
return {
dialogVisible: false,
userNameOrAccount: '',
//本界面的用戶列表
addUsers: [],
//勾選的用戶賬號列表
checkedUserAccounts: [],
//用戶列表
queryUsers: [], //所有可以選擇的用戶
//用戶多選框
userIsIndeterminate: true,
userCheckAll: false,
//角色列表
allRoles: [], //所有可以選擇的角色
//勾選的角色code
checkedRoleCodes: [],
//角色選擇復選框
roleIsIndeterminate: true,
roleCheckAll: false
//從角色列表中選擇的用戶
};
},
created() {
this.init();
},
methods: {
init() {
this.findRoles();
this.addUsers = this.addUsers.concat(this.initUers);
this.handleCheckedValue();
this.dialogVisible = this.selectUserDialogVisible;
},
//從全量用戶中獲取勾選的賬號和角色編碼信息,去重
handleCheckedValue() {
//勾選的用戶
this.handleCheckUser();
//勾選的角色
this.handleCheckRoleCode();
},
handleCheckUser() {
let checkedUserAccounts = this.addUsers.map(function(item) {
return item.userAccount;
});
this.checkedUserAccounts = Array.from(new Set(checkedUserAccounts));
},
handleCheckRoleCode() {
let checkedRoleCodes = this.addUsers.map(function(item) {
return item.roleCode;
});
this.checkedRoleCodes = Array.from(new Set(checkedRoleCodes));
},
findRoles() {
this.$api['role/getAllRoles']({
}).then(data => {
data.forEach(item => {
item.indeterminate = false;
});
this.allRoles = data;
});
},
cancel() {
this.dialogVisible = false;
this.$emit('cancelSelectUser');
},
ok() {
this.dialogVisible = false;
//發(fā)送對象 = 初始化的用戶+用戶列表中選擇的用戶+角色列表選擇的用戶
this.$emit('changeSelectUser', this.addUsers);
},
//角色全選/全部取消,全量
handleCheckAllRole(val) {
if (val) {
//全選
this.checkedRoleCodes = this.allRoles.map(function(item) {
return item.value;
});
this.getUsersByRoles(this.checkedRoleCodes).then(users => {
this.addUsers = users;
});
this.handleCheckUser();
} else {
//取消全選
this.addUsers = [];
this.checkedUserAccounts = [];
this.checkedRoleCodes = [];
}
this.roleIsIndeterminate = false;
},
//角色復選框點擊事件
clickRole(e, role) {
// 因為原生click事件會執(zhí)行兩次,第一次在label標簽上,第二次在input標簽上,故此處理
if (e.target.tagName === 'INPUT' || e.target.tagName === 'A') return;
let roleCode = role.value;
if (this.checkedRoleCodes.indexOf(roleCode) === -1) {
//選中
this.getUsersByRoles(new Array(roleCode)).then(users => {
let addUsers = this.addUsers.concat(users);
this.addUsers = this.unique(addUsers);
});
} else {
//取消
role.indeterminate = false;
this.addUsers = this.addUsers.filter(function(item) {
return item.roleCode !== roleCode;
});
}
this.handleCheckUser();
},
//角色詳情單擊事件詳情,取A標簽的事件
clickToRoleDetail(e, role) {
if (e.target.tagName !== 'A') return;
let roleCode = role.value;
//阻止選中
// this.checkedRoleCodes = this.checkedRoleCodes.filter(item => {
// return item !== roleCode;
// });
this.getUsersByRoles(new Array(roleCode)).then(users => {
this.queryUsers = users;
let addUsers = this.addUsers.concat(users);
this.addUsers = this.unique(addUsers);
this.handleCheckUser();
});
},
//角色選擇改變
handleCheckedRoleChange(roleCodes) {
let checkedCount = roleCodes.length;
let totalCount = this.allRoles.length;
this.roleCheckAll = checkedCount === totalCount;
this.roleIsIndeterminate = checkedCount > 0 && checkedCount < totalCount;
},
async getUsersByRoles(roleCodes) {
let roleCodeStr = roleCodes.join(',');
let queryUsers = [];
await this.$api['personDetail/listPersonnelDetailByPositionTypeCodes']({
positionTypeCodeList: roleCodeStr
}).then(data => {
queryUsers = data;
});
return queryUsers;
},
//搜索用戶
queryUser() {
if (this.userNameOrAccount) {
this.$api['personDetail/listPersonnelDetailByNameOrAccount']({
nameOrAccount: this.userNameOrAccount
}).then(data => {
this.queryUsers = data;
});
} else {
this.queryUsers = [];
}
},
//用戶全選,用戶是角色的子集,故用戶新增/刪除需要做比對
handleCheckAllUserChange(val) {
if (val) {
//全選,addUsers加上queryUsers,去重
this.addUsers = this.addUsers.concat(this.queryUsers);
} else {
//全部取消,addUsers去掉所有queryUsers
let queryUserAccounts = this.queryUsers.map(function(item) {
return item.userAccount;
});
this.addUsers = this.addUsers.filter(function(item) {
return queryUserAccounts.every(function(item1) {
return item.userAccount !== item1;
});
});
}
this.addUsers = this.unique(this.addUsers);
//復選框勾選綁定值改變
this.handleCheckedValue();
this.userIsIndeterminate = false;
},
//用戶復選框點擊事件
clickUser(e, user) {
// 因為原生click事件會執(zhí)行兩次,第一次在label標簽上,第二次在input標簽上,故此處理
if (e.target.tagName === 'INPUT' || e.target.tagName === 'A') return;
let userAccount = user.userAccount;
let roleCode = user.roleCode;
if (this.checkedUserAccounts.indexOf(userAccount) === -1) {
//選中
let addUser = this.queryUsers.find(item => {
return item.userAccount === userAccount;
});
this.addUsers.push(addUser);
this.addUsers = this.unique(this.addUsers);
} else {
//取消
this.addUsers = this.addUsers.filter(function(item) {
return item.userAccount !== userAccount;
});
}
//全選狀態(tài)改變
this.userAndRoleAllCheckStatusChange();
//角色選中值變化
this.handleCheckedValue();
//角色復選框選中狀態(tài)改變
this.roleUserCheckStatusChange(roleCode);
},
//用戶、角色全選框選中狀態(tài)改變
userAndRoleAllCheckStatusChange() {
//右側用戶列表包含左側復選框用戶列表,userCheckAll為true,userIsIndeterminate為false
let userCheckAll = true;
this.queryUsers.forEach(item => {
if (this.checkedUserAccounts.indexOf(item.userAccount) < 0) {
userCheckAll = false;
return;
}
});
this.userCheckAll = userCheckAll;
this.userIsIndeterminate = !this.userCheckAll;
//角色
this.handleCheckedRoleChange(this.checkedRoleCodes);
},
//角色復選框選中狀態(tài)改變
roleUserCheckStatusChange(roleCode) {
this.allRoles.forEach(item => {
if (item.value === roleCode) {
if (this.checkedRoleCodes.indexOf(roleCode) !== -1) {
item.indeterminate = true;
} else {
item.indeterminate = false;
}
}
});
},
//去重
unique(arr) {
var obj = {};
arr = arr.reduce(function(item, next) {
obj[next.userAccount] ? '' : (obj[next.userAccount] = true && item.push(next));
return item;
}, []);
return arr;
},
//刪除本次新增的用戶
deleteAddUser(index) {
let deleteUser = this.addUsers[index];
let deleteUserAccount = deleteUser.userAccount;
let roleCode = deleteUser.roleCode;
//1、用戶復選框綁定值同步刪除
this.checkedUserAccounts = this.checkedUserAccounts.filter(function(value) {
return value !== deleteUserAccount;
});
//2、最后本次新增的用戶刪除
this.addUsers.splice(index, 1);
//3、角色復選框綁定值同步變化
this.handleCheckRoleCode();
//4、用戶全選狀態(tài)改變
this.userAndRoleAllCheckStatusChange();
//5、角色選中狀態(tài)改變,設置已選且有刪除用戶操作的角色indeterminate為true
this.roleUserCheckStatusChange(roleCode);
}
},
watch: {
queryUsers: {
handler: function(val) {
this.userAndRoleAllCheckStatusChange();
}
}
}
};
</script>
<style scoped lang="less">
.user-row {
.department-user-col {
/deep/ .el-checkbox {
color: #606266;
font-weight: 500;
font-size: 14px;
cursor: pointer;
user-select: none;
margin-right: 30px;
display: block;
}
.detail-btn {
float: right;
margin-left: 20px;
}
}
.user-col {
.user-item {
margin-left: 10px;
}
.delete-icon {
float: right;
margin-right: 20px;
}
}
//滾動條
.scoll-col {
max-height: 300px;
overflow-y: auto;
}
}
</style>已知問題:某角色先選中,然后刪除用戶,該角色變?yōu)榘脒x,如果該用戶通過搜索用戶列表的方式來單獨勾選或者全選重新加上,該角色的狀態(tài)仍為半選。因為需要全量判斷,性能較差。
2、舉例2:例1是從角色跳轉到用戶,現在再加一層關系,角色跳轉到區(qū)域(固定的省份),區(qū)域再調轉到用戶:
父組件:這里對角色、區(qū)域、區(qū)域復選框狀態(tài)做了一個緩存
<!-- @format -->
<template>
<div>
<div class="container">
<el-form ref="formValidate" :model="formValidate" :rules="ruleValidate" label-position="left" label-width="100px">
<el-form-item :required="true">
<div class="user-div" @click="openSelectUserDialog">
<template v-for="(item, index) in formValidate.receiverList">
<span class="user-item" :title="item" :key="index">{{
item.userName + '(' + item.userAccount + ')'
}}</span></template
>
</div>
</el-form-item>
</el-form>
</div>
<!--彈框-->
<div>
<SelectUser
:selectUserDialogVisible="selectUserDialogVisible"
:initUers="formValidate.receiverList"
:cacheAllRoles="cacheAllRoles"
:cacheAllRegions="cacheAllRegions"
:cacheRoleRegionIndeterminateMap="cacheRoleRegionIndeterminateMap"
v-if="selectUserDialogVisible"
@cancelSelectUser="cancelSelectUser"
@changeSelectUser="changeSelectUser"
></SelectUser>
</div>
</div>
</template>
<script>
import SelectUser from './children/select-user';
export default {
data() {
return {
// 表單數據
formValidate: {
receiverList: []
},
selectUserDialogVisible: false,
//通訊錄緩存的角色信息
cacheAllRoles: [],
//通訊錄緩存的區(qū)域信息
cacheAllRegions: [],
//通訊錄緩存的區(qū)域復選框狀態(tài)
cacheRoleRegionIndeterminateMap: {}
};
},
methods: {
//選擇用戶彈框
openSelectUserDialog() {
this.selectUserDialogVisible = true;
},
//關閉用戶選擇彈框
cancelSelectUser() {
this.selectUserDialogVisible = false;
},
//選擇用戶
changeSelectUser(users, cacheAllRoles, cacheAllRegions, cacheRoleRegionIndeterminateMap) {
this.formValidate.receiverList = users;
this.cancelSelectUser();
this.cacheAllRoles = cacheAllRoles;
this.cacheAllRegions = cacheAllRegions;
this.cacheRoleRegionIndeterminateMap = cacheRoleRegionIndeterminateMap;
}
}
},
components: {
SelectUser
}
};
</script>子組件:右側用戶采用滾動加載
<!-- @format -->
<template>
<div>
<el-dialog title="通訊錄" :visible.sync="dialogVisible" width="60%" @close="cancel">
<el-row class="user-row">
<el-col :span="12" class="role-region-user-col scoll-col">
<div class="header-query">
<el-input v-model.trim="userNameOrAccount" placeholder="輸入姓名/賬號" size="mini"
><i class="el-icon-search" slot="suffix" @click="searchUser"></i
></el-input>
</div>
<div class="role-region-user">
<!--錯誤提示-->
<template v-if="isNoDataShow">
<p class="no-data">無搜索結果</p>
</template>
<!--正常數據-->
<template v-else>
<!--用戶列表復選框-->
<template v-if="queryUsers && queryUsers.length > 0">
<el-row>
<el-col :span="20">
<el-checkbox
:indeterminate="userIsIndeterminate"
@change="handleCheckAllUser"
v-model="userCheckAll"
>全選</el-checkbox
>
<el-checkbox-group v-model="checkedUserAccounts">
<el-checkbox
v-for="user in queryUsers"
:label="user.userAccount"
:key="user.userAccount"
@click.native="handleCheckUser($event, user)"
@change="checkUserChange"
>{{ user.userName + '(' + user.userAccount + ')' }}</el-checkbox
>
</el-checkbox-group></el-col
>
<el-col :span="2" v-if="isFromClickRegion">
<a @click="goBackToRegion($event)" class="goback-to-role"
><svg
t="1628844742588"
class="icon"
viewBox="0 0 1482 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2061"
width="40"
height="40"
>
<path
d="M584.884104 272.714912V0L0 477.152657l584.884104 477.073906V674.817811c406.119203 0 690.568023 108.991464 893.588249 347.528417-81.271091-340.755826-324.926863-681.354149-893.588249-749.631316"
fill="#467CFD"
p-id="2062"
></path></svg
></a>
</el-col>
</el-row>
</template>
<!--角色復選框-->
<template v-else-if="!isRegionListShow">
<el-checkbox :indeterminate="roleIsIndeterminate" @change="handleCheckAllRole" v-model="roleCheckAll"
>全選</el-checkbox
>
<el-checkbox-group v-model="checkedRoleCodes" @change="handleCheckedRoleChange">
<template v-for="(role, index) in allRoles">
<el-checkbox
:label="role.value"
:key="role.value"
@click.native="handleCheckRole($event, role)"
:indeterminate="role.indeterminate"
>{{ role.text }}
<a class="detail-btn" @click="clickRoleToRegionDetail($event, role)" :key="index">詳情</a>
</el-checkbox>
</template>
</el-checkbox-group>
</template>
<!--區(qū)域復選框-->
<template v-else>
<el-row>
<el-col :span="20">
<el-checkbox
:indeterminate="roleRegionAllIndeterminateMap[currentClickRoleCode]"
v-model="roleRegionAllCheckMap[currentClickRoleCode]"
@change="handleCheckAllRegion"
>全選</el-checkbox
>
<el-checkbox-group v-model="checkedRoleRegionsMap[currentClickRoleCode]">
<template v-for="(item, index) in allRegions">
<el-checkbox
:label="item.value"
:key="item.value"
:indeterminate="roleRegionIndeterminateMap[currentClickRoleCode][item.value]"
@click.native="handleCheckRegion($event, item.value)"
>{{ item.value }}
<a class="detail-btn" :key="index" @click="clickRegionToUserDetail($event, item.value)"
>詳情</a
>
</el-checkbox>
</template>
</el-checkbox-group>
</el-col>
<el-col :span="2">
<a @click="goBackToRole($event)" class="goback-to-role"
><svg
t="1628844742588"
class="icon"
viewBox="0 0 1482 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2061"
width="40"
height="40"
>
<path
d="M584.884104 272.714912V0L0 477.152657l584.884104 477.073906V674.817811c406.119203 0 690.568023 108.991464 893.588249 347.528417-81.271091-340.755826-324.926863-681.354149-893.588249-749.631316"
fill="#467CFD"
p-id="2062"
></path></svg
></a>
</el-col>
</el-row>
</template>
</template>
</div>
</el-col>
<!--右側-->
<el-col :span="12" class="user-col">
<!--選中的用戶列表-->
<!-- <div class="user-item" v-for="(user, index) in addUsers" :key="index">
{{ user.userName + '(' + user.userAccount + ')' }}
<a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="deleteAddUser(index)" class="delete-icon">X</a>
</div> -->
<div class="infinite-list-wrapper" style="overflow:auto">
<template>
<p v-if="scrollUserLoading" class="load-user"><i class="el-icon-loading"></i></p>
<ul class="infinite-list" v-infinite-scroll="scrollLoadUser" style="overflow:auto;height:300px">
<li
v-for="i in scrollCount"
class="infinite-list-item"
:key="i"
infinite-scroll-disabled="userScrollDisabled"
>
<div v-if="addUsers[i - 1]">
{{ addUsers[i - 1].userName + '(' + addUsers[i - 1].userAccount + ')' }}
<a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="deleteAddUser(i - 1)" class="delete-icon">X</a>
</div>
</li>
</ul>
</template>
</div>
</el-col>
</el-row>
<span slot="footer" class="dialog-footer">
<el-button @click="cancel()">取 消</el-button>
<el-button type="primary" @click="ok()">確 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
props: {
selectUserDialogVisible: {},
//初始化的用戶列表
initUers: {},
//緩存的角色列表,包含角色的半選狀態(tài)
cacheAllRoles: {},
//緩存的區(qū)域列表
cacheAllRegions: {},
//緩存的區(qū)域復選框狀態(tài)
cacheRoleRegionIndeterminateMap: {}
},
data() {
return {
dialogVisible: false,
userNameOrAccount: '',
isNoDataShow: false,
//右側的用戶列表
addUsers: [],
//用戶列表復選框綁定值
checkedUserAccounts: [],
//左側用戶復選框列表
queryUsers: [],
//用戶復選列表全選框狀態(tài)
userIsIndeterminate: true,
userCheckAll: false,
//角色列表
allRoles: [],
//角色列表復選框綁定值
checkedRoleCodes: [],
//角色復選列表全選框狀態(tài)
roleIsIndeterminate: false,
roleCheckAll: false,
//區(qū)域列表
allRegions: [],
allRegionCodes: [],
//當前點擊的角色
currentClickRole: '',
currentClickRoleCode: '',
isRegionListShow: false,
//區(qū)域復選列表全選框狀態(tài)
roleRegionAllIndeterminateMap: {},
roleRegionAllCheckMap: {},
//區(qū)域復選框綁定值,map:string->array,如{'管理員':['上海','北京']}
checkedRoleRegionsMap: {},
//區(qū)域復選框狀態(tài),map:string->map,如{'管理員':{{'上海':true},{'北京':false}}}
roleRegionIndeterminateMap: {},
//用戶列表來自區(qū)域詳情跳轉標志
isFromClickRegion: false,
//滾動加載
scrollCount: 0,
scrollUserLoading: false
};
},
created() {
//獲取所有角色
this.findRoles().then(res => {
//獲取所有區(qū)域
this.findRegions();
//初始化數據和勾選狀態(tài)
this.init();
});
},
computed: {
scrollUserNoMore() {
return this.scrollCount >= this.addUsers.length;
},
userScrollDisabled() {
return this.scrollUserLoading || this.scrollUserNoMore;
}
},
methods: {
scrollLoadUser() {
//一次加載20條
let increaseCount = 20;
let addAllCount = this.addUsers.length;
if (this.scrollCount + increaseCount > addAllCount) {
this.scrollCount = addAllCount;
} else {
this.scrollCount += increaseCount;
}
console.info('加載數據:' + this.scrollCount);
this.scrollUserLoading = false;
},
init() {
this.dialogVisible = this.selectUserDialogVisible;
this.addUsers = this.addUsers.concat(this.initUers);
this.handleCheckedValue();
this.handleCheckedRoleChange(this.checkedRoleCodes);
this.roleRegionIndeterminateMap = this.cacheRoleRegionIndeterminateMap || {};
},
//處理用戶、角色、區(qū)域復選框綁定值和選擇狀態(tài)
handleCheckedValue() {
let checkedUserAccounts = [];
let checkedRoleCodes = [];
let checkedRoleRegionsMap = {};
this.addUsers.forEach(user => {
let userAccount = user.userAccount;
let roleCode = user.roleCode;
let regionName = user.regionName;
checkedUserAccounts.push(userAccount);
checkedRoleCodes.push(roleCode);
if (!checkedRoleRegionsMap[roleCode]) {
checkedRoleRegionsMap[roleCode] = [];
} else if (checkedRoleRegionsMap[roleCode].indexOf(regionName) === -1) {
checkedRoleRegionsMap[roleCode].push(regionName);
}
});
//用戶列表復選框勾選
this.checkedUserAccounts = Array.from(new Set(checkedUserAccounts));
//角色列表復選框勾選
this.checkedRoleCodes = Array.from(new Set(checkedRoleCodes));
//角色-區(qū)域列表復選框勾選
this.checkedRoleRegionsMap = checkedRoleRegionsMap;
},
handleCheckedUser() {
let checkedUserAccounts = this.addUsers.map(function(item) {
return item.userAccount;
});
this.checkedUserAccounts = Array.from(new Set(checkedUserAccounts));
},
handleCheckedRoleCode() {
let checkedRoleCodes = this.addUsers.map(function(item) {
return item.roleCode;
});
this.checkedRoleCodes = Array.from(new Set(checkedRoleCodes));
},
//處理區(qū)域綁定值和勾選狀態(tài)
handleRegionCheckedAndStatus(deleteRegion) {
//1、處理區(qū)域復選框綁定值與全選框狀態(tài)
//角色選中
if (this.checkedRoleCodes.indexOf(this.currentClickRoleCode) > -1) {
if (!this.currentClickRole.indeterminate) {
//(1)全選狀態(tài)
this.checkedRoleRegionsMap[this.currentClickRoleCode] = this.allRegionCodes;
this.roleRegionAllCheckMap[this.currentClickRoleCode] = true;
} else {
//(2)半選狀態(tài)
//獲取選擇的區(qū)域列表
let checkedRegions = this.addUsers.map(user => {
if (user.roleCode === this.currentClickRoleCode) {
return user.regionName;
}
});
if (checkedRegions.length === 0) {
this.roleRegionAllCheckMap[this.currentClickRoleCode] = false;
this.roleRegionAllIndeterminateMap[this.currentClickRoleCode] = false;
} else {
this.roleRegionAllIndeterminateMap[this.currentClickRoleCode] = true;
}
this.checkedRoleRegionsMap[this.currentClickRoleCode] = Array.from(new Set(checkedRegions));
}
} else {
this.checkedRoleRegionsMap[this.currentClickRoleCode] = [];
this.roleRegionAllCheckMap[this.currentClickRoleCode] = false;
this.roleRegionAllIndeterminateMap[this.currentClickRoleCode] = false;
}
//(3)其他情況,賦空值,防止空指針
if (!this.checkedRoleRegionsMap[this.currentClickRoleCode]) {
this.checkedRoleRegionsMap[this.currentClickRoleCode] = new Array();
this.roleRegionAllCheckMap[this.currentClickRoleCode] = false;
this.roleRegionAllIndeterminateMap[this.currentClickRoleCode] = false;
}
//2、處理區(qū)域復選框狀態(tài)
let regionIndeterminateMap = {};
this.allRegionCodes.forEach(regionCode => {
//區(qū)域是選中狀態(tài)且有刪除用戶操作,則狀態(tài)置為半選
if (this.checkedRoleRegionsMap[this.currentClickRoleCode].indexOf(regionCode) === -1) {
//沒有勾選,為false
regionIndeterminateMap[regionCode] = false;
} else if (deleteRegion && regionCode === deleteRegion) {
//勾選且本次被刪除了,為半選狀態(tài)
console.info('刪除' + regionCode);
regionIndeterminateMap[regionCode] = true;
} else if (this.roleRegionIndeterminateMap && this.roleRegionIndeterminateMap[this.currentClickRoleCode]) {
//使用原來的值
regionIndeterminateMap[regionCode] = this.roleRegionIndeterminateMap[this.currentClickRoleCode][regionCode];
} else {
//其他情況
regionIndeterminateMap[regionCode] = false;
}
});
this.roleRegionIndeterminateMap[this.currentClickRoleCode] = regionIndeterminateMap;
},
//獲取區(qū)域
findRegions() {
if (this.cacheAllRegions && this.cacheAllRegions.length > 0) {
this.allRegions = this.cacheAllRegions;
this.allRegionCodes = this.allRegions.map(function(item) {
return item.value;
});
return;
}
//為空,第一次進入
this.$api['region/getRegions']().then(data => {
this.allRegions = data;
this.allRegionCodes = this.allRegions.map(function(item) {
return item.value;
});
});
},
//獲取角色
async findRoles() {
if (this.cacheAllRoles && this.cacheAllRoles.length > 0) {
this.allRoles = this.cacheAllRoles;
return;
}
//為空,第一次進入,查詢接口
await this.$api['role/getRoles']().then(data => {
data.forEach(item => {
item.indeterminate = false;
});
this.allRoles = data;
});
},
cancel() {
this.dialogVisible = false;
this.$emit('cancelSelectUser');
},
ok() {
this.dialogVisible = false;
//發(fā)送對象 = 初始化的用戶+用戶列表中選擇的用戶+角色列表選擇的用戶
this.$emit('changeSelectUser', this.addUsers, this.allRoles, this.allRegions, this.roleRegionIndeterminateMap);
},
//角色全選/全部取消,全量
handleCheckAllRole(val) {
console.info('全選開始:' + new Date());
if (val) {
//全選
this.scrollUserLoading = true;
//1、處理角色多選
this.checkedRoleCodes = this.allRoles.map(function(item) {
return item.value;
});
this.getUsersByRoles(new Array()).then(users => {
this.addUsers = users;
});
//2、處理用戶多選
this.handleCheckedUser();
//3、處理區(qū)域多選、全選狀態(tài)
this.checkedRoleCodes.forEach(roleCode => {
this.checkedRoleRegionsMap[roleCode] = this.allRegionCodes;
this.roleRegionAllCheckMap[roleCode] = true;
this.roleRegionAllIndeterminateMap[roleCode] = false;
});
} else {
//取消全選
//1、處理角色多選
this.checkedRoleCodes = [];
//2、處理用戶多選
this.addUsers = [];
this.checkedUserAccounts = [];
//3、處理區(qū)域多選、全選狀態(tài)
this.checkedRoleRegionsMap = {};
this.roleRegionAllCheckMap = {};
this.roleRegionAllIndeterminateMap = {};
}
//4、處理角色復選框狀態(tài)
this.allRoles.forEach(function(item) {
item.indeterminate = false;
});
//5、處理角色全選框樣式
this.roleIsIndeterminate = false;
console.info('全選結束:' + new Date());
},
//角色多選框勾選事件
handleCheckRole(e, role) {
// 因為原生click事件會執(zhí)行兩次,第一次在label標簽上,第二次在input標簽上,故此處理
if (e.target.tagName === 'INPUT' || e.target.tagName === 'A') return;
let roleCode = role.value;
if (this.checkedRoleCodes.indexOf(roleCode) === -1) {
//選中
//1、處理用戶多選
this.getUsersByRoles(new Array(roleCode)).then(users => {
let addUsers = this.addUsers.concat(users);
this.addUsers = this.uniqueUser(addUsers);
});
this.handleCheckedUser();
//2、處理區(qū)域多選
this.checkedRoleRegionsMap[roleCode] = this.allRegionCodes;
//3、處理角色-區(qū)域全選框狀態(tài)
this.roleRegionAllCheckMap[roleCode] = true;
this.roleRegionAllIndeterminateMap[roleCode] = false;
} else {
//取消
//1、處理用戶多選
this.addUsers = this.addUsers.filter(function(item) {
return item.roleCode !== roleCode;
});
this.handleCheckedUser();
//2、處理區(qū)域多選
this.checkedRoleRegionsMap[roleCode] = [];
//3、處理角色復選框狀態(tài)
role.indeterminate = false;
//4、處理角色-區(qū)域全選框狀態(tài)
this.roleRegionAllCheckMap[roleCode] = false;
this.roleRegionAllIndeterminateMap[roleCode] = true;
}
},
//角色詳情單擊事件,取A標簽的事件
clickRoleToRegionDetail(e, role) {
if (e.target.tagName !== 'A') return;
let roleCode = role.value;
this.currentClickRoleCode = roleCode;
this.currentClickRole = role;
//初始化區(qū)域勾選值與勾選狀態(tài)
this.handleRegionCheckedAndStatus();
this.isRegionListShow = true;
},
//從區(qū)域列表返回到角色
goBackToRole(e) {
//this.currentClickRoleCode = '';
this.isRegionListShow = false;
},
//區(qū)域全選/全部取消事件
handleCheckAllRegion(val) {
if (val) {
//全選
this.getUsersByRoles(new Array(this.currentClickRoleCode)).then(users => {
//1、處理用戶多選
let addUsers = this.addUsers.concat(users);
this.addUsers = this.uniqueUser(addUsers);
this.handleCheckedUser();
//2、處理角色多選
this.handleCheckedRoleCode();
});
//3、處理區(qū)域全選
this.checkedRoleRegionsMap[this.currentClickRoleCode] = this.allRegionCodes;
} else {
//取消全選
//3、處理區(qū)域多選
this.checkedRoleRegionsMap[this.currentClickRoleCode] = new Array();
this.$forceUpdate();
//1、處理用戶多選
let addUsers = this.addUsers.filter(user => {
return user.roleCode !== this.currentClickRoleCode;
});
this.addUsers = addUsers;
this.handleCheckedUser();
//2、處理角色多選
this.checkedRoleCodes = this.checkedRoleCodes.filter(roleCode => {
return roleCode !== this.currentClickRoleCode;
});
}
//4、處理角色全選框樣式
this.currentClickRole.indeterminate = false;
this.roleIsIndeterminate = false;
},
//區(qū)域勾選事件
handleCheckRegion(e, regionName) {
// 原生click事件會執(zhí)行兩次,第一次在label標簽上,第二次在input標簽上
if (e.target.tagName !== 'INPUT') return;
let checkRegions = this.checkedRoleRegionsMap[this.currentClickRoleCode];
if (checkRegions.indexOf(regionName) === -1) {
//選中
this.getUsersByRoles(new Array(this.currentClickRoleCode), regionName).then(users => {
//1、處理用戶多選
let addUsers = this.addUsers.concat(users);
this.addUsers = this.uniqueUser(addUsers);
this.handleCheckedUser();
//2、處理角色多選
this.handleCheckedRoleCode();
});
//3、處理角色多選狀態(tài);處理區(qū)域全選狀態(tài)
if (checkRegions.length === this.allRegionCodes.length - 1) {
//區(qū)域全部選中
this.currentClickRole.indeterminate = false;
this.roleRegionAllIndeterminateMap[this.currentClickRoleCode] = false;
} else {
this.currentClickRole.indeterminate = true;
this.roleRegionAllIndeterminateMap[this.currentClickRoleCode] = true;
}
} else {
//取消,強制改變值
checkRegions = checkRegions.filter(item => {
return item !== regionName;
});
this.checkedRoleRegionsMap[this.currentClickRoleCode] = checkRegions;
//1、處理用戶多選
let addUsers = this.addUsers.filter(item => {
return !(item.roleCode === this.currentClickRoleCode && item.regionName === regionName);
});
this.addUsers = addUsers;
this.handleCheckedUser();
//2、處理角色多選、多選狀態(tài);處理區(qū)域全選狀態(tài)
if (checkRegions.length === 0) {
this.roleRegionAllIndeterminateMap[this.currentClickRoleCode] = false;
this.checkedRoleCodes = this.checkedRoleCodes.filter(roleCode => {
return roleCode !== this.currentClickRoleCode;
});
} else {
this.currentClickRole.indeterminate = true;
this.roleRegionAllIndeterminateMap[this.currentClickRoleCode] = true;
}
}
},
//區(qū)域詳情單擊事件
clickRegionToUserDetail(e, regionName) {
if (e.target.tagName !== 'A') return;
//阻止選中
e.preventDefault();
this.isFromClickRegion = true;
this.getUsersByRoles(new Array(this.currentClickRoleCode), regionName).then(users => {
this.queryUsers = users;
});
},
//角色選擇改變
handleCheckedRoleChange(roleCodes) {
let checkedCount = roleCodes.length;
let totalCount = this.allRoles.length;
this.roleCheckAll = checkedCount === totalCount;
this.roleIsIndeterminate = checkedCount > 0 && checkedCount < totalCount;
},
async getUsersByRoles(roleCodes, regionName) {
let roleCodeStr = '';
if (roleCodes && roleCodes.length > 0) {
roleCodeStr = roleCodes.join(',');
}
let queryUsers = [];
await this.$api['user/getUserByRoleAndRegion']({
roleCodes: roleCodeStr,
region: regionName
}).then(data => {
queryUsers = data;
});
return queryUsers;
},
//搜索用戶
searchUser() {
if (this.userNameOrAccount) {
this.$api['user/getByNameOrAccount']({
nameOrAccount: this.userNameOrAccount
}).then(data => {
this.queryUsers = data;
if (data.length === 0) {
this.isNoDataShow = true;
} else {
this.isNoDataShow = false;
}
});
this.isFromClickRegion = false;
} else {
this.isNoDataShow = false;
this.queryUsers = [];
this.isRegionListShow = false;
}
},
//從用戶列表返回到區(qū)域
goBackToRegion(e) {
this.queryUsers = [];
this.isRegionListShow = true;
this.handleRegionCheckedAndStatus();
},
//用戶全選,這里選中的用戶是整體用戶的子集
handleCheckAllUser(val) {
let queryRoleCodes = this.queryUsers.map(user => {
return user.roleCode;
});
if (val) {
//全選
//1、處理用戶多選
let addUsers = this.addUsers.concat(this.queryUsers);
this.addUsers = this.uniqueUser(addUsers);
this.handleCheckedUser();
//2、處理角色多選框狀態(tài),新增的角色設為半選
this.allRoles.forEach(role => {
let roleCode = role.value;
if (queryRoleCodes.indexOf(roleCode) >= 0 && this.checkedRoleCodes.indexOf(roleCode) === -1) {
role.indeterminate = true;
}
});
//3、處理角色多選
this.handleCheckedRoleCode();
} else {
//全部取消
//1、處理用戶多選
let queryUserAccounts = this.queryUsers.map(function(item) {
return item.userAccount;
});
let addUsers = this.addUsers.filter(function(item) {
return queryUserAccounts.every(function(item1) {
return item.userAccount !== item1;
});
});
this.addUsers = this.uniqueUser(addUsers);
this.handleCheckedUser();
//2、處理角色多選
this.handleCheckedRoleCode();
//3、處理角色多選框狀態(tài),取消的角色去除選擇狀態(tài)
this.allRoles.forEach(role => {
let roleCode = role.value;
if (queryRoleCodes.indexOf(roleCode) >= 0 && this.checkedRoleCodes.indexOf(roleCode) >= 0) {
role.indeterminate = true;
} else {
role.indeterminate = false;
}
});
}
//4、用戶全選樣式改變
this.userIsIndeterminate = false;
//5、點擊后回到角色列表頁
if (!this.isFromClickRegion) {
this.queryUsers = [];
this.isRegionListShow = false;
}
},
//用戶復選框點擊事件
handleCheckUser(e, user) {
// 原生click事件防止執(zhí)行多次
if (e.target.tagName !== 'SPAN') return;
let userAccount = user.userAccount;
let roleCode = user.roleCode;
let regionName = user.regionName;
if (this.checkedUserAccounts.indexOf(userAccount) === -1) {
//選中
//1、處理用戶
let addUser = this.queryUsers.find(item => {
return item.userAccount === userAccount;
});
this.addUsers.push(addUser);
this.addUsers = this.uniqueUser(this.addUsers);
//2、處理角色多選、角色復選框選擇狀態(tài)
this.handleCheckedRoleCode();
this.handleCheckedRoleChange(this.checkedRoleCodes);
//3、角色復選框選中狀態(tài)改變
this.roleCheckStatusChange(roleCode);
} else {
//取消
//1、處理用戶
this.addUsers = this.addUsers.filter(function(item) {
return item.userAccount !== userAccount;
});
//2、處理角色多選、角色復選框選擇狀態(tài)
this.handleCheckedRoleCode();
this.handleCheckedRoleChange(this.checkedRoleCodes);
//3、角色復選框選中狀態(tài)改變
this.roleCheckStatusChange(roleCode);
//4、處理區(qū)域復選框
this.handleRegionCheckedAndStatus(regionName);
}
//點擊后回到角色列表頁
if (!this.isFromClickRegion) {
this.queryUsers = [];
this.isRegionListShow = false;
}
},
checkUserChange(checkedUserAccounts) {
//右側用戶列表包含左側復選框用戶列表,userCheckAll為true,userIsIndeterminate為false
let isUserCheckAll = true;
let isUserCheck = false;
//是否都選中了,有一個沒選擇則為false
this.queryUsers.forEach(item => {
if (this.checkedUserAccounts.indexOf(item.userAccount) < 0) {
isUserCheckAll = false;
return;
}
});
//是否沒選擇的,有一個選擇則為true
this.queryUsers.forEach(item => {
if (this.checkedUserAccounts.indexOf(item.userAccount) >= 0) {
isUserCheck = true;
return;
}
});
this.userCheckAll = isUserCheckAll;
if (isUserCheck && !isUserCheckAll) {
//有勾選,全選才會存在半選狀態(tài)
this.userIsIndeterminate = true;
} else {
this.userIsIndeterminate = false;
}
},
//用戶、角色全選框選中狀態(tài)改變
userAndRoleAllCheckStatusChange() {
this.checkUserChange(this.checkedUserAccounts);
//角色復選框選中狀態(tài)改變
this.handleCheckedRoleChange(this.checkedRoleCodes);
},
//角色復選框選中狀態(tài)改變
roleCheckStatusChange(roleCode) {
this.allRoles.forEach(item => {
if (item.value === roleCode) {
if (this.checkedRoleCodes.indexOf(roleCode) !== -1) {
item.indeterminate = true;
} else {
item.indeterminate = false;
}
}
});
},
//去重
uniqueUser(arr) {
var obj = {};
arr = arr.reduce(function(item, next) {
obj[next.userAccount] ? '' : (obj[next.userAccount] = true && item.push(next));
return item;
}, []);
return arr;
},
//刪除本次新增的用戶
deleteAddUser(index) {
let deleteUser = this.addUsers[index];
let deleteUserAccount = deleteUser.userAccount;
let roleCode = deleteUser.roleCode;
let regionName = deleteUser.regionName;
//1、用戶復選框綁定值同步刪除
this.checkedUserAccounts = this.checkedUserAccounts.filter(function(value) {
return value !== deleteUserAccount;
});
//2、最后本次新增的用戶刪除
this.addUsers.splice(index, 1);
//3、角色復選框綁定值同步變化
this.handleCheckedRoleCode();
//4、用戶全選狀態(tài)改變
this.userAndRoleAllCheckStatusChange();
//5、角色選中狀態(tài)改變,設置已選且有刪除用戶操作的角色indeterminate為true
this.roleCheckStatusChange(roleCode);
//6、區(qū)域選擇情況
this.handleRegionCheckedAndStatus(regionName);
}
},
watch: {
queryUsers: {
handler: function(val) {
if (val && val.length > 0) {
this.handleCheckedValue();
this.userAndRoleAllCheckStatusChange();
}
}
},
addUsers: {
handler: function(val) {
if (val && val.length > 0) {
this.scrollLoadUser();
}
}
}
}
};
</script>
<style scoped lang="less">
.role-region-user {
.goback-to-role {
//margin-right: 10px;
}
.no-data {
color: red;
}
}
.user-row {
.role-region-user-col {
/deep/ .el-checkbox {
color: #606266;
font-weight: 500;
font-size: 14px;
cursor: pointer;
user-select: none;
margin-right: 30px;
display: block;
}
.detail-btn {
float: right;
margin-left: 20px;
}
}
.user-col {
.user-item {
margin-left: 10px;
}
.delete-icon {
float: right;
margin-right: 20px;
}
.load-user {
text-align: center;
/deep/ .el-icon-loading {
font-size: 30px;
}
}
}
//滾動條
.scoll-col {
max-height: 300px;
overflow-y: auto;
}
}
</style>從性能角度考慮,已知問題:
(1)左側用戶列表勾選操作,對應的角色不會由半選變?yōu)槿x:如某角色先選中,再刪除右側某一人員,該角色變?yōu)榘脒x狀態(tài),再通過左側用戶列表單獨勾選或者全選的方式加上該用戶,該角色的狀態(tài)仍為半選;
(2)區(qū)域上方的全選框可以區(qū)分全選和半選,而每個區(qū)域的復選框不能嚴格區(qū)分半選和全選:
如執(zhí)行用戶添加動作,對應的區(qū)域均為全選,執(zhí)行用戶刪除操作時,所屬區(qū)域狀態(tài)變?yōu)榘脒x,再次添加上刪除的用戶,區(qū)域仍為半選
到此這篇關于Vue3+ElementUI 多選框中復選框和名字點擊方法效果分離的文章就介紹到這了,更多相關Vue3 ElementUI 多選框內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue中router.beforeEach()的簡單用法舉例
router.beforeEach()一般用來做一些進入頁面的限制,比如沒有登錄,就不能進入某些頁面,只有登錄了之后才有權限查看某些頁面,下面這篇文章主要給大家介紹了關于vue中router.beforeEach()的簡單用法舉例,需要的朋友可以參考下2023-01-01
Vue?echarts實例項目商家銷量統(tǒng)計圖實現詳解
Echarts,它是一個與框架無關的?JS?圖表庫,但是它基于Js,這樣很多框架都能使用它,例如Vue,估計IONIC也能用,因為我的習慣,每次新嘗試做一個功能的時候,總要新創(chuàng)建個小項目,做做Demo2022-09-09

