级联选择器
- 一、市面上的级联选择器
- 二、功能实现
- 1、数据类型
- 2、隐藏下拉框的方法
- 3、html结构
- 4、CSS代码
- 5、各个方法代码
- 三、实现样式截图
- 1、一级菜单
- 1、鼠标放到一级菜单,就显示二级菜单
- 2、鼠标点击一级菜单的时候
- 2、二级菜单
- 1、鼠标放到二级菜单的时候,显示三级菜单
- 2、鼠标点击二级菜单的时候,显示一级菜单和二级菜单
- 3、三级菜单
- 1、鼠标点击三级菜单的时候
一、市面上的级联选择器
用多了组件库以后,发现各种级联选择器都有很多问题,用着很不方便
1、比如我有三级,我只能点击我最后一个级别的时候,我的下拉框才会收回,
2、很多组件都没法实现光点击我的一级或者二级菜单,必须要点击最后一级菜单
3、 而且传的值也是一个数组类型的,处理起来要判断,很麻烦,没法我点击一个传递一个ID
所以我根据功能自己写了一个三级下拉框,
二、功能实现
1、数据类型
数据类型为树形结构,我贴上我的数据
dataList: {
name: '总经理',
code: 1,
level: 1,
isSaleDepartment: false,
nodes: [
{
name: '管理部',
code: 11,
level: 2,
isSaleDepartment: false,
nodes: [
{
name: '人事',
code: 111,
level: 3,
isSaleDepartment: true,
nodes: [],
id: 8,
},
{
name: '行政',
code: 112,
level: 3,
isSaleDepartment: true,
nodes: [],
id: 9,
},
{
name: '采购',
code: 113,
level: 3,
isSaleDepartment: true,
nodes: [],
id: 10,
},
{
name: '仓库',
code: 114,
level: 3,
isSaleDepartment: true,
nodes: [],
id: 11,
},
{
name: '财务',
code: 115,
level: 3,
isSaleDepartment: true,
nodes: [],
id: 12,
},
],
id: 2,
},
{
name: '销售部',
code: 12,
level: 2,
isSaleDepartment: true,
nodes: [
{
name: '销售部门1',
code: 121,
level: 3,
isSaleDepartment: true,
nodes: [],
id: 13,
},
{
name: '销售部门2',
code: 122,
level: 3,
isSaleDepartment: true,
nodes: [],
id: 14,
},
{
name: '销售部门3',
code: 123,
level: 3,
isSaleDepartment: true,
nodes: [],
id: 15,
},
{
name: '销售部门4',
code: 124,
level: 3,
isSaleDepartment: true,
nodes: [],
id: 16,
},
],
id: 3,
},
{
name: '业务部',
code: 13,
level: 2,
isSaleDepartment: false,
nodes: [
{
name: '销售',
code: 131,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 17,
},
{
name: '市场开发',
code: 132,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 18,
},
{
name: '售后服务',
code: 133,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 19,
},
],
id: 4,
},
{
name: '工程部',
code: 14,
level: 2,
isSaleDepartment: false,
nodes: [
{
name: '新产品开发',
code: 141,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 20,
},
{
name: '产品设计',
code: 142,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 21,
},
{
name: '产品工艺',
code: 143,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 22,
},
{
name: '资料管理',
code: 144,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 23,
},
],
id: 5,
},
{
name: '生产部',
code: 15,
level: 2,
isSaleDepartment: false,
nodes: [
{
name: '生产计划',
code: 151,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 24,
},
{
name: '设备制造',
code: 152,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 25,
},
{
name: '工程安装',
code: 153,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 26,
},
],
id: 6,
},
{
name: '品质部',
code: 16,
level: 2,
isSaleDepartment: false,
nodes: [
{
name: '质量管理',
code: 161,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 27,
},
{
name: '过程控制',
code: 162,
level: 3,
isSaleDepartment: false,
nodes: [],
id: 28,
},
],
id: 7,
},
],
id: 1,
},
2、隐藏下拉框的方法
hideDropdown() {
this.showDropdown = false;
this.currentProvinceName = null;
this.currentCityName = null;
},
3、html结构
我是用原生的div和ul以及li标签实现的
<div class="app">
<div class="dropdown" @mouseleave="hideDropdown">
<div
@click="showDropdown = !showDropdown"
@mouseenter="showclose = true"
@mouseleave="showclose = false"
:style="{ width: widthLength }"
class="selectContent"
:class="showDropdown ? 'active' : ''"
>
<span style="color: #ccc" v-if="selectedText === '请选择'">{{
selectedText
}}</span>
<span v-else>{{ selectedText }}</span>
<Icon
class="icon"
type="md-close"
v-if="
selectedText &&
selectedText !== '请选择' &&
showclose &&
showcloseIcon
"
@click.stop="clear"
/>
</div>
<ul class="menu" v-if="showDropdown">
<li
@click.stop="clickFirst(dataList)"
@mouseenter="showSubmenu(dataList)"
>
{{ dataList.name }}
<!-- <div class="arrow-down" v-if="dataList.nodes.length > 0"></div> -->
<!-- <Icon v-if="dataList.nodes.length > 0" type="ios-arrow-forward" /> -->
<ul
v-if="
currentProvinceName === dataList.name && dataList.nodes.length > 0
"
class="submenu"
>
<li
class="secondMenu"
v-for="second in dataList.nodes"
:key="second.id"
@click.stop="clickSecond(dataList.name, second)"
@mouseenter="showSubmenuSecond(second)"
>
{{ second.name }}
<Icon v-if="second.nodes.length > 0" type="ios-arrow-forward" />
<ul
v-if="
currentCityName === second.name && second.nodes.length > 0
"
class="thiredMe"
>
<li
class="thirdMenu"
v-for="third in second.nodes"
:key="third.id"
@click.stop="selectDistrict(dataList.name, second, third)"
>
{{ third.name }}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
4、CSS代码
<style scoped>
.arrow-down {
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid black;
}
.app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
margin: 0 auto;
}
.active {
border-color: #57a3f3;
outline: 0;
box-shadow: 0 0 0 2px rgba(45, 140, 240, 0.2);
}
.icon {
position: absolute;
right: 5px;
font-size: 16px;
}
.selectContent {
border: 1px solid #ccc;
border-radius: 3px;
position: relative;
height: 32px;
padding: 0 24px 0 8px;
display: flex;
align-items: center;
}
.selectContent:hover {
border-color: #57a3f3;
outline: 0;
box-shadow: 0 0 0 2px rgba(45, 140, 240, 0.2);
}
.dropdown {
display: inline-block;
position: relative;
cursor: pointer;
z-index: 1000;
}
.dropdown .menu {
list-style-type: none;
padding: 0;
margin: 0;
position: absolute;
top: 102%;
left: 0;
background: white;
border: 1px solid #ccc;
border-radius: 5px;
z-index: 1000;
width: 100px;
}
.dropdown .menu > li {
padding: 8px;
cursor: pointer;
position: relative;
}
.dropdown .menu > li:hover {
background: #f3f3f3;
}
.secondMenu {
padding: 5px;
position: relative;
}
.secondMenu:hover {
background: #f3f3f3;
}
.dropdown .submenu {
list-style-type: none;
padding: 0;
margin: 0;
position: absolute;
top: 0;
left: 100%;
background: white;
border: 1px solid #ccc;
border-radius: 5px;
display: none;
z-index: 500;
width: 100px;
/* max-height: 200px;
overflow-y: auto; */
max-height: 200px; /* 设置固定高度 */
}
.thiredMe {
border: 1px solid #ccc;
position: absolute;
left: 100%;
width: 100px;
top: 0;
z-index: 1001;
background: white;
border-radius: 5px;
list-style-type: none;
height: 150px;
overflow: auto;
}
.thirdMenu {
padding: 5px;
position: relative;
}
.thirdMenu:hover {
background: #f3f3f3;
}
.dropdown .menu > li:hover > .submenu {
display: block;
}
ul {
padding-left: 0 !important;
}
</style>
5、各个方法代码
methods: {
showSubmenu(item) {
this.currentProvinceName = item.name;
this.currentCityName = null;
},
showSubmenuSecond(item) {
this.currentCityName = item.name;
},
hideDropdown() {
this.showDropdown = false;
this.currentProvinceName = null;
this.currentCityName = null;
},
// 点击一级菜单
clickFirst(first) {
this.$emit('current', first);
this.selectedText = first.name;
this.hideDropdown();
},
// 点击二级菜单
clickSecond(firstname, second) {
this.$emit('current', second);
this.selectedText = firstname + '-' + second.name;
this.hideDropdown();
},
// 点击三级菜单
selectDistrict(first, second, third) {
console.log('firs', first, second.name, third.name);
this.selectedText = first + '-' + second.name + '-' + third.name;
this.hideDropdown();
this.$emit('current', third);
},
},
三、实现样式截图
1、一级菜单
1、鼠标放到一级菜单,就显示二级菜单
2、鼠标点击一级菜单的时候
就直接显示一级的内容,并且下拉框也是隐藏状态
2、二级菜单
1、鼠标放到二级菜单的时候,显示三级菜单
2、鼠标点击二级菜单的时候,显示一级菜单和二级菜单
并且下拉框也是隐藏状态
3、三级菜单
1、鼠标点击三级菜单的时候
直接显示三个菜单的内容,并且下拉框隐藏了,