首页 > 其他分享 >树状选择组件

树状选择组件

时间:2023-08-21 11:45:24浏览次数:33  
标签:index const 树状 选择 item datasource 组件 data check

1、创建组件

<template>
  <!-- 遮罩层 -->
  <div class="mask" v-if="show">
    <!-- picker-->
    <div class="content" :style="'height:' + height">
      <div class="header">
        <div class="cancel" @click="cancel">取消</div>
        <div class="title">
          {{ title }}
        </div>
        <div class="submit" @click="submit">确定</div>
      </div>
      <!-- 横线 -->
      <div class="line"></div>
      <!-- tree 可下拉 可全展开 可勾选 原生 -->
      <div class="tree">
        <ul>
          <template v-for="item in datasource">
            <li>
              <div class="item-text">
                <div
                  class="label"
                  :style="{ paddingLeft: item.level * 20 + 'px' }"
                >
                  {{ item[label] }}
                </div>
                <div class="check-box">
                  <div
                    :class="item.check ? 'check-active' : 'check'"
                    @click="toggleItem(item)"
                  ></div>
                </div>
              </div>
            </li>
            <div style="margin-left: 20px">
              <template v-if="item.children">
                <li v-for="child in item.children" :key="child.id">
                  <div
                    class="item-text"
                    :style="{ marginLeft: (item.level + 1) * 20 + 'px' }"
                  >
                    <div class="label">{{ child[label] }}</div>
                    <div class="check-box">
                      <div
                        :class="child.check ? 'check-active' : 'check'"
                        @click="toggleItem(child)"
                      ></div>
                    </div>
                  </div>
                </li>
              </template>
            </div>
          </template>
        </ul>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "mw-tree-picker",
  props: {
    show: {
      type: Boolean,
      default: false,
    },
    height: {
      type: String,
      default: "50%",
    },
    title: {
      type: String,
      default: "请选择",
    },
    data: {
      type: Array,
      default: () => [],
    },
    label: {
      type: String,
      default: "label",
    },
    children: {
      type: String,
      default: "children",
    },
  },
  watch: {
    show: {
      handler(newData) {
        this.datasource = this.flattenData(this.data);
      },
      deep: true,
    },
  },

  data() {
    return {
      datasource: [],
    };
  },
  methods: {
    // 取消
    cancel() {
      // emit
      this.$emit("cancel");
    },
    // 根据传递进来的数组 和动态的key 和this.datasource 匹配上的 item[key] 等于 datas中的某个id 说明这个item是选中的
    checkData(datas, key) {
        console.log(datas,'传值怎么会这样',datas.length)
      this.$nextTick(() => {
          if(datas.length!=0){
             this.datasource =  this.datasource.map((item) => {
                 if(datas.some((data) => data[key] === item[key])) {
                   item.check = true;
                  // 如果勾选了子节点,那么它的父节点也要勾选
                  if (item.level > 1) {
                    const parentIndex = item.index.split("-").slice(0, -1).join("-");
                    const parent = this.datasource.find(
                      (item) => item.index === parentIndex
                    );
                    parent.check = true;
                  }
                 }
                 return item;
              });
          }else{
               this.datasource =  this.datasource.map((item) => {
                   item.check = false
                   return item
               })
          }
          
      
        console.log(this.datasource ,'人生');
      });
    },

    // 通过已经勾选的数据 匹配原数据data 只不过check要通过判断形成新的
    getCheckedData() {
      const checkedData = this.datasource.filter(
        (item) => item.check && !item[this.children]
      );
      const checkedIds = checkedData.map((item) => item.id);
      const data = JSON.parse(JSON.stringify(this.data));
      return this.matchData(data, checkedIds);
    },

    // 通过已经勾选的数据 匹配原数据data 只不过check要通过判断形成新的
    matchData(data, checkedIds) {
      return data.map((item) => {
        if (checkedIds.includes(item.id)) {
          item.check = true;
        }
        if (item[this.children]) {
          item[this.children] = this.matchData(item[this.children], checkedIds);
        }
        return item;
      });
    },

    // 提交
    submit() {
      // 要勾选的数据 如果有子节点 父级节点不要
      const checkedData = this.datasource.filter(
        (item) => item.check && !item[this.children]
      );
      // emit
      this.$emit("submit", { checkedData, datasource: this.getCheckedData() });
    },
    // 选中的处理
    toggleItem(item) {
      // 选中的处理
      item.check = !item.check;
      // 如果勾选当前节点,那么它的所有子节点都勾选
      if (item.check) {
        this.checkAllChildren(item);
      } else {
        this.uncheckAllChildren(item);
      }
      this.$forceUpdate();
    },
    // 将指定元素的所有子元素勾选
    checkAllChildren(item) {
      // 如果勾选了子节点,那么它的父节点也要勾选
      if (item.level > 1) {
        const parentIndex = item.index.split("-").slice(0, -1).join("-");
        const parent = this.datasource.find(
          (item) => item.index === parentIndex
        );
        parent.check = true;
      }

      this.datasource.forEach((child) => {
        if (child.index.startsWith(item.index) && child.index !== item.index) {
          child.check = true;
        }
      });
    },
    // 将指定元素的所有子元素取消勾选
    uncheckAllChildren(item) {
      //当子节点所有都取消勾选,那么它的父节点也要取消勾选
      if (item.level > 1) {
        const parentIndex = item.index.split("-").slice(0, -1).join("-");
        const parent = this.datasource.find(
          (item) => item.index === parentIndex
        );
        const siblings = this.datasource.filter(
          (item) =>
            item.index.startsWith(parentIndex) && item.index !== parentIndex
        );
        if (siblings.every((item) => !item.check)) {
          parent.check = false;
        }
      }

      this.datasource.forEach((child) => {
        if (child.index.startsWith(item.index) && child.index !== item.index) {
          child.check = false;
        }
      });
    },
    // 递归成一维 并且都有唯一的index 层次分明 有父子关系函数
    flattenData(data, parentIndex = "") {
      let flattenedData = [];
      data.forEach((item, index) => {
        const currentIndex = parentIndex
          ? `${parentIndex}-${index}`
          : `${index}`;
        const { id, name, children, ...rest } = item;
        flattenedData.push({
          id,
          name,
          index: currentIndex,
          level: parentIndex ? parentIndex.split("-").length + 1 : 1,
          ...rest,
        });
        if (item[this.children]) {
          flattenedData = flattenedData.concat(
            this.flattenData(item[this.children], currentIndex)
          );
        }
      });
      return flattenedData;
    },
  },
};
</script>
<style scoped>
.line {
  width: 100%;
  height: 1px;
  background-color: #e5e5e5;
}

.content {
  display: flex;
  flex-direction: column;
  width: 100%;
  background-color: #fff;
  min-height: 30%;
  position: absolute;
  bottom: 0;
}

.header {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  height: 50px;
  min-height: 50px;
  background-color: #fff;
  /* padding: 0 10px; */
  width: 90%;
  margin: 0 auto;
}

.cancel {
  font-size: 14px;
  color: #333;
}

.title {
  font-size: 16px;
  color: #333;
}

.submit {
  font-size: 14px;
  color: #409eff;
}

.check-active {
  background-color: #409eff;
  color: #fff;
  width: 20px;
  height: 20px;
  border: 1px solid #409eff;
  border-radius: 2px;
  float: right;
  margin-right: 10px;
}

/* 伪类 伪元素 选中的有对勾 */
.check-active::after {
  content: "";
  display: block;
  width: 10px;
  height: 10px;
  border: 1px solid #fff;
  border-top: none;
  border-right: none;
  transform: rotate(-50deg);
  position: relative;
  top: 2px;
  left: 4px;
}

.check {
  width: 20px;
  height: 20px;
  border: 1px solid #e5e5e5;
  border-radius: 2px;
  margin-right: 10px;
  background-color: #fff;
  cursor: pointer;
  float: right;
}

.tree {
  overflow-y: auto;
  width: 100%;
}
.tree ul {
  list-style: none;
  padding: 10px;
}

.tree ul li {
  position: relative;
}

.tree ul li .item-text {
  display: flex;
  height: 40px;
  font-size: 14px;
  color: #333;
  cursor: pointer;
  width: 100%;
}

.tree ul li .item-text .check-box {
  width: 100%;
  position: absolute;
  right: 0;
}

.mask {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
  background-color: rgba(0, 0, 0, 0.5);
}
</style>

2.引入组件

<uni-forms-item label="班级列表" name="names" :labelWidth='85'>
					<view style="margin-top: 15rpx;" @click="isShows">
						<text v-if="name.length==0 ">点击选择班级</text>
						<text v-else v-for="it in name">{{it}}</text>
						<!-- {{name.length>0 ? name : '点击选择班级'}} -->
					</view>                         
                                                    
//treeData:数据
//children:分类级别
  <mwTreePicker ref="tree" :show="isShow" :data="treeData" title="选择班级" label="name" children="banjilist" @submit="submit" @cancel="isShow=false" /> </uni-forms-item>

  

	import mwTreePicker from "@/components/mw-tree-picker/mw-tree-picker.vue"
	export default {
		components: {
			mwTreePicker
		},

  

            submit(data) {

                this.name = data.checkedData.map(function(item) {

                    return item.name
                })

                this.formData.banji_ids = data.checkedData.map(function(item) {
                    return item.id
                })
                // this.treeData = data.datasource
                this.isShow = false
                this.Xunaze = data.checkedData


            },
        isShows() {
                this.isShow = true
                // const arr = this.Xunaze.map(item => {
                //     if (item.banji_id) {
                //         item.id = item.banji_id
                //         item.name = item.banji
                //     }
                //     return item
                // })
                // console.log(arr, '你相信吗');
                this.$refs.tree.checkData(this.Xunaze, 'id')
            },

 

标签:index,const,树状,选择,item,datasource,组件,data,check
From: https://www.cnblogs.com/bshit/p/17645619.html

相关文章

  • 4 CSS属性选择器
    4属性选择器属性选择器是通过元素的属性及属性值来选择元素的。下面介绍属性选择器的用法。第一种用法作用:选择含有指定属性的元素。语法:[属性名]{}示例如下:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>属性选择器</title><s......
  • [记录一下]lazarus DBGrid Datetime类型时下拉选择日期
    默认的lazarusDBGrid选择Datetime类型时是没有下拉选择日期的,按以下方法就能实现下拉选择日期。在界面放一个DBDateTimePicker控件,并设置控件的Visibler为false,在DBGrid的DBGrid1SelectEditor添加下面的代码就可以。procedureTForm1.DBGrid1SelectEditor(Sender:TObject;Co......
  • 选择排序
    排序#include<iostream>#include<algorithm>usingnamespacestd;inta[10010];intmain(){ intn; cin>>n; for(inti=1;i<=n;i++) { cin>>a[i]; } //使用选择排序进行排序 for(inti=1;i<=n;++i) { for(int......
  • Prim算法是一种用于解决最小生成树问题的贪心算法。它通过逐步选择边来构建最小生成树
    importjava.util.*;classPrimAlgorithm{privatestaticfinalintINF=Integer.MAX_VALUE;publicvoidprimMST(int[][]graph){intvertices=graph.length;int[]parent=newint[vertices];//用于存储最小生成树的父节点int......
  • Kruskal算法是一种用于寻找图的最小生成树的贪心算法。它通过按照边的权重递增的顺序
    Kruskal算法可以通过生活中的例子来解释。我们可以将城市之间的道路网络看作是一个图,每个城市是一个顶点,道路是连接城市的边,而道路的长度可以看作是边的权重。假设我们想要修建一条连接所有城市的最小成本道路网络。首先,我们需要找到连接城市的所有道路,并按照道路的长度进行排......
  • 加速比计算+一致性新的O状态+block大小对cache的影响+BBM和写时复制+伪汇编和嵌入+汉
    加速比计算100个处理器对于程序的并发而言,是100倍的加速。对于程序的顺序执行而言,是1倍的速度。对于该题目,首先明确90倍的加速意味着什么:原始程序量为1,原始执行时间为1,现在加速了90倍,而程序本身不变,则:原始的程序量为1,现在的执行时间是1/90。现在假设x为并行执行的比例,则程序......
  • AWS的组件及组合
    kafka或kinesis做数据收集S3+redshift做数仓EMR做计算RDS做数据市场AWSGlue/AWSDataPipeline做数据集成这些组件配合起来,几乎可以做各种方式的数据分析kinesis还是比较推荐,延迟时间可以配置的算是实时的,而且功能会多一点,聚合、过滤什么的都可以......
  • 创业公司如何选择管理系统?
    对于创业公司,既要控制成本,又需要简化管理,更需要一套高效且多功能整合的管理软件,来对企业运行中的数据、流程和信息沟通进行综合性管理。为应付随时可能出现的需求变化和扩展,软件的自定义能力和扩展性显得尤为重要。选择适合创业公司的管理软件可以帮助提高工作效率、组织协调和......
  • 电脑技巧:电脑关机、休眠、睡眠之间如何选择,看完你就懂了!
    电脑是选关机、休眠、还是睡眠好呢?关机、休眠、睡眠的区别?1.关机关机想必是是大家最熟悉的方法了吧。关机的时候,系统首先会关闭所有运行中的程序,然后再关闭系统后台的服务。随后,系统再向主板请求关机,主板断开电源的供电,让电源切断对绝大多数设备的供电(只剩下一些内部零件仍会维持电......
  • 为什么 Java 坚持多线程不选择协程?
    1.引言在编程的世界里,多线程和协程是两种主要的并发处理方法。Java,作为一种广泛使用的编程语言,从其早期版本开始就深入支持多线程。那么,为什么Java坚持使用多线程而不是协程?要理解这个问题,我们需要深入探讨两者之间的差异以及Java的设计哲学。2.多线程和协程的基本差异多线程:线程......