Vue3 封装Tree树形组件,且只支持单选

App.vue



<script setup>
import HelloWorld from './components/HelloWorld.vue'
import Tree from './components/Tree.vue'
import Panel from './components/Panel.vue'

import { provide, ref} from 'vue'
function isExceedThirtydays(value) {
  console.log(new Date(value).getTime());
  let timetamp = (new Date().getTime() - new Date(value).getTime()) >= 30 * 24 * 60 * 60 * 1000
  return timetamp
}
console.log(isExceedThirtydays("2023-12-17 09:46:56"));

const list = ref([
  {
    id:1,
    parentId:null,
    name:'qwerqwe',
  },
  {
    id:12,
    parentId:1,
    name:'qweradsfa',
  },
  {
    id:13,
    parentId:1,
    name:'wuliheadsfasdfihei',
  },
  {
    id:2,
    parentId:null,
    name:'技术部',
  },
  {
    id:21,
    parentId:2,
    name:'前端部门',
  },
  {
    id:22,
    parentId:2,
    name:'前端部门',
  },
  {
    id:222,
    parentId:22,
    name:'前端一级',
  },
  {
    id:223,
    parentId:22,
    name:'前端2级',
  },
  {
    id:224,
    parentId:22,
    name:'前端3级',
  },
])


function deepToTree(data,parentId){
  if(data.length > 0){
    return data.filter(item => item.parentId === parentId).map(item => {
      item.checked = false
      item.children = deepToTree(data,item.id)
      if(item.children.length){
        item.isClick = false
      }else {
        item.isClick = true
      }
      return item
    })
  }else{
    return []
  }
}
function changeTreeData(list,selectedId){
  if(list.length > 0){
    list.forEach(item => {
      if(item.id ===selectedId){
        item.checked = true
      }else {
        item.checked = false
      }
      if(item.children.length > 0){
        changeTreeData(item.children,selectedId)
      }
    });
  }
}
function changeSelectedRadio(item){
  changeTreeData(data.value,item.id)
  console.log(data.value,'xxxx');
}
provide('changeSelectedRadio',changeSelectedRadio)
const data =ref(deepToTree(list.value,null))
</script>

<template>
  <Tree :list="data"></Tree>
</template>

<style scoped>

</style>

Tree.vue


<template>
    <div class="containerz" v-if="list.length > 0" v-for="(item,index) in list" :key="item.id">
        <input type="checkbox" @click="change(item)" :checked="item.checked" :disabled="!item.isClick">{{item.name}}
        <div class="child" v-if="item.children.length > 0">
            <Tree :list="item.children"></Tree>
        </div>
    </div>
</template>
  
<script lang="ts" setup>
import { PropType, ref, watch, computed,inject } from 'vue'
const props = defineProps({
    list:{
        type:Array<any>,
        default:()=>[]
    }
})
const change= inject('changeSelectedRadio')
</script>
  
<style scoped lang="scss">
.containerz {
    text-align: start;
    .child {
        margin-left: 10px;
    }
}
   /* 未选中状态 */
//    input[type="checkbox"]:not(:checked) {
//       /* 添加灰色样式 */
//       filter: grayscale(100%);
//       /* 设置不可点击 */
//       pointer-events: none;
//     }

</style>
  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的示例,演示如何使用 Vue3 封装一个树形组件: ``` <template> <ul> <li v-for="item in treeData" :key="item.id"> <span @click="toggle(item.id)"> {{ item.label }} <i v-if="item.children && item.children.length" :class="{'fa-chevron-down': !item.showChildren, 'fa-chevron-up': item.showChildren}"></i> </span> <Tree :tree-data="item.children" v-if="item.showChildren" /> </li> </ul> </template> <script> import { ref, watch } from 'vue'; export default { name: 'Tree', props: { treeData: { type: Array, required: true } }, setup(props) { // 使用 ref 来追踪当前节点是否展开 const treeNodes = ref([]); watch(() => props.treeData, () => { // 在每次更新 props 时更新 ref 的值 treeNodes.value = props.treeData.map(item => ({ ...item, showChildren: false })); }, { deep: true }); const toggle = (id) => { // 切换当前节点的展开状态 treeNodes.value = treeNodes.value.map(item => { if (item.id === id) { return { ...item, showChildren: !item.showChildren }; } else { return item; } }); } return { treeNodes, toggle }; } } </script> <style> .fa-chevron-up:before { content: "\f077"; transform: rotate(45deg); } .fa-chevron-down:before { content: "\f078"; } </style> ``` 在这个示例中,我们使用了 setup 函数来处理数据和逻辑。首先,我们使用一个 ref 变量来存储每个节点的展开状态,并使用 watch 来监听 props.treeData 的变化,更新 ref 变量的值。然后,我们定义了一个 toggle 函数,用来切换当前节点的展开状态。最后,我们使用 v-for 来循环遍历树形数据,使用 v-if 来判断当前节点是否展开,并使用递归地方式来渲染嵌套的子组件。最终,我们在树形节点上添加了一个可点击的图标,来让用户方便地展开或收缩子节点。 当然,这只是一个简单的示例,你可以根据自己的需求来扩展和优化它。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值