用elemet-ui组件实现弹窗里的树形结构和拖拽功能

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yilanyoumeng3/article/details/88015231

这个弹窗功能,主要是导出字段的设置,左边是树形字段结构,右边是选中的设置字段,字段可以拖动调顺序。我实现这个功能主要用的element-ui里的tree和dialog组件,及vuedraggable组件,如果没有拖拽功能差不多半个小时就搞定这个功能,就因为实现这个拖拽功能,浪费了很多时间,从昨天晚上八点多开始,一直折腾到十一点多,大致效果如图在这里插入图片描述
刚开始没考虑到拖拽会引起这么多问题,只是用store,state选中的字段,和选中的id给存起来,这样可以实现公用,及后面的设置存储数据
模拟数据如下

data2: [{
        id: 1,
        label: '一级 1',
        children: [{
          id: 4,
          label: '二级 1-1',
          children: [{
            id: 9,
            label: '三级 1-1-1'
          }, {
            id: 10,
            label: '三级 1-1-2'
          }]
        }]
      }, {
        id: 2,
        label: '一级 2',
        children: [{
          id: 5,
          label: '二级 2-1'
        }, {
          id: 6,
          label: '二级 2-2'
        }]
      }, {
        id: 3,
        label: '一级 3',
        children: [{
          id: 7,
          label: '二级 3-1'
        }, {
          id: 8,
          label: '二级 3-2'
        }]
      }]
import Service from './service'
import config from './config'
const store = {
  namespaced: true,
  state: {
    checkedFields: [],  //选中对象
    fieldKeys: [], //选中的id
    deepData: []
  },
  mutations: {

    setCheckedFields (state, data = []) {
      state.checkedFields = data
    },
    setFieldKeys (state, keys = []) {
      state.fieldKeys = keys
    },
    setDeepData (state, data = []) {
      state.deepData = data
    }
  }
}

export default store

后来发现在这个行不通,数据都是共用的,拖动,删除的实话容易造成排序问题,
后来就把选中的给深拷贝来一份,左右数据相当独立,在state中添加了一个变量,

deepData: []
 mutations: {

    setCheckedFields (state, data = []) {
      state.checkedFields = data
    },
    setFieldKeys (state, keys = []) {
      state.fieldKeys = keys
    },
    setDeepData (state, data = []) {
      state.deepData = data
    }
  }

利用getters处理数据获取深拷贝后的id数据,如下

  getters: {
  
    deepKeys (state) {
      const { deepData } = state
      let arr = []
      deepData.map(ele => {
        arr.push(ele.id)
      })
      return arr
    }
  }

然后监听tree里面的复选框事件,再递归循环数据,对比是选中还是重置,然后再根据情况,修改deepData里的值,刚开始用的tree里的check-change事件,发现这个事件容易触发几次事件,如果在父节点上点击,这样就获取了重复数据,右边的数据也出现了重复现象,后来用check事件避免了这个问题
实现代码如下

//监听事件方法
handleCheckChange (data, checked) {
      let isReset = checked.checkedKeys.every(ele => ele !== data.id)
      if (!isReset) {
        this.$refs.tree.store.nodesMap[data.id].expanded = true
        data.unfold = true
        this.dataCheck(data, !isReset)
      } else {
        this.dataCheck(data, !isReset)
      }
      this.setCheckedFields(this.$refs.tree.getCheckedNodes(true))
      this.setFieldKeys(this.$refs.tree.getCheckedKeys(true))
    },
    dataCheck (obj, b) {
      let arr = []
      this.dataLoop(obj, arr)
      if (b) {
        this.setDeepData(cloneDeep(this.deepData.concat(arr)))
      } else {
        arr.forEach(ele => {
          this.deepData.forEach(val => {
            if (ele.id === val.id) {
              this.deepData.splice(this.deepData.indexOf(val), 1)
              this.setDeepData(cloneDeep(this.deepData))
            }
          })
        })
      }
    },
    //递归
    dataLoop (obj, arr) {
      let arr2 = obj.children
      if (arr2) {
        arr2.forEach(ele => {
          this.dataLoop(ele, arr)
        })
      } else {
        arr.push(obj)
      }
    }

删除功能是利用watch监听deepKeys变化,然后再设置
删除功能代码:

 delItem (index) {
      this.deepData.splice(index, 1)
    }

watch监听deepKeys变化

watch: {
    deepKeys (newkeys) {
      if (newkeys) {
        this.$refs.tree.setCheckedKeys(newkeys, true)
      }
    }
  },

拖拽功能实现主要用的vuedraggable组件,实现代码如下:

<draggable
        :list="child"
        @end="dragEndHandle"
      >
        <li
          v-for="(item, index) in child"
          :key="item.id"
          :index1="item.index"
        >
          <span>{{ item.label }}</span>
          <div class="set-field-tool">
            <i
              class="icon iconfont icon-move"
            />
            <i
              class="icon iconfont icon-minus"
              @click="delItem(index)"
            />
          </div>
        </li>
      </draggable>

拖拽js代码如下:

dragEndHandle ({ oldIndex, newIndex }) {
      const { deepData } = this
      const item = deepData[oldIndex]
      deepData.splice(oldIndex, 1)
      deepData.splice(newIndex, 0, item)
    }

猜你喜欢

转载自blog.csdn.net/yilanyoumeng3/article/details/88015231