美文网首页
vue树形结构,实现无限级分类,可移动排序

vue树形结构,实现无限级分类,可移动排序

作者: 芸芸众生ing | 来源:发表于2019-10-16 17:07 被阅读0次

    需要配合 VUEX 实现,ui组件用的是element-ui

    import Vue from 'vue'
    import Vuex from 'vuex';
    
    Vue.use(Vuex)
    const module = {
      state: {
          menuList: null, 
      },
      mutations: {
        setMenuList(state, data) {
          state.menuList = data
        }
      }
    };
    const store = new Vuex.Store(module);
    export default store
    
    

    组件代码

    <template>
      <!-- 菜单结构 -->
      <div>
        <div class="menu-box menu-box-margin" v-for="(v,i) in value" :key="i">
          <div class="menu-box-item">
            <!-- 单条菜单 -->
            <div class="menu-box-item-title">
              <div>
                <i class="el-icon-caret-bottom" @click.stop="v.check = !v.check"></i>
                <span>{{v.title}}</span>
              </div>
              <div>
                <i class="el-icon-back" @click.stop="onMoveLeft(i,v)"></i>
                <i class="el-icon-right" @click.stop="onMoveRight(i,v)"></i>
                <i class="el-icon-top" @click.stop="onMoveTop(i,v)"></i>
                <i class="el-icon-bottom" @click.stop="onMoveBottom(i,v)"></i>
                <i class="el-icon-close" @click.stop="_delOneNavItem(v)"></i>
              </div>
            </div>
            <!-- 菜单设置 -->
            <div class="menu-box-content" v-show="v.check">
              <el-form-item label="菜单标题">
                <el-input size="mini" v-model="v.title" />
              </el-form-item>
              <el-form-item label="菜单副标题">
                <el-input size="mini" v-model="v.subTitle" />
              </el-form-item>
              <div class="space-between">
                <el-form-item label="对应页面名称">
                  <el-select value="s" size="mini">
                    <el-option :label="v.title" value />
                  </el-select>
                </el-form-item>
                <el-form-item label="那些设备上显示">
                  <el-select value="s" size="mini" multiple>
                    <el-option label="--" value="a" />
                  </el-select>
                </el-form-item>
              </div>
            </div>
          </div>
          <!-- 递归循环遍历 -->
          <tree v-if="v.children" :value="v.children" />
        </div>
      </div>
    </template>
    <script>
    import { mapMutations,mapState } from "vuex";
    export default {
      name: "tree",
      props: {
        value: null
      },
      computed: {
        ...mapState(["menuList"])
      },
      methods: {
        ...mapMutations(["setMenuList"]),
        _navListSort() {
          let menuList = this._setDept(this.menuList);
          this.setMenuList(this.menuList);
        },
        _setDept(arr, dept = 1, id = null, address = null) {
          if (!arr) {
            return null;
          }
          for (let k = 0; k < arr.length; k++) {
            arr[k].dept = dept;
            arr[k].parentId = id;
            arr[k].position = k;
            arr[k].parentPosition = address;
            if (arr[k].children && arr[k].children.constructor == Array) {
              arr[k].children = this._setDept(
                arr[k].children,
                arr[k].dept + 1,
                arr[k].id,
                k
              );
            }
          }
          return arr;
        },
        _getDept(dept, arr, parentId) {
          dept--;
          if (dept == 0) {
            return arr;
          }
          for (let k in arr) {
            if (arr[k].dept == dept) {
              if (arr[k].id == parentId) {
                return arr;
              }
            }
            if (arr[k].children && arr[k].children.constructor == Array) {
              return this._getDept(dept, arr[k].children, parentId);
            }
          }
          return [];
        },
        onMoveLeft(index, v) {
          let current = this._getDept(v.dept - 1, this.menuList, v.parentId);
          if (v.dept == 1) return;
          let item = this.value.splice(index, 1)[0];
          current.splice(item.parentPosition + 1, 0, item);
          this._navListSort();
        },
        onMoveRight(index, v) {
          if (index == 0) return;
          let current = this.value;
          let item = current.splice(index, 1);
          item[0].parentId = current[index - 1].id;
          if (current[index - 1].children) {
            current[index - 1].children.push(...item);
          } else {
            current[index - 1].children = item;
          }
          this._navListSort();
        },
    
        onMoveBottom(index, v) {
          let current = this.value;
          if (index + 1 == current.length) return;
          let item = current.splice(index, 1);
          current.splice(index + 1, 0, ...item);
          this._navListSort();
        },
        onMoveTop(index, v) {
          if (index == 0) return;
          let current = this.value;
          let item = current.splice(index, 1);
          current.splice(index - 1, 0, ...item);
          this._navListSort();
        },
    
        // 删除一个子菜单
        async _delOneNavItem(e) {
          this.value.splice(this.value.findIndex(k => k.id == e.id), 1);
          let result = await this.$http({
            url: "/manager/menuitem/" + e.id,
            method: "delete",
            headers: {
              "X-TENANT-ID": this.$route.params.organizationId
            }
          });
        }
      }
    };
    
    </script>
    <style lang="less" scoped>
    .menu-box {
      width: 100%;
      height: 100%;
      overflow: hidden;
      .menu-box-item {
        margin-top: 10px;
        border: solid 1px #e6ebf1;
        border-radius: 6px;
        min-width: 300px;
        max-width: 500px;
        background: #fff;
        .menu-box-item-title {
          padding: 0 20px;
          display: flex;
          justify-content: space-between;
          align-items: center;
          height: 40px;
          i {
            padding: 2px;
            background-color: #e6ebf1;
            border-radius: 6px;
            color: #838eab;
            cursor: pointer;
            margin: 0 2px;
          }
        }
        .menu-box-content {
          padding: 0 20px;
          border-top: 1px solid #e6ebf1;
        }
      }
      .menu-box-margin {
        margin-left: 40px;
      }
    }
    </style>
    

    相关文章

      网友评论

          本文标题:vue树形结构,实现无限级分类,可移动排序

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