淘先锋技术网

首页 1 2 3 4 5 6 7

实现的效果
在这里插入图片描述

html的页面构造

<el-dialog
      v-if="dialogVisible"
      title="新增厅局代理人"
      :visible.sync="dialogVisible"
      width="660px"
      :before-close="cancel"
    >
      <div class="dialogContent">
        <div class="firstBox">
          <div class="serchBox">
            <!-- <el-input v-model.trim="searchPerson" prefix-icon="el-icon-search" placeholder="请输入" @keyup.enter.native="searchContent" /> -->
            <el-input
              v-model="filterText"
              placeholder="输入关键字进行过滤"
              @input="filterInput"
            />
          </div>
          <el-tree
            ref="tree"
            class="notTree"
            :class="treeTop ? 'notChecked' : 'haveChecked'"
            node-key="code"
            show-checkbox
            :data="personData"
            :props="defaultProps"
            :default-checked-keys="defKeys"
            :filter-node-method="filterNode"
            @check="handleNodeClick"
          >
            <span slot-scope="{ node, data }" class="notHover">
              <svg-icon v-if="data.personList" icon-class="filter" />
              <svg-icon v-else icon-class="person" />
              <span style="margin-left: 10px">{{ node.label }}</span>
            </span>
          </el-tree>
        </div>
        <div class="secondBox">
          <div class="personBox">
            <span>已选人数: {{ showPerson.length }}</span>
            <el-button type="text" @click="clearOut">清空</el-button>
          </div>
          <div class="personBoxTwo">
            <div v-for="(item, index) in showPerson" :key="index" class="selectBox">
              <div class="notHover">
                <svg-icon icon-class="person" />
                <span>{{ item.name }}</span>
              </div>
              <div>
                <svg-icon icon-class="clear" @click="removeData(item, index)" />
              </div>
            </div>
          </div>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="cureSure">确 定</el-button>
      </span>
    </el-dialog>

简介,在对话框里面使用树组件和列表渲染
node-key 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的
show-checkbox 节点是否可被选择
data 展示数据
prop:
label 指定节点标签为节点对象的某个属性值
children 指定子树为节点对象的某个属性值
default-checked-keys 默认勾选的节点的 key 的数组
filter-node-method 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏
check 当复选框被点击的时候触发

filterInput() {
      // 调用el-tree的filter方法,触发条件过滤,并将当前输入的信息传递到事件内部.
      this.$refs.tree.filter(this.filterText)
    },

输入关键字进行过滤

filterNode(value, data, node) {
      if (!value) {
        // 如果数据为空,则返回true,显示所有的数据项
        node.expanded = false
        return true
      }
      // 查询列表是否有匹配数据,将值小写,匹配英文数据
      const val = value.toLowerCase()
      return this.chooseNode(val, data, node) // 调用过滤二层方法
    },
    chooseNode(value, data, node) {
      if (data.name.indexOf(value) !== -1) {
        return true
      }
      const level = node.level
      // 如果传入的节点本身就是一级节点就不用校验了
      if (level === 1) {
        return false
      }
      // 先取当前节点的父节点
      let parentData = node.parent
      // 遍历当前节点的父节点
      let index = 0
      while (index < level - 1) {
        // 如果匹配到直接返回,此处name值是中文字符。判断匹配中英文过滤
        if (parentData.data.name.indexOf(value) !== -1) {
          return true
        }
        // 否则的话再往上一层做匹配
        parentData = parentData.parent
        index++
      }
      // 没匹配到返回false
      return false
    },

可以通过搜索父节点来遍历第二层,甚至第三层

handleNodeClick(data, row, res) {
// 这里主要是为了解决使用组件本身的过滤的方法全选会把之前隐藏的节点选上
      if (data.personList && data.personList.length) {
        // 只有点击是父节点并且父节点有孩子才能进入
        // 获取当前选中的叶子节点的id
        const checkedIds = this.getLeafNodes(data.personList)
        if (this.showPerson) {
        // 这里解决是当前父节点已经有选上的节点,会被删除
        // 这通过已选节点的数组和全选的父节点下叶子节点遍历,如果已选数组中和父节点叶子节点中都存在,就把父节点中的叶子点删除
          for (let i = 0; i < this.showPerson.length; i++) {
            for (let j = 0; j < checkedIds.length; j++) {
              if (checkedIds[j] === this.showPerson[i].code) {
                checkedIds.splice(j, 1)
              }
            }
          }
        }
        // 通过过滤后的数组,去删除全选父节点中多余的节点
        checkedIds.forEach((item) => {
          const node = this.$refs.tree.getNode(item)// 根据id获取node
          console.log('1445', node)
          if (!node.visible && node.checked) { // 将选中且隐藏的节点设置为 不选中
            this.$refs.tree.setChecked(item, false)
          }
        })
      }
      const valuePerson = this.$refs.tree.getCheckedNodes()
      // 这个获取选中节点的数组(会把父节点也加上)
      for (let i = 0; i < valuePerson.length; i++) {
        if (valuePerson[i].personList) {
          valuePerson.splice(i, 1)
        }
      }
      // 来删除父节点
      console.log('2104', valuePerson)
      //   this.showPerson = [...this.showPerson, ...valuePerson]
      this.showPerson = JSON.parse(JSON.stringify(valuePerson))
      // 将最终结果的数组进行深拷贝
      this.filterChecked(this.showPerson)
      // 需要去掉重复名的可以调用这个方法
    },

点击复选框触发的方法,

去重

 // 去重
    filterChecked(checked) {
      checked.forEach(el => {
        if (!this.exhibitionPerson.some(e => e.id === el.id)) {
          this.exhibitionPerson.push(el)
        }
      })
    },

清空

clearOut() {
      this.$nextTick(() => {
        this.$refs.tree.setCheckedKeys([])
        this.showPerson = []
        this.exhibitionPerson = []
        this.defKeys = []
        this.filterText = ''
      })
    },

单个删除

removeData(data) {
      this.$nextTick(() => {
        this.$refs.tree.setChecked(data.code, false, true)
        // 用来提交
        for (let i = 0; i < this.showPerson.length; i++) {
          if (this.showPerson[i].code === data.code) {
            this.showPerson.splice(i, 1)
            this.defKeys.splice(i, 1)
          }
        }
        // 用来显示
        for (let i = 0; i < this.exhibitionPerson.length; i++) {
          if (this.exhibitionPerson[i].id === data.id) {
            this.exhibitionPerson.splice(i, 1)
          }
        }
        console.log('2250', this.showPerson)
      })
    },