vue3 + ts递归组件 初尝

1、背景:

由于之前,做小程序的时候,需要用到树状菜单显示,但是又没有原生小程序好像是没有相关组件的,当时是网上找了一个组件暂时使用着,现在想起了,觉得有必要自己写一下,于是就开始尝试一下

2、效果

 

3、代码

app.vue代码

<template>
  <div class="app">
    <div class="app-menu">
      <TreeMenu :data="state.data" :depth="0" :active-ids="['1']" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive } from "vue";
import TreeMenu from "./components/TreeMenu.vue";
const state = reactive({
  data: [
    {
      id: "1",
      title: "菜单1",
      children: [
        {
          id: "1-1",
          title: "菜单1-1",
          children: [
            { id: "1-1-1", title: "菜单1-1-1" },
            { id: "1-1-2", title: "菜单1-1-2" },
            { id: "1-1-3", title: "菜单1-1-3" },
          ],
        },
        { id: "1-2", title: "菜单1-2" },
        { id: "1-3", title: "菜单1-3" },
      ],
    },
    {
      id: "2",
      title: "菜单2",
      children: [
        {
          id: "2-1",
          title: "菜单2-1",
          children: [
            { id: "2-1-1", title: "菜单2-1-1" },
            { id: "2-1-2", title: "菜单2-1-2" },
            { id: "2-1-3", title: "菜单2-1-3" },
          ],
        },
        { id: "2-2", title: "菜单2-2", children: [] },
        { id: "2-3", title: "菜单2-3" },
      ],
    },
    {
      id: "3",
      title: "菜单3",
      children: [
        {
          id: "3-1",
          title: "菜单3-1",
          children: [
            { id: "3-1-1", title: "菜单3-1-1" },
            { id: "3-1-2", title: "菜单3-1-2" },
            { id: "3-1-3", title: "菜单3-1-3" },
          ],
        },
        { id: "3-2", title: "菜单3-2" },
        { id: "3-3", title: "菜单3-3" },
      ],
    },
  ],
});
</script>

<style scoped lang="scss">
.app-menu {
  width: 200px;
  min-height: 500px;
  background: #f4f4f4;
}
</style>

菜单组件代码

<template>
  <div class="menu">
    <div class="menu-container" v-for="item in state.data" :key="item.id">
      <!-- 显示的标题 -->
      <div
        class="title"
        :class="{ active: state.activeIds[props.depth] === item.id }"
        @click="activeEvent(item.id)"
      >
        {{ item.title }}
      </div>
      <!-- children属性存在才渲染 -->
      <template v-if="item.children?.length > 0">
        <!-- 激活项是当前项才显示其子菜单 -->
        <TreeMenu
          :data="item.children"
          v-show="state.activeId === item.id"
          :active-ids="state.activeIds"
          :depth="props.depth + 1"
        />
      </template>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { reactive } from "vue";
import TreeMenu from "@/components/TreeMenu.vue";
// 接收父组件传过来的数据
const props = defineProps<{
  data: any;
  activeIds: Array<string>;
  depth: number;
}>();
// 将数据保存到本地
const state = reactive({
  data: props.data,
  activeId: "",
  activeIds: props.activeIds,
});

// 激活项改变
const activeEvent = (val: string) => {
  state.activeId = val;
  // 修改对应层级的激活id
  state.activeIds[props.depth] = val;
  // 把当前层级的下一级的激活id去掉,不然当前层级改变后,在返回改变之前的id,其子层级激活的id还在
  state.activeIds.forEach((item, index, arr) => {
    if (index > props.depth) {
      arr[index] = "";
    }
  });
  console.log(state.activeIds);
};
</script>

<style scoped lang="scss">
.menu {
  width: 200px;
  overflow: hidden;
  background: #f4f4f4;
  color: #333;
  .menu-container {
    width: 100%;
    padding-left: 10px;
    box-sizing: border-box;
    .title {
      padding-left: 10px;
      box-sizing: border-box;
      height: 40px;
      line-height: 40px;
      &:hover {
        cursor: pointer;
        background: rgba(0, 0, 0, 0.8);
        color: #fff;
      }
    }
    .active {
      color: #e4393c !important;
    }
  }
}
</style>

初次尝试写的递归组件,欢迎指教!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue3是一种流行的JavaScript框架,而TypeScript是一种类型安全的JavaScript超集。结合使用Vue3和TypeScript可以提供更好的开发体验和代码可维护性。 在Vue3中,可以使用TypeScript来编写组件。下面是一个简单的Vue3+TypeScript评论组件的示例: ```typescript <template> <div> <h2>评论列表</h2> <ul> <li v-for="comment in comments" :key="comment.id"> {{ comment.text }} </li> </ul> <form @submit.prevent="addComment"> <input type="text" v-model="newComment" placeholder="请输入评论" /> <button type="submit">添加评论</button> </form> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue'; interface Comment { id: number; text: string; } export default defineComponent({ name: 'CommentComponent', data() { return { comments: [] as Comment[], newComment: '', }; }, methods: { addComment() { const newId = this.comments.length + 1; this.comments.push({ id: newId, text: this.newComment }); this.newComment = ''; }, }, }); </script> ``` 在上面的示例中,我们定义了一个名为`CommentComponent`的Vue组件组件包含一个评论列表和一个表单用于添加新的评论。`comments`数组用于存储评论数据,`newComment`变量用于绑定输入框的值。 通过使用`defineComponent`函数和`ref`函数,我们可以定义组件的数据和方法,并将其导出供其他组件使用。 相关问题: 1. Vue3是什么? 2. TypeScript在Vue3中的作用是什么? 3. 请解释一下Vue3+TypeScript评论组件的代码逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZL随心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值