抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

就这样吧

描述

假设服务器返回下列数据

const data = [
  { id: 1, name: '1', parent: null },
  { id: 2, name: '2', parent: 1 },
  { id: 3, name: '3', parent: 1 },
  { id: 4, name: '4', parent: 3 }
]

期望转成下列格式

[
  {id:1,name:'1',children:[
    {id:2,name:'2',children:[]},
    {id:3,name:'3',children:[
      {id:4,name:'4',children:[]}
    ]}
  ]}
]

并用 Vue 渲染出来

分析

数据转换可以用Map减少复杂度。

Vue用到了递归组件。

实现

Vue SFC Playground

<script setup>
// App.vue

import { ref, computed } from 'vue'

import TreeNode from './TreeNode.vue'

const dataFromServer = ref([
  { id: 1, name: '1', parent: null },
  { id: 2, name: '2', parent: 1 },
  { id: 3, name: '3', parent: 1 },
  { id: 4, name: '4', parent: 3 }
])

const dataTree = computed(() => {
  const data = dataFromServer.value.map(item => ({ ...item }))
  const m = new Map(data.map(({ id, name }) => [id, {
    id,
    name,
    children: []
  }]))
  const root = {
    id: null,
    name: 'null',
    children: []
  }

  m.set(null, root)

  for (let node of data) {
    if (m.has(node.parent)) {
      m.get(node.parent).children.push(m.get(node.id))
    }
    else {
      console.log('no parent node:', node)
    }
  }
  return root
})

</script>

<template>
  <TreeNode :node="childNode" v-for="childNode in dataTree.children" :key="childNode.id"></TreeNode>
</template>
<script setup>
// TreeNode.vue

import { ref } from 'vue'
const props = defineProps(['node'])
let expand = ref(true)
</script>

<template>
  <div style="padding-left:1em">
    <div @click="expand = !expand">name {{ props.node.name }} {{ expand ? '▼' : '▲' }}</div>
    <div v-if="expand">
      <TreeNode :node="childNode" v-for="childNode in props.node.children" :key="childNode.id"></TreeNode>
    </div>
  </div>
</template>

就写完了一个默认展开的树形组件啦。

name 1 ▼
  name 2 ▼
  name 3 ▼
    name 4 ▼

评论