美文网首页
在element-ui的dropdown 组件的基础上,实现二级

在element-ui的dropdown 组件的基础上,实现二级

作者: 前端青音 | 来源:发表于2020-06-08 15:03 被阅读0次

需求

实现如下交互样式


image.png image.png

可通过传参方式定一级、二级的数据。
可配置文字前的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>


相关文章

网友评论

      本文标题:在element-ui的dropdown 组件的基础上,实现二级

      本文链接:https://www.haomeiwen.com/subject/zekrtktx.html