需求
实现如下交互样式


可通过传参方式定一级、二级的数据。
可配置文字前的icon,是否可点击 disabled 、分隔线 divided 等等,具体看demo代码实例
公共组件代码
<template>
<el-dropdown
trigger="click"
@command="dropdownClick"
@visible-change="dropdownChange"
>
<span class="el-dropdown-link">
<slot></slot>
</span>
<el-dropdown-menu slot="dropdown" ref="dropdownView">
<div
v-for="(item, index) in data"
:key="index"
:class="item.disabled ? 'disabled' : ''"
>
<div
v-if="item.children && item.children.length > 0"
class="dropdown-item-more"
ref="dropdownItemMore"
>
<div
class="dropdown-item-more-view"
@click="openMore(item)"
:class="item.active || item.isOpenMore ? 'active' : ''"
>
<i v-if="item.icon" class="iconfont" :class="item.icon"></i>
<span>{{ item.label }}</span>
<i class="el-icon-arrow-right"></i>
</div>
<div
v-show="item.isOpenMore"
class="dropdown-item-more-right"
ref="dropdownItemMoreRight"
:style="{ left: left, right: right }"
>
<div
v-for="(itemChildren, i) in item.children"
:key="i"
:class="itemChildren.disabled ? 'disabled' : ''"
>
<div
v-if="itemChildren.type === 'title'"
:class="itemChildren.divided ? 'title-disabled' : ''"
class="title"
>
{{ itemChildren.label }}
</div>
<el-dropdown-item
v-else
:command="[item.val, itemChildren.val]"
:disabled="itemChildren.disabled"
:class="itemChildren.active ? 'active' : ''"
:divided="itemChildren.divided"
>
<div class="check">
<i
v-if="itemChildren.icon"
class="iconfont"
:class="itemChildren.icon"
></i>
<span>{{ itemChildren.label }}</span>
<i
v-if="ischeck && itemChildren.active"
class="check-icon iconfont iconcheck"
></i>
</div>
</el-dropdown-item>
</div>
</div>
</div>
<el-dropdown-item
v-else
ref="dropdownItemMore"
:command="[item.val]"
:disabled="item.disabled"
:class="item.active ? 'active' : ''"
>
<i class="iconfont" :class="item.icon"></i>
{{ item.label }}
</el-dropdown-item>
</div>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
props: {
data: {
type: Array,
default: () => []
},
checkedData: {
type: Array,
default: () => []
},
ischeck: {
type: Boolean,
default: () => false
}
},
data() {
return {
left: '',
right: ''
}
},
components: {},
methods: {
leftFun() {
const aa =
document.body.clientWidth - this.$refs.dropdownView.$el.offsetLeft
if (aa < 300) {
this.right = `${this.$refs.dropdownItemMore[0].offsetWidth}px`
} else {
this.left = `${this.$refs.dropdownItemMore[0].offsetWidth}px`
}
},
dropdownChange(val) {
this.$emit('visibleChange', val)
setTimeout(() => {
this.leftFun()
}, 0)
this.checkedDataFun()
if (!val) {
this.clearFun()
}
},
dropdownClick(val) {
this.$emit('dropDownCallback', val)
},
clearFun() {
for (let i = 0; i < this.data.length; i++) {
this.$set(this.data[i], 'isOpenMore', false)
this.$set(this.data[i], 'active', false)
if (this.data[i].children && this.data[i].children.length) {
for (let j = 0; j < this.data[i].children.length; j++) {
this.$set(this.data[i].children[j], 'active', false)
}
}
}
},
openMore(item) {
if (item.disabled) {
return
}
this.clearFun()
this.$set(item, 'isOpenMore', true)
this.leftFun()
},
checkedDataFun() {
for (let i = 0; i < this.data.length; i++) {
if (this.data[i].val === this.checkedData[0]) {
this.$set(this.data[i], 'active', true)
this.$set(this.data[i], 'isOpenMore', true)
if (this.data[i].children && this.data[i].children.length) {
for (let j = 0; j < this.data[i].children.length; j++) {
if (this.data[i].children[j].val === this.checkedData[1]) {
this.$set(this.data[i].children[j], 'active', true)
return
}
}
}
}
}
}
},
mounted() {}
}
</script>
<style lang="scss" scoped>
.dropdown-item-more {
position: relative;
.dropdown-item-more-view {
display: flex;
align-items: center;
line-height: 36px;
margin: 0 8px;
padding: 0 16px;
border-radius: 6px;
color: $--color-font-default;
cursor: pointer;
span {
flex: 1;
}
&:hover {
background: $--custom-background-hover;
}
i {
color: $--custom-button-font-disabled;
}
.el-icon-arrow-right {
font-size: 12px;
margin-left: 8px;
}
}
.dropdown-item-more-right {
background: $--custom-dropdown-background;
border-radius: 6px;
width: auto;
position: absolute;
top: -8px;
padding: 8px 0;
box-shadow: -6px 0px 4px rgba(0, 0, 0, 0.16);
.title {
color: #9e9da1;
font-size: 14px;
padding-top: 8px;
margin-top: 8px;
padding-left: 24px;
line-height: 20px;
}
.title-disabled {
border-top: 1px solid $--custom-divide;
}
.check {
display: flex;
align-items: center;
span {
flex: 1;
}
}
}
.iconfont {
margin-right: 8px;
}
}
.active {
background: $--custom-background-focus;
.check-icon {
color: $--color-primary;
margin-left: 8px;
font-size: 12px;
margin-right: 0;
}
}
.disabled {
cursor: not-allowed;
.dropdown-item-more-view {
color: $--custom-placeholder;
cursor: not-allowed;
&:hover {
background: transparent;
color: $--custom-placeholder;
}
}
}
</style>
demo实例代码
<template>
<div>
<drop-down
class="p"
:data="data"
:checkedData="['1', '1-1']"
@dropDownCallback="dropDownCallback"
:ischeck="true"
>
<template>是他是他就是他 小哪吒</template>
</drop-down>
</div>
</template>
<script>
import DropDown from './DropDown'
export default {
data() {
return {
data: [
{
label: '1',
val: '1',
icon: 'iconmsnui-more',
// disabled: true,
children: [
{
label: '取消私有取消私有取消私有取消私有',
val: '1-1',
icon: 'iconmsnui-more'
// disabled: true
},
{
label: '1-2',
divided: true,
val: '1-2'
}
]
},
{
label: '2',
// disabled: true,
val: '2',
icon: 'iconmsnui-more'
},
{
label: '3',
val: '3',
// disabled: true,
children: [
{
label: '3-1',
val: '3-1',
disabled: true
},
{
label: '3-2',
val: '3-2'
}
]
}
],
more: false,
treedata: [
{
label: '一级 1',
children: [
{
label: '二级 1-1',
children: [
{
label: '三级 1-1-1'
}
]
}
]
},
{
label: '一级 2',
children: [
{
label: '二级 2-1',
children: [
{
label: '三级 2-1-1'
}
]
},
{
label: '二级 2-2',
children: [
{
label: '三级 2-2-1'
}
]
}
]
},
{
label: '一级 3',
children: [
{
label: '二级 3-1',
children: [
{
label: '三级 3-1-1'
}
]
},
{
label: '二级 3-2',
children: [
{
label: '三级 3-2-1'
}
]
}
]
}
],
defaultProps: {
children: 'children',
label: 'label'
}
}
},
components: { DropDown },
methods: {
dropDownCallback(val) {
console.log('fuyuansu', val)
}
},
mounted() {}
}
</script>
<style lang="scss" scoped>
.p {
position: absolute;
// bottom: 0;
}
</style>
网友评论