碰到的问题
今天用elment-ui时碰到了一个坑,记录一下:
项目中有一个页面是带批量下载功能的,需要点击批量操作才会出现全选按钮和item中的多选框,但是直接用v-if没有过渡效果感觉很生硬。于是自己写了一个css过渡效果,把全选按钮隐藏在批量操作按钮下方,点击批量操作后,从按钮的右侧移出
<!-- 点击切换操作和取消操作,取消操作后清空已选列表 -->
<el-button @click="isBatch=!isBatch;!isBatch&&checkedList.splice(0)">
{{isBatch?'取消操作':'批量操作'}}
</el-button>
<!-- 通过添加class类名实现come-out过渡,通过change事件实现全选按钮的勾选和取消勾选逻辑 -->
<el-checkbox label="全选" border @change="checkAll" :class="isBatch?'come-out':''"
:checked="!!checkedList.length && checkedList.length === dataList.length"
:indeterminate="!!checkedList.length && checkedList.length < dataList.length"></el-checkbox>
<!-- 通过checkedList和dataList的长度来控制indeterminate和checked状态 -->
<!-- 通过checkedList的长度来控制下载本页还是下载选中 -->
<el-button type="primary" @click="downloadFn">
{{!checkedList.length?'下载本页':`下载选中 (${checkedList.length})`}}
</el-button>
<el-checkbox-group v-model="checkedList">
<div v-for="item in dataList">
<el-checkbox v-if="isBatch" :label="item.id"></el-checkbox>
<!-- other content -->
</div>
</el-checkbox-group>
export default{
data:() => ({
isBatch: false,
checkedList: [],
dataList:[
{ id:1, name:'Keith' },
{ id:2, name:'Annie' }
]
}),
methods:{
checkAll(isCheckAll){
this.checkedList = isCheckAll? this.dataList.map(item => item.id) : []
},
downloadFn(){
if(this.checkedList.length){
// download checkList
} else {
// download all
}
}
}
}
.el-button{
position: relative;
z-index: 10;
}
.el-checkbox.is-bordered {
background-color: #fff;
padding-left: 20px;
opacity: 0.5;
margin-left: -99px;
transition: all 0.5s;
&.come-out {
opacity: 1;
margin-left: 10px;
}
}
但是出现了一个很奇怪的问题,当我全部选中时点击取消操作,清空了已选列表,但是再点击批量操作的时候,全选按钮还是勾选状态,于是就出现了奇怪的一幕
子选项一个都没选,而且checkedList也是空的,但全选按钮是选中状态
解决办法1:
既然是checked状态的问题,那么改用v-model绑定一个变量不就可以解决了,通过watch监控checkedList的值变化来改变变量的值
<!-- 去掉:checked 加上v-model -->
<el-checkbox label="全选" border @change="checkAll" :class="isBatch?'come-out':''" v-model="isAllChecked"
:indeterminate="!!checkedList.length && checkedList.length < dataList.length"></el-checkbox>
export default{
data:() => ({
// ...
isAllChecked: false // 加上控制组件的变量
}),
watch:{
// 监控checkedList的变化来控制全选按钮的v-model
checkedList(arr){
this.isAllChecked = !!arr.length && arr.length === this.dataList.length
}
},
// ...
}
解决办法2:
前面说过用v-if的时候并不存在这个问题,因为v-if对组件进行了销毁,再次出现会正确显示勾选状态,那么我们需要解决的问题就是过渡css效果,那就可以用vue的transition
来制作过渡样式
进入/离开 & 列表过渡
将el-checkbox
放入transition
标签内并指定name
<transition name="come">
<el-checkbox v-if="isBatch" label="全选" border @change="checkAll"
:checked="!!checkedList.length && checkedList.length === dataList.length"
:indeterminate="!!checkedList.length && checkedList.length < dataList.length">
</el-checkbox>
</transition>
css中改为
.el-checkbox.is-bordered {
background-color: #fff;
padding-left: 20px;
margin-left: 10px;
&.come-enter-active,
&.come-leave-active {
transition: all 0.5s;
}
&.come-enter,
&.come-leave-to {
margin-left: -99px;
opacity: 0;
}
}
这样也能实现保留过渡效果,也能保证全选按钮的checked状态是正常的。
墙裂建议用第二种解决方法,vue的transition用起来简直爽爆了