vue3 树型视图,利用自定义SFC来定义一个TreeItem,然后进行渲染出一个树形。

1、我们在各种项目中都会碰到树形的视图,所以说这个还是很重要的。

2、项目中我们一般会用现成的组件(ant-design、element)来处理,这里我们使用自定义的方法,提供一个data来处理,比如这样:

最后喧染出来的效果类似如下:

3、定义一个自定义SFC,TreeItem.vue

<script setup>
import { ref, computed } from 'vue'

const props = defineProps({
  model: Object
})

const isOpen = ref(false)
const isFolder = computed(() => {
  return props.model.children && props.model.children.length
})

function toggle() {
  isOpen.value = !isOpen.value
}

function changeType() {
  if (!isFolder.value) {
    props.model.children = []
    addChild()
    isOpen.value = true
  }
}

function addChild() {
  props.model.children.push({ name: 'new stuff' })
}
</script>

<template>
  <li>
    <div
      :class="{ bold: isFolder }"
      @click="toggle"
      @dblclick="changeType">
      {
   
   { model.name }}
      <span v-if="isFolder">[{
   
   { isOpen ? '-' : '+' }}]</span>
    </div>
    <ul v-show="isOpen" v-if="isFolder">
      <!--
        一个可以通过其“name”选项递归渲染自己的组件,
        (如果使用单文件组件,则从文件名推断)
      -->
      <TreeItem
        class="item"
        v-for="model in model.children"
        :model="model">
      </TreeItem>
      <li class="add" @click="addChild">+</li>
    </ul>
  </li>
</template>

说明

isFolder: 是一个计算型的属性,如果model的children不为空,并且这个children的length是大于0的,那么就会变成一个目录的形式,就是说下面有子项目。

isOpen:点击的时候,会切换isOpen的状态,对应的是template中的样式的变化,及“-”,“+”的变化,这样我们看上去就是展开的树形,或者是收缩状态的树形。

+:每一项的TreeItem的最后有一个+号,这样可以点击以后,在+号同级加入一项new stuff项。

ul:通过isOpen+isFolder来进行判断要不要显示子项目,如果都成立,那么就是利用自己TreeItem去递归出所有的子项目,并且如果还有,那么会直接children都显示完成。

这样就是我们使用子组件的优势了。

4、最后,我们建一个App.vue文件,来传递数据给TreeItem:

<!--
一个可以递归渲染自己的嵌套树组件。
你可以双击一个项目将其转变为一个文件夹。
-->

<script setup>
import { ref } from 'vue'
import TreeItem from './TreeItem.vue'

const treeData = ref({
  name: 'My Tree',
  children: [
    { name: 'hello' },
    { name: 'world' },
    {
      name: 'child folder',
      children: [
        {
          name: 'child folder',
          children: [{ name: 'hello' }, { name: 'world' }]
        },
        { name: 'hello' },
        { name: 'world' },
        {
          name: 'child folder',
          children: [{ name: 'hello' }, { name: 'world' }]
        }
      ]
    }
  ]
})
</script>

<template>
  <ul>
    <TreeItem class="item" :model="treeData"></TreeItem>
  </ul>
</template>

<style>
.item {
  cursor: pointer;
  line-height: 1.5;
}
.bold {
  font-weight: bold;
}
</style>

只要将属性model赋值,就可以达到树形的效果。

5、官方地址:https://cn.vuejs.org/examples/#tree

有兴趣可以自己尝试下,我想会有更大的收获。

猜你喜欢

转载自blog.csdn.net/jwbabc/article/details/143227158