首页 > 其他 > 详细

基于vue的多级下拉框组件

时间:2019-12-16 10:33:32      阅读:80      评论:0      收藏:0      [点我收藏+]

前几天做了个需求,如图所示,有删除选项,全选/取消全选,大类切换,选中/取消选中功能。找不到现有的组件,就自己动手写了一个。

技术分享图片

 

话不多说,直接上代码

 

1、selectBar.vue

<template>
<div class="select-box" v-clickoutside="handClose">
<el-checkbox @change="chooseAll" id="checkboxBtn">全选</el-checkbox>
<div class="select-input" @click="toggle">
<p v-if="inputData.length==0">请选择类型</p>
<div class="selected-btn" v-for="(item,key) in inputData">
{{item.name}} <a href="##" @click.stop="delInput(item.id)"><i class="el-icon-error"></i></a>
</div>
<i class="el-icon-arrow-down down-icon" v-if="!isShow"></i>
<i class="el-icon-arrow-up down-icon" v-else></i>
</div>
<div class="select-banner" v-show="isShow">
<div class="banner-left">
<p :class="{active:bigActive==key}" v-for="(item,key) in listData" @click="switchFn(key)">{{item.name}}</p>
</div>
<div class="banner-right">
<div class="select-list" v-for="(item,key) in nowData">
<div class="select-list-left">
{{item.name}}
</div>
<div class="select-list-right">
<span v-for="(list,index) in item.children" :class="{‘active‘:list.active}" v-on:click.stop="chooseFn(list.id)">{{list.name}}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import clickoutside from ‘../../utils/clickoutside.js‘ //引入点击外部触发事件的插件
export default {
name: ‘selectBar‘,
directives: {clickoutside },
props: [‘goodsList‘,‘chooseList‘],
data () {
return {
allStatus: false,
isShow:false,
listData:this.goodsList,//全部商品列表
inputData:this.chooseList, //选中项列表
nowData:[],
bigActive:0,
index:0
}
},

watch:{
goodsList: {
      handler(newValue, oldValue) {
this.listData=newValue;
this.nowData= this.index===0? newValue[0].children: this.nowData;
this.index++;
     },
     deep: true
   },
inputData(value){
if(value.length==0){ //如果没有选中项,取消全选按钮选择的状态
if( document.querySelectorAll(‘.is-checked‘).length>0){
document.querySelectorAll(‘.is-checked‘)[0].classList.remove(‘is-checked‘);
}
}
     }},
   
methods: {
switchFn(index){
this.bigActive=index;
this.nowData=this.listData[index].children;
},
handClose(){
this.isShow=false
},
toggle(){
this.isShow=!this.isShow;
if(this.listData==‘‘){
this.$parent.getData();
}
},
//递归遍历数据,全选和反选
filtersData(data,value){
let oData=data.filter((item)=>{
if(item.children){
this.filtersData(item.children,value)
}else{
item.active = value;
}
return item
})
return oData
},
//全选
chooseAll(){
this.allStatus=!this.allStatus;
this.listData = this.filtersData(this.listData,this.allStatus)
this.setInput()
},
//选中
chooseFn(value,type=true){
this.listData= this.listData.filter((oValue)=>{
oValue.children.filter((item)=>{
item.children.filter((list)=>{
if(list.id === value){
list.active = !list.active;
}
return list
})

return item
})
return oValue
})
this.setInput(type)

},
//过滤ID传回父组件
setInput(type=true){
let oA=[];
if(this.listData&&this.listData.length>0){
this.listData.forEach((item)=>{
if(item&&item.children&&item.children.length>0){
item.children.forEach((list)=>{
list.children.forEach((value)=>{
if(value.active){
oA.push(value)
}
})
})
}

})
}

if(type){
this.inputData = oA;
}
let value=[];
oA.forEach((item)=>{
value.push(item.id)
})
this.$emit(‘getInput‘, value)
},
//取消选中
delInput(id){
this.chooseFn(id,false)
this.inputData=this.inputData.filter((item)=>{
return item.id !==id;
})
}
}}

</script>
<style scoped type="text/less" lang="less">
.select-box{
width: 100%;
position: relative;
.el-checkbox{
width: 50px;display: inline-block;position: absolute;top:-30px;right: 0;
}
.select-input{
min-height: 40px;border: 1px solid #ddd;
padding:5px 30px 10px 0;
p{
height: 40px;line-height: 40px;margin-left: 20px;color: #999;font-size:14px;
}
.down-icon{
position: absolute;right: 10px;top: 15px;
font-size: 20px;
}
.selected-btn{
display: inline-block;
padding:5px; background-color: #f9f9f9;border: 1px solid #ddd;border-radius: 6px;
margin:5px 0 0 8px;
}
}
.select-banner{
max-height: 300px;border:1px solid #ddd;
border-top:none;
position: absolute;left: 0 ;
background-color: #fff;
width: 100%;
overflow:hidden;
box-sizing: border-box;

.banner-left{
width: 25%;float: left;
min-width: 100px;
background-color: #f2f2f2;
height: 200px;
overflow-y: auto;
p{
text-align: center;
font-size: 15px;
height: 30px;line-height: 30px;
cursor: pointer;
color: #333;
}
.active{
background-color: #fff;
}
}
.banner-right{
width: 75%;float:left;
padding:10px 0;
height: 180px;
overflow-y: auto;
}
.select-list{
overflow: hidden;
}
.select-list-left{
width: 100px;
float: left;
text-align: center;
min-height: 40px;line-height: 40px;
color: #333;
font-weight: 700;
}
.select-list-right{
width: calc(100% - 100px);
float: left;
span{
margin: 5px 0 0 10px;
padding:5px 10px;border-radius: 4px;
display: inline-block;
cursor: pointer;
color: #666;
}
.active{
background-color: #0079fe;color: #fff;
}
}
}
}
</style>

 

2、使用  在要用的页面中引入

 import selectBar from ‘../../components/selectBar/selectBar‘

注册

components: {
selectBar
},

使用

 <selectBar :goodsList="listData" :chooseList="inputData" @getInput="getInputId"></selectBar>

此处 getInputId方法用于取到选中的项的ID 传给后台。

 

listData的测试数据:[{"id":"1","name":"家用电器","children":[{"id":"5","name":"电视","children":[{"id":"7","name":"曲面电视1"}]},{"id":"70","name":"空调","children":[{"id":"86","name":"壁挂式空调"}]},{"id":"90","name":"洗衣机","children":[{"id":"91","name":"滚筒洗衣机"}]}]},{"id":"9","name":"手机数码","children":[{"id":"72","name":"手机通讯","children":[{"id":"116","name":"手机"}]},{"id":"187","name":"摄影摄像","children":[{"id":"190","name":"单电/微单相机"}]},{"id":"258","name":"数码配件","children":[{"id":"259","name":"存储卡"}]}]},{"id":"29","name":"电脑办公","children":[{"id":"352","name":"电脑整机","children":[{"id":"354","name":"笔记本"}]},{"id":"357","name":"电脑配件","children":[{"id":"358","name":"显示器"}]},{"id":"362","name":"外设产品","children":[{"id":"364","name":"鼠标"}]}]}]

基于vue的多级下拉框组件

原文:https://www.cnblogs.com/zjk6/p/12047422.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!