Vue组件树:从设计到实现的全方位指南 🚀

Vue组件树:从设计到实现的全方位指南 🚀

组件化开发:Vue的核心思想

Vue 的核心思想之一就是组件化开发,而组件树(Component Tree)则是 Vue 应用的基础结构。组件化开发不仅能提高代码复用性,还能让项目结构更清晰,便于团队协作和维护。

页面组件化实战

组件化设计示例

如下图的页面,我们将页面组件化后得到右边的组件树:

结合上面的图,用组件化的思想设计出下面的页面结构:

一个实际的页面,将其组件化后得到了一棵包含多个组件的组件树。比如,一个常见的网页布局包含:

  • 顶部的导航栏
  • 侧边的侧边栏
  • 主体内容区域

我们可以把这些部分分别抽象成 AppHeaderAppAsideAppMain 组件,再加上 AppAside 的子组件 UserAppMain 的子组件 Item。整个页面则由 App 组件来统筹管理这些子组件的组合与交互。

组件树结构

抽象为组件树,即下面的模式:

markdown 复制代码
App
├── AppHeader
├── AppMain
│   ├── Item
│   └── Rate
└── AppAside
    └── User

在 Vue DevTools 中应该呈现出这样的组件树结构:

详细设计思路

设计流程

  1. 静态页面设计阶段

    markdown 复制代码
    App
    ├── AppHeader
    ├── AppMain
    │   └── Item
    └── AppAside
        └── User
  2. 动态功能扩展阶段

    AppMain 中再设计 Rate 组件,采用父组件向子组件传递信息的方式:

    复制

    复制代码
    AppMain
    ├── Rate
    └── Item

代码实现详解

App

xml 复制代码
<script setup>
import AppAside from './components/AppAside.vue'
import AppHeader from './components/AppHeader.vue'
import AppMain from './components/AppMain.vue'

</script>

<template>
  <!-- LayOut -->
  <div class="contaner">
      <AppHeader/>
      <!--  布局 : 弹性 -->
      <div class="flx">
          <AppMain/>
          <AppAside/>
      </div>
  </div>
</template>

<style scoped>
.flx {
  display : flex;
}
</style>

导入相关组件

  • App.vue文件中,我们首先导入了AppAsideAppHeaderAppMain组件,以便在模板中使用它们。

模板布局


  • 模板中使用div元素进行布局,外层的div设置类为contaner,内部AppHeader独占一行,接着是一个类为flxdiv,在这个弹性布局容器中,AppMainAppAside并列排放,并且AppMain会占据剩余空间(通过flex: 1设置)。

AppHeader

xml 复制代码
<template>
     <Header>
        Header
    </Header>
</template>

<script setup>

</script>

<style  scoped>
header {
    height : 100px;
    background-color: #37372c;
}
</style>

模板内容

  • 模板非常简单,只有一个Header标签,用于显示页面头部的内容,比如网站的 logo、标题等。

样式设置

  • 样式中设置了背景颜色为#37372c,高度为 100px,给头部一个明确的视觉效果。

AppMain

在该组件里 , 父组件是 AppMain , 子组件是 Item

xml 复制代码
<template>
   <main>
    Main
    <Item/>
    <Item/>
   </main>
</template>

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

</script>

<style  scoped>
main {
   flex : 1;
   height: 500px;
   background-color: rgb(136, 111, 137);
}
</style>

Item

xml 复制代码
<template>
    <div>
        Item
    </div>
</template>

<script setup>

</script>

<style scoped>
div{
    height:100px;
    background-color: aquamarine;
    margin:10px;
}
</style>

模板展示

  • 模板中是一个简单的div标签,用于显示具体的项目内容,比如列表项、文章摘要等。

样式调整

  • 样式中设置div高度为 100px,背景颜色为aquamarine,外边距为 10px,使每个项目在页面上有一定的间隔和视觉区分。

AppAside

xml 复制代码
<template>
    <aside class = "flx">
        Aside
        <User/>
        <User/>
        <User/>
    </aside>
</template>

<script setup>
import User from './User.vue'
</script>

<style  scoped>
aside{
    width:200px;
    height:500px;
    background-color: rgb(109, 90, 54);
}
</style>

导入用户组件

  • 导入User组件,因为侧边栏可能会展示用户相关信息或其他导航链接等内容。

模板布局

  • 模板中是一个aside标签,内部包含三个User组件,使用在App组件中定义的flx类进行布局,使User组件在侧边栏中按一定方式排列。

User

xml 复制代码
<template>
    <div>
        User
    </div>
</template>

<script setup>

</script>


