Bootstrap

【VUE3】ElementUI--el-card卡片列表、el-tree 结合多选框获取子节点id导出数据

唠唠叨叨

	好久没更了(赶紧水一篇啊X      临近节日,大家五一都会出行游玩还是宅家充电呢?
	顺便问一下北京有哪些便宜好玩的地方,还要有很多好吃的那种ˋ( ° ▽、° ) 

啊——这个人就是水。
在这里插入图片描述

事发背景

	记录一下开发中遇到的较为麻烦的多选checkbox结合组件。

实现效果

1.el-card卡片列表多选:
在这里插入图片描述
2.el-tree树形多选:
在这里插入图片描述在父级选中后我们不需要父级的id,只要求子级已选中的id,当子级全部勾选后父级也执行勾选,此时也要把父级id去掉。

安装和引入(水

首先要在项目文件安装具体可以查看element ui官网

1.通过 npm、yarn、pnpm 安装

//NPM
$ npm install element-plus --save

//Yarn
$ yarn add element-plus

//pnpm
$ pnpm install element-plus

2.浏览器引入

既可以通过将脚本下载到本地也可以直接引入在线资源:

#unpkg
<head>
  <!-- Import style -->
  <link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css" />
  <!-- Import Vue 3 -->
  <script src="//unpkg.com/vue@3"></script>
  <!-- Import component library -->
  <script src="//unpkg.com/element-plus"></script>
</head>

#jsDelivr
<head>
  <!-- Import style -->
  <link
    rel="stylesheet"
    href="//cdn.jsdelivr.net/npm/element-plus/dist/index.css"
  />
  <!-- Import Vue 3 -->
  <script src="//cdn.jsdelivr.net/npm/vue@3"></script>
  <!-- Import component library -->
  <script src="//cdn.jsdelivr.net/npm/element-plus"></script>
</head>

实现代码

这次比较简单直接,贴上代码就可以了!

  1. el-card卡片列表多选。
<template>
  <div class="flex button-right">
    <c-button class="mr-10" type="download" @click="onExportClick"/>
  </div>
  <div class="mt-20">
    <el-row :gutter="20">
      <el-col
        v-for="(item, index) in state.listData"
        :key="index"
        :span="8">
        <el-card class="mb-20">
          <el-image :key="index" class="pl-10 pr-10" style="width: 168px; height: 136px" :src="images.find(x => x.name === item.type).url" fit="contain" />
          <div style="padding: 0 14px 14px 14px">
            <span>{{ item.name }}</span>
            <div class="mt-5 mb-5">
              {{ item.database }}
            </div>
            <div class="bottom">
              <el-space wrap :size="10">
                <el-checkbox :ref="'check'+index" v-model="item.index"></el-checkbox>
              </el-space>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>
<script>
  import { getCurrentInstance, onMounted, reactive } from "vue";
  export default {
    name: "",
    setup() {
      const { proxy } = getCurrentInstance();
      const images = [
        { name: 'MYSQL', url: require('../../../../assets/Database/mysql.jpg') },
        { name: 'ORACLE', url: require('../../../../assets/Database/oracle.jpg') },
        { name: 'SQLSERVER', url: require('../../../../assets/Database/sqlserver.png') },
        { name: 'POSTGRESQL', url: require('../../../../assets/Database/postgresql.jpg') },
        { name: 'CLICKHOUSE', url: require('../../../../assets/Database/clickhouse.png') },
        { name: 'FTP', url: require('../../../../assets/Database/ftp.svg') },
        { name: 'HTTP', url: require('../../../../assets/Database/HTTP.svg') }
      ]
      const state = reactive({
        listData: [],
        typeList: ['CLICKHOUSE','MYSQL','ORACLE','POSTGRESQL','SQLSERVER','FTP','HTTP']
      })
      const onExportClick = () => { // 导出
        let fileList = []
        state.listData.forEach((x, index) => {
          if (proxy.$refs[`check${index}`][0].modelValue === true) { //判断当checkedbox传回的value为true时将id push进数组中
            fileList.push(x.id)
          }
        })
        let dataBaseIds = ''
        dataBaseIds = fileList.join(',') //获取到的id数组转为字符串以','隔开
        const formatData = new FormData()
        formatData.append('dataBaseIds', dataBaseIds)
        console.log(dataBaseIds);
      }
      onMounted(() => {
      });
      return {
        state,
        images,
        onExportClick,
      }
    },
  }
</script>
  1. el-tree树形节点多选。
<template>
  <div style="float:right">
    <el-dropdown @command="onExportClick" class="mr-10 cursor-pointer">
      <i><el-icon><Download /></el-icon></i>
      <template #dropdown>
        <el-dropdown-menu>
          <el-dropdown-item command="one">导出任务</el-dropdown-item>
          <el-dropdown-item command="all">导出全局</el-dropdown-item>
        </el-dropdown-menu>
      </template>
    </el-dropdown>
  </div>
  <el-tree
    ref="treeRef"
    :data="state.dataSource"
    show-checkbox
    node-key="code" <-- 当data里有哪个数值你要设为key的你就填哪个,一般是id,这里因为需求我写的是code -->
    :currrent-node-key="state.currentNodekey"
    highlight-current
    default-expand-allid
    :default-expanded-keys="state.defaultShowNodes"
    :expand-on-click-node="true"
    :filter-node-method="filterNode"
    @check-change="getCheckedNodes"
    @node-click="onTreeClick"
  />
</template>
<script>
import { defineComponent, getCurrentInstance, ref, onMounted, watch, reactive, toRefs } from "vue";
import { ElMessage } from 'element-plus'
import { Download } from '@element-plus/icons-vue'
export default defineComponent({
  name: "",
  components: { Download },
  setup() {
    const { proxy } = getCurrentInstance()
    const treeRef = ref('treeRef');
    const state = reactive({
      dataSource: [],
      checkedChild: [],
      checkedParent: [],
      currentData: '',
      currentNode: '',
      currentNodeName: '', //当前选中的节点名
      motif: '',//作业主题名(根节点名)
      defaultShowNodes: [],
      currentNodekey: "", //作业监控跳转选中的节点
    })
    //获取目录
    const getTreeData = () => {
      proxy.$axios.get(`url`,{
      })
      .then((res) => {
        let resq = res.data
        if(resq.code == 200){
          resq.data.map(x => {
            if(x.children.length === 0){ //设置若根目录无子节点,则其选框不可勾选
              x.disabled = true
            }
          })
          state.dataSource = resq.data
        }else{
          ElMessage.error(resq.msg) //报错
        }
      });
    }
    const getCheckedNodes = (data ,value) => { //获取选中节点id
      if(value === true){
        if (data.children === null) {
          state.checkedChild.push(data.code)
        } else {
          if (data.children.length !== 0) {
            state.checkedParent.push(data.code) //分出选中的项中的根目录id并形成数组
          }else{
            data.children.map(x => {
              state.checkedChild.push(x.code)
            })
          }
        }
      }else{
        state.checkedParent.map((item) =>{
          if(item === data.code){
            state.checkedParent.splice(state.checkedParent.indexOf(item) , 1) //当取消勾选移除根目录已选数组中取消的项
          }
        })
      }
    }
    const onExportClick = (command) => { // 导出
      state.outPortList = treeRef.value.getCheckedKeys() //获取树形结构数据中已勾选项的key值(这里在dom中我们设置的是code)
      state.checkedParent.map((x) => { //遍历删除已勾选项的key值数组中的父节点key值
        state.outPortList.map((item) =>{
          if(item === x){
            state.outPortList.splice(state.outPortList.indexOf(item) , 1)
          }
        })
      })
      let fileList = ''
      fileList = state.outPortList.join(',') //获取到的id数组转为字符串以','隔开
      if (command === 'current') {  //导出任务   
        if (fileList) {
          //调用导出方法
        }else{
          ElMessage.warning("请选择导出项")
        }
      } else {  //导出全局
        if (fileList) {
          //调用导出方法
        }else{
          ElMessage.warning("请选择导出项")
        }
      }
    }
    //监听
    watch([],(newval,oldval) => {
    })
    onMounted(() => {
      getTreeData()
    })
    return {
      ...toRefs(state),
      treeRef,
      state,
      getTreeData,
      getCheckedNodes,
      onExportClick,
    }
  },
});
</script>

参考资料

1.Element Plus(#Tree树形控件)
2.Element Plus(#Checkbox 多选框)

;