vue3 移动端 实现树形结构 tree(支持多选 全选)

实现效果:
image
)
版本号:
image

1、需求是支持全选功能,网上找了许多 这里做个记录
这里使用的是vue-virtual-tree 感觉作者写的很详细 可以跳转查看 git地址
2、使用方法
(1)npm i @ysx-libs/vue-virtual-tree
(2)main.js中引入
import '@ysx-libs/vue-virtual-tree/style.css';
(3)页面中使用

点击查看代码
<template>
  <!-- 白名单 页面 -->
  <div class="content">
    <nut-popup :close-on-click-overlay="false" round class="popup_con" position="bottom" :style="{ height: '80%' }"
      v-model:visible="showBottom">
      <div class="demo">
        <div class="check_all_box" >
          <nut-checkbox @click="checkAllFun(list)" v-model="checkRadio" checked-color="#ee0a24">
            <div class="check_all">全选</div>
          </nut-checkbox>
        </div>
        <!-- <section> -->
        <vir-tree  ref="virTreeOne" show-checkbox :source="list" :render-node="renderNode"
          :default-checked-keys="defaultCheckedKeys" @checkChange=checkChangeHandle()>
        </vir-tree>
        <!-- </section> -->
      </div>
      <div class="footer_btn">
        <nut-button @click="handleCancel" class="cancel_btn" type="default">取消</nut-button>
        <nut-button @click="handleSubmit" class="submit_btn" type="primary">提交</nut-button>
      </div>
    </nut-popup>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue'
import { VirTree } from '@ysx-libs/vue-virtual-tree';
// 弹窗是否展示
const showBottom = ref(true)
let list = ref([]);
const virTreeOne = ref(null);
let defaultCheckedKeys = ref([]);
let checkRadio = ref(false)

onMounted(() => {
  list.value = recursion();
  getListLength(list.value)
});

// tree 组件开始
const recursion = () => {
  const listData = [
    {
      nodeKey: '1',
      name: '1',
      children: [
        {
          nodeKey: '1.1',
          name: '1.1',
          children: [
            {
              nodeKey: '1.11',
              name: '1.11',
              children: [],
            },
          ],
        },
        {
          nodeKey: '1.2',
          name: '1.2',
          children: [],
        }
      ],
    },
    {
      nodeKey: '2',
      name: '2',
      children: [
        {
          nodeKey: '2.1',
          name: '2.1',
          children: [],
        },
        {
          nodeKey: '2.2',
          name: '2.2',
          children: [],
        }
      ],
    }, {
      nodeKey: '3',
      name: '3',
      children: [
        {
          nodeKey: '3.1',
          name: '3.1',
          children: [],
        },
        {
          nodeKey: '3.2',
          name: '3.2',
          children: [],
        }, {
          nodeKey: '3.3',
          name: '3.3',
          children: [],
        }
      ],
    }
  ];

  return listData;
}
// 获取tree 数据总条数
let listLength = ref(0)
let getListLength = (row) => {
  row.forEach(ele => {
    listLength.value++
    if (ele.children) {
      getListLength(ele.children)
    }
  });
}

// 获取选中数据
const checkedNodes = () => {
  const checks = virTreeOne.value.getCheckedNodes();
  console.log('获取选中', checks);
}
//定义树形结构样式 
const renderNode = node => {
  return <div style="padding: 0 4px;"><b style=" { color: '#333333',fontSize: '1rem'}">{node.name}</b></div>
};

// 提交按钮
const handleSubmit = () => {
  console.log(defaultCheckedKeys.value);
  checkedNodes()
}
// 取消按钮
const handleCancel = () => {
  showBottom.value = false
}

// 属性组件选中复选框事件
const checkChangeHandle = () => {
  if (virTreeOne.value.getCheckedNodes().length == listLength.value) {
    checkRadio.value = true
  }
  if (virTreeOne.value.getCheckedNodes().length != listLength.value) {
    checkRadio.value = false
  }
}

// 全选按钮
const checkAllFun = (row) => {
  console.log('全选按钮',checkRadio.value);
  if (checkRadio.value) {
    row.forEach(ele => {
      defaultCheckedKeys.value = defaultCheckedKeys.value.concat([ele.nodeKey])
      if (ele.children) {
        checkAllFun(ele.children)
      }
    });
  } else {
    defaultCheckedKeys.value = []
  }
}

// tree 组件结束
</script>
<style scoped lang='scss'>
.content {
  position: relative;
  height: 100vh;
}

.up_img {
  width: 12px;
  height: 12px;
  margin-right: 2%;
}

.down_img {
  width: 12px;
  height: 16px;
  margin-right: 2%;

}

::v-deep .vir-tree-wrap .vir-tree-node .node-arrow {
  position: absolute !important;
  right: 0 !important;
}

::v-deep .nut-popup {
  padding: 16px 16px 64px 16px;
  box-sizing: border-box;
}

::v-deep .check_all_box {

  height: 48px;
  display: flex;
  align-items: center;

  .nut-checkbox__label {
    margin-left: 4px !important;
  }

  .check_all {
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0px;
    line-height: 16px;
    color: rgba(51, 51, 51, 1);
  }
}



.footer_btn {
  position: fixed;
  left: 0px;
  bottom: 0px;
  right: 0px;
  width: 100%;
  background: rgba(255, 255, 255, 1);
  display: flex;
  box-shadow: 0px -20px 10px #f8f8f8;

  .cancel_btn {
    width: 164px;
    height: 36px;
    font-size: 14px;
    color: rgba(153, 153, 153, 1);
    border-radius: 51px;
    margin: 6px 16px 6px 15px;
  }

  .submit_btn {
    width: 164px;
    height: 36px;
    font-size: 14px;
    border-radius: 51px;
    margin: 6px 16px 6px 0px;
  }
}

::v-deep .vir-tree {
  max-height: calc(80% - 80px) !important;

  .vir-tree-node {
    border-bottom: 1px solid #ECECEC;
    min-height: 32px;
    line-height: 32px;
  }

  .iconzhankai:before {
    font-size: 16px;
  }

  .vir-checkbox .inner {
    border-radius: 50% !important;
    width: 14px;
    height: 14px;
  }

  .vir-checkbox.checked .inner {
    border-color: #DE1627;
    background-color: #DE1627;
  }

  .vir-checkbox.half-checked .inner:after {
    background-color: #DE1627 !important;
  }
}
</style>

  </vir-tree>

(4)问题记录
取消全选:defaultCheckedKeys.value = []
全选:
defaultCheckedKeys.value.push(ele.nodeKey) // 不生效 使用为下面的方法

defaultCheckedKeys.value = defaultCheckedKeys.value.concat([ele.nodeKey]) // 使用这种方法

posted @ 2023-03-23 17:06  你的眼里有星星  阅读(3120)  评论(0编辑  收藏  举报