<!-- scoped css的作用域 -->
<style  scoped>
div{
    height:50px;
    width:50px;
    background-color: rgb(255, 127, 168);
    margin:5px;
}
</style>

模板内容

  • 模板中是一个div标签,用于显示用户相关的具体内容,比如用户头像、用户名等。

样式定义

  • 样式中设置div高度为 50px,宽度为 50px,背景颜色为rgb(255, 127, 168),外边距为 5px,用于展示用户信息的样式效果。

数据驱动

在 AppMain 模块下 , 我们添加一个打分的组件

xml 复制代码
<template>
   <main>
    Main
    <h1>你的评分是{{score}}</h1>
    <!-- 父子组件传递数据 -->
    <Rate :value="score"/>
    <Item/>
    <Item/>
   </main>
</template>

<script setup>
import Item from './Item.vue'
import Rate from './Rate.vue'
import {ref} from 'vue'
// 创建一个ref , 默认值为3
// 将数据从父组件传递给子组件 
const score = ref(3)
</script>

<style  scoped>
main {
   flex : 1;
   height: 500px;
   background-color: rgb(136, 111, 137);
}
</style>

Rate

xml 复制代码
<template>
    <div>
       {{rate}}
    </div>
</template>

<!-- vue 中script setup的作用:  -->
 <!-- 自动暴露组件的属性和方法。
 在 "script setup" 中定义的变量、函数等会自动暴露给模板使用,
 无需显式地通过return语句返回。 -->
<script setup>
import {ref,defineProps,computed} from 'vue'
//用于props业务消费数据 , 不是自身的数据 ,而是父组件绑定
//子组件和父组件不一定绑定的 , 哪里要用就往哪里绑定
let props = defineProps({
    //限制为Number类型
    value : Number
})
//组件自有的数据
let count =  ref(0)
let rate = computed(()=>"★★★★★☆☆☆☆☆".slice(5 - props.value, 10 - props.value))
</script>

<style scoped>

</style>
  • vue导入refdefinePropscomputed。使用defineProps定义value属性,限制其类型为Number,这个属性用于接收父组件(如AppMain)传递过来的评分数据,是组件间通信的重要方式。

巧妙设计评分

ini 复制代码
let rate = computed(()=>"★★★★★☆☆☆☆☆".slice(5 - props.value, 10 - props.value))

我的思路是 : 用一个长度为五颗星的尺子slice(5,10)置于"★★★★★☆☆☆☆☆"五颗空五角星上 , 之后在"★★★★★☆☆☆☆☆" 上移动 , 移动的距离是 : props.value

而props.value 是父组件 AppMain 传给子组件的值 , 通过 props 属性取出

组件通信总结

在这个示例中,我们展示了组件通信方式:

  1. Props 向下传递

    • AppMainRate 传递初始评分
    • AppAsideUser 传递用户数据

最佳实践建议

  1. 组件设计原则

    • 单一职责原则:每个组件只做一件事
    • 高内聚低耦合:组件内部紧密相关,与外部关系简单
    • 合理的 props 设计:明确类型和默认值
  2. 可维护性

    • 清晰的组件结构
    • 良好的文档注释
    • 一致的代码风格

总结

通过这个完整的示例,我们展示了如何:

  1. 将页面拆分为组件树
  2. 设计组件间的通信机制
  3. 实现响应式布局
  4. 创建可复用的组件
  5. 遵循 Vue 的最佳实践

组件化开发是 Vue 强大功能的基石,掌握组件树的设计和实现,能够显著提高开发效率和代码质量。

相关推荐
HelloRevit27 分钟前
React DndKit 实现类似slack 类别、频道拖动调整位置功能
前端·javascript·react.js
阿珊和她的猫39 分钟前
Webpack Dev Server的安装与配置:解决跨域问题
vue.js·webpack
ohMyGod_1231 小时前
用React实现一个秒杀倒计时组件
前端·javascript·react.js
eternal__day1 小时前
第三期:深入理解 Spring Web MVC [特殊字符](数据传参+ 特殊字符处理 + 编码问题解析)
java·前端·spring·java-ee·mvc
醋醋1 小时前
Vue2源码记录
前端·vue.js
艾克马斯奎普特1 小时前
Vue.js 3 渐进式实现之响应式系统——第四节:封装 track 和 trigger 函数
javascript·vue.js
敲代码的玉米C1 小时前
Vue Draggable 深入教程:从配置到实现的完整指南
vue.js
frontDeveloper1 小时前
Vue3基础使用概览
vue.js
江耳1 小时前
从10秒到无限流:我用Vercel+NextJS实现AI流式对话遇到的超时问题及解决方案
前端
总之就是非常可爱2 小时前
三分钟让你看懂alien-signals computed基本原理
前端