Ant-design 的 a-tree-select 使用

需求:需求

  1. 树形结构中的children 和 labels 需要同时展示在页面

    递归处理数据,将labels 合并进入children

  2. 展示labels时需要在前面加一个标记○

    // 需求1 需求2 
    /** 
     * @description 获取标签分类的树形结构
     */
    getData(data, dataIndex) {
      const list = data.map((item, index) => {
        if (item.children && item.children.length > 0) {
          item.children = item.children.map((child) => {
            return {
              ...child,
              type: 'children', // 添加标识符,判断是否为children/labels 给需求4使用
              label: child.name, // a-tree-select 中为选中子节点的内容和展示字节点内容做区分
            }
          })
          this.getData(item.children, dataIndex + '-' + index)
        } else {
          item.children = []
        }
        if (item.labels && item.labels.length > 0) {
          item.children = item.children
            .map((child) => {
              return {
                ...child,
                type: 'children',
                label: child.name,
              }
            })
            .concat(
              item.labels.map((label) => {
                return {
                  ...label,
                  type: 'label',
                  label: label.name,
                  name: `○ ${label.name}`, // 需求2
                }
              })
            )
        }
        return {
          ...item,
          label: item.name,
          key: dataIndex + '-' + index,
        }
      })
      return list
    },
    
  3. 选中label时需要去除标记

    注意事项:
    - 可以自定义下拉框中的title,展示icon,但是选中时,icon也会出现在输入框中,而且必须在treeData的每一项中加入scopedSlots:{title:‘custom’},使用时slot=‘custom’
    - 选中后输入框中显示值可以用 treeNodeLabelProp=“label” 进行显示设置,目前选项有 title/label/id/key,默认选项是title

	<a-tree-select
       v-model="searchParams.labelIds"
       tree-checkable
       :tree-data="treeData"
       :show-checked-strategy="SHOW_PARENT"
       :replaceFields="{
         title: 'name', //  == 下拉框显示值 ==
         children: 'children',
         value: 'id'
       }"
       search-placeholder="请选择"
       class="color-select"
       style="min-width: 400px"
       :dropdownStyle="{ width: '400px' }"
       :dropdownMatchSelectWidth="false"
       treeNodeLabelProp="label" // == 选中后输入框中显示值 ==
     >
     	<!-- 自定义下拉框中title的内容,配合treeData中加入scopedSlots -->
     	<!-- 
	     	<span  slot="custom" slot-scope="{key, value}">
	     		<a-icon type="close-circle"  />
		       {{value}}
		    </span>
	    -->
	    
	 </a-tree-select>
  1. 选中父节点时,需要将父节点中的labels全部过滤给后端

    新建一个 new Map(),接收一个 Id1:[labelId1, labelId2]…
    选中某个父节点时,直接在Map的get方法获取下面所有的labels

过滤得到的数据

	// 使用时的代码
	let labels = []
    this.searchParams.labelIds.forEach((item) => {
      if (this.treeDataValues.get(item)) {
        labels = labels.concat(this.treeDataValues.get(item))
      }
    })


	// 数据转化时的代码
	/**
     * @description 获取标签分类中子分类的id
     */
    getLabelIds(data) {
      const list = data
        .map((item) => {
          if (item.children && item.children.length > 0) {
          // 只需要存在 label 的父元素 id
            const val = item.children
              .map((child) => (child.type === 'label' ? child.id : null))
              .filter((i) => i)
              .concat(this.getLabelIds(item.children))
            // 过滤掉不存在labels
            if (val.length > 0) {
              if (!this.treeDataValues.has(item.id)) { // treeDataValues : new Map()
                this.treeDataValues.set(item.id, val.flat(Infinity)) // 使用es6的方法,将多维数组转化为一维数据, Infinity:代表不管有多少层都转化为一维数组
              }
              return val
              // { [item.id] : val }
            }
          }
        })
        .filter((i) => i)
      return list
    },

数据结构:

{
    "code":200,
    "traceId":"",
    "message":"成功",
    "data":[
        {
            "id":16,
            "name":"驾驶行为属性",
            "children":[
                {
                    "id":137,
                    "name":"guyufan_test1"
                },
                {
                    "id":148,
                    "name":"温油"
                }
            ],
            "labels":[
                {
                    "id":600024,
                    "name":"智能驾驶"
                },
                {
                    "id":600018,
                    "name":"test8"
                }
            ]
        },
        {
            "id":17,
            "name":"车主使用属性",
            "children":[
                {
                    "id":18,
                    "name":"地图产品",
                    "labels":[
                        {
                            "id":600006,
                            "name":"年龄"
                        },
                        {
                            "id":600005,
                            "name":"销售城市"
                        },
                        {
                            "id":600004,
                            "name":"性别"
                        }
                    ]
                },
                {
                    "id":19,
                    "name":"音乐产品",
                    "children":[
                        {
                            "id":20,
                            "name":"音乐产品行为偏好",
                            "labels":[
                                {
                                    "id":600000,
                                    "name":"用户30天内的驾驶习惯"
                                }
                            ]
                        },
                        {
                            "id":21,
                            "name":"音乐内容偏好",
                            "children":[
                                {
                                    "id":144,
                                    "name":"guyufan_test1"
                                }
                            ]
                        }
                    ]
                },
                {
                    "id":143,
                    "name":"guyufan_test1"
                }
            ]
        },
        {
            "id":15,
            "name":"车主核心属性",
            "children":[
                {
                    "id":117,
                    "name":"guyufan_test2"
                },
                {
                    "id":135,
                    "name":"guyufan_test1"
                },
                {
                    "id":153,
                    "name":"未命名子分类",
                    "children":[
                        {
                            "id":155,
                            "name":"未命名子分类1213"
                        }
                    ]
                }
            ]
        },
        {
            "id":126,
            "name":"guyufan_parent_test4",
            "labels":[
                {
                    "id":600023,
                    "name":"mark3"
                }
            ]
        },
        {
            "id":138,
            "name":"guyufan_parent_test5"
        },
        {
            "id":139,
            "name":"guyufan_parent_test"
        },
        {
            "id":142,
            "name":"guyufan_parent_test645"
        },
        {
            "id":150,
            "name":"未命名分类",
            "children":[
                {
                    "id":152,
                    "name":"未命名子分类"
                }
            ]
        },
        {
            "id":151,
            "name":"guyufan_parent_test6"
        },
        {
            "id":159,
            "name":"未命名分类111"
        }
    ]
}