有个移动端树形组件 我打算根据节点是否有children属性来条件渲染节点是否可被选择,有没有比较好的实现方法?

作者站长头像
站长
· 阅读数 7

有个移动端树形组件 我打算根据节点是否有children属性来条件渲染节点是否可被选择,有没有比较好的实现方法? 图1

有个移动端树形组件 我打算根据节点是否有children属性来条件渲染节点是否可被选择,有没有比较好的实现方法? 图2

问题描述:如图1所示,当几个子节点同时渲染时,有的节点由于children是空的,那么该节点就是最后一级节点,就像图1中的李四 王五。有些节点children属性存在子元素,那么该节点是个部门,现在问题是 最后一级节点 李四 王五 不显示复选框,无法被选择只有点击部门节点后才会显示复选框 如图2

应该是判断节点的函数有问题,只要检测到同级节点存在子元素就break了

贴下代码

    <div class="list" :class="{ 'p-b-75 ': isFixed }">
      <div class="row" v-for="(item, index) in data" :key="index" @click="rowHandler(item)">
        <span class="label">{{ item.label }}</span>
        <span class="total" v-if="isNum && !isLast">{{ item.total }} {{ unit }}</span>
        <input v-if="isCheckbox && isLast" class="total" type="checkbox" name="checkbox" :checked="checked(item.label)"
          :value="item[checkboxKey]" />
      </div>
    </div>


      /** 判断当前数据是否是最后一组,如果children都是空数组则表示最后一级 */
      lastHandler() {
        //每次用户点击菜单项时 data都会被重新赋值 所以data表示的是当前数据
        for (let i = 0; i < this.data.length; i++) {
          console.log(this.data, 'data')
          const child = this.data[i]
          if (child['children'] && child.children.length === 0) {
            this.isLast = true
          } else {
            this.isLast = false
          }
          break
        }
      },

父组件传入的数据如下所示

  const tree = ref([
    {
      label: '集团总部',
      total: 20,
      children: [
        {
          label: '集团党委',
          total: 5,
          children: [
            {
              label: '信息部',
              total: 1,
              children: [{
                label: '张三',
                children: []
              }],
            },
            {
              label: '李四',
              children: [],
            },
            {
              label: '王五',
              children: [],
            },
          ],
        },
      ],
    },
  ],
  )
回复
1个回答
avatar
test
2024-06-30

根本原因还是出在数据上

//这是人员的数据解构
{
  label: '王五',
  children: [],
}
//如果将部门的total删掉,再把子级清空,跟人员就没区别了

{
  label: '信息部',
  children: [],
}

再看看lasthandler的这部分,当前页面的所有数据是否为最后一级都是用一个isLast控制的

for (let i = 0; i < this.data.length; i++) {
  console.log(this.data, 'data')
  const child = this.data[i]
  // 第一次循环进来,第一条是信息部的,它的children数组长度是大于0的,所以执行else
  if (child['children'] && child.children.length === 0) {
    this.isLast = true
  } else {
    this.isLast = false
  }
  // 将isLast赋值为false后直接break了
  break
}
// 总结一下就是,你只用第一条数据做是否为最后一级的判断,且将该判断结果应用在了当前页的所有数据上

修改方法

// js
// 既然都循环判断了,干脆将每一行数据的判断结果都塞到原数据里面
// html上的 isLast都改成item.isLast就行了
this.data = this.data.map(item=>{
    const isLast = Reflect.has('children') && item.children.length === 0
    return {
        ...item,
        isLast
    }
})

最后提一嘴开头说到的数据问题,靠children是否为空数组判断不靠谱,因为有时候可能添加了部门但没有人的时候,这里前端就会认为是人员。最好的办法就是作出区分,加个type都行,部门还是人员还是明确点好

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容