一、效果
二、实现思路
1、多选下拉框由已选数据显示区域(input)、下拉框数据显示区域(ul)、查询输入框区域(input)组成;
2、已选数据显示区域不可编辑,只显示指定长度的数据,多余数据隐藏;
3、下拉框数据显示,点击数据选中之后,数据后方会出现对勾;再次点击,对勾消失,表示未选中此条数据;
4、查询输入框区域,支持模糊查询、精确查询
5、下拉框多选组件接受父组件数据:下拉框的基本配置参数
6、下拉框多选组件向父组件传送数据:当前下拉框的已选数据
三、代码分析
1、下拉框数据格式:
下拉框数据:
//text:用于下拉框中的显示字段,必须字段;
//value:默认是数据索引,非必须字段;
//isSelected:true-表示数据是已选中状态;false-表示数据未选中状态,必须字段
let selectList = [
{text:"zyk",value:"1",isSelected:true},
{text:"666",value:"2",isSelected:false}
];
2、dom代码:
<template>
<div :id="id" class="selectMultiple">
<!--已选数据显示区域-->
<input :id="inputID" :class="config.inputClass" type="text"
v-model="inputValue"
style="border-radius: 4px 4px 0 0;"
v-on:focus="inputFocus_control"
unselectable="on" onfocus="this.blur()"
v-on:input="toParent()"
/>
<!--下拉框展开/收缩按钮-->
<div class="selectList_collapse" v-on:click="showListDom_control()"></div>
<!--下拉框数据显示区域-->
<div :id="listDomID" class="select_list" v-show="isShowList">
<!--查询输入框区域-->
<div id="input_searchSelect" v-if="defaultCfg.isSearch">
<input :class="config.inputClass" type="search"
placeholder="请输入查询内容"
v-model="searchValue"
v-on:input="searchData()"/>
</div>
<!--下拉框数据-->
<ul>
<li v-for="item in selectDataList" :title="item.text"
v-on:click="selectedList(item)">
<!--预留图标,用于表示下拉框数据-->
<i></i>
<!--数据显示内容-->
<div class="listData_every" v-text="item[defaultCfg.view]"></div>
<!--对勾显示-表示选中;对勾隐藏-表示未选中-->
<div class="listData_every_isOK" v-show="item.isSelected"
:selectedFlag="selectedFlag">
</div>
</li>
</ul>
</div>
</div>
</template>
3、子组件接受父组件的值
props:{
//多选下拉框的基础配置
configBasic:{
type:Object,
default(){
return {}
}
},
/*下拉框中的数据*/
selectList:{
type:Array,
default(){
/*
* text:显示
* value:编号
* isSelected:是否被选中
* */
return []
}
}
}
4、子组件向父组件传递的值
//注册getSelectedData方法,返回当前下拉框选择的数据
_this.$emit("getSelectedData",_this.selectedArr);
5、data中的属性值
data(){
return {
id:"select_mulitiple",//多选下拉框的ID
inputID:"select_mulitiple_input",
listDomID:"select_mulitiple_list",
defaultCfg :{
inputClass:"",//多选框的input的class
width:'400px',//输入框的宽度
listHeight:'200px',//下拉框展开高度
isSearch:true,//是否支持查询
view:"text",//下拉框数据中用来显示
mode:"value",//下拉框数据中的索引标示
isSelectedFlag:"isSelected",//下拉框数据中的表示已经选择的数据
obscureSearch:true,//true:模糊查询;false:精确查询
maxSelect:15,//最多选择的个数
minSelect:5//最少选择的个数
},//默认值
config:this.configBasic,//接受父级传来的基本配置参数
selectedFlag:"√",//用于表示数据选中的样式
selectDataList:this.selectList,//接受父级传来的下拉框的数据
selectedArr:[],//存放下拉框选择的数据
isShowList:false,//控制下拉框显隐状态
inputValue:"",//存放选中数据的值,并且赋予下拉框中
searchValue:""//查询字符串
}
}
6、watch中的方法
//用于监听下拉框中值的变化
watch:{
selectList(value){
let _this = this;
//更新下拉框中的值
_this.selectDataList = value;
//下拉框数据处理,区分出已选数据
_this.initData(value)
}
},
7、组件基础方法
methods:{
/**
* 功能说明:初始化已经选择的数据
* 参数:listData-下拉框中的数据
* */
initData(listData){
let _this = this;
//获取已经选择的数据
_this.selectedArr = listData.filter(function (val,index,arr) {
return val[_this.defaultCfg.isSelectedFlag] ===true
});
/*更新输入框*/
let tempArr = [];
tempArr = _this.selectedArr.map(function (val,index,arr) {
return val[_this.defaultCfg.view];
});
//更新输入框中的值
_this.inputValue = tempArr.join(",");
},
/*
*功能说明:初始化多选择组件的基本样式
* */
initStyle(){
let _this = this;
let basicStyle = _this.defaultCfg;
//输入框的宽度
document.getElementById(_this.inputID).style.width = basicStyle.width;
//下拉框的宽度、高度
document.getElementById(_this.listDomID).style.width = basicStyle.width;
document.getElementById(_this.listDomID).style.height = basicStyle.listHeight;
},
/*
* 功能说明:点击选项时的点击事件
* 参数:item-选择的数据
* */
selectedList(item){
let _this = this;
//校验当前选择的个数
//缓存选择的数据
if(item.isSelected){
if(_this.selectedArr.length <= _this.defaultCfg.minSelect){
alert("至少选择"+_this.defaultCfg.minSelect+"条数据。");
return true;
}
//改变选择的数据的样式:隐藏对勾
item.isSelected = false;
//如果未选择当前数据,则从selectedArr中删除
_this.selectedArr = _this.selectedArr.filter(function (val,index,arr) {
return val[_this.defaultCfg.view]!=item[_this.defaultCfg.view]
});
}else{
if(_this.selectedArr.length>=_this.defaultCfg.maxSelect){
alert("最多只能选择"+_this.defaultCfg.maxSelect+"条数据。");
return true;
}
//改变选择的数据的样式:出现对勾
item.isSelected = true;
_this.selectedArr.push(item);
}
/*更新输入框*/
let tempArr = [];
tempArr = _this.selectedArr.map(function (val,index,arr) {
return val[_this.defaultCfg.view]
});
_this.inputValue = tempArr.join(",");
//把已选数据传向父组件
_this.$emit("getSelectedData",_this.selectedArr);
},
/*
* 功能说明:下拉框显隐控制
* */
showListDom_control(){
let _this=this;
let e = event ||window.event;
let currentDom = e.currentTarget;
if(_this.isShowList)
{
//如果当前是展开下拉框,则下拉框收起,图标变成向下
_this.isShowList =false;
currentDom.className = "selectList_collapse";
}
else
{
//如果当前是收起下拉框,则下拉框展开,图标变成向上
_this.isShowList =true;
currentDom.className = "selectList_expend";
}
},
/*
* 功能说明:输入框focus事件
* */
inputFocus_control(){
let _this = this;
let e=event||window.event;
let currentDom = e.currentTarget;
let expendDom = currentDom.nextSibling.nextSibling;
if(!_this.isShowList)
{
//如果当前是展开下拉框,则下拉框收起,图标变成向下
_this.isShowList =true;
expendDom.className = "selectList_expend";
}
},
/*
* 功能说明:实现查询功能
* 参数:val-查询输入框的值
* */
searchData(val){
let _this = this;
//查询字段
let searchVal = _this.searchValue;
if(searchVal ==""){
//如果查询字段是空,则返回所有数据
_this.selectDataList = _this.selectList;
}else{
if(_this.defaultCfg.obscureSearch){
//模糊查询-大小写不敏感
_this.selectDataList = _this.selectDataList.filter(function (val,index,arr) {
let viewText = val[_this.defaultCfg.view].toLowerCase();
let searchValToLower = searchVal.toLowerCase();
if(viewText.indexOf(searchValToLower)>-1){
return true;
}else{
return false
}
});
}else{
//精确查询
_this.selectDataList = _this.selectDataList.filter(function (val,index,arr) {
return searchVal === val[_this.defaultCfg.view]
});
}
}
}
}
8、生命周期调用
created(){
//初始化组件数据
let _this = this;
//合并
Object.assign(_this.defaultCfg,_this.config);
_this.selectDataList = _this.selectList
},
mounted(){
let _this = this;
/*初始化多选择组件的基本样式*/
_this.initStyle();
_this.initData( _this.selectDataList);
}