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 强大功能的基石,掌握组件树的设计和实现,能够显著提高开发效率和代码质量。

相关推荐
runnerdancer3 小时前
LLM是怎么处理messages数组的,提示词缓存又是什么
前端·agent
陈随易4 小时前
VSCode的Copilot扩展支持接入DeepSeek,Kimi了!
前端·后端·程序员
我不是外星人5 小时前
有了 Harness Engineering ,真的还需要研发工程师吗?
前端·后端·ai编程
IT_陈寒8 小时前
JavaScript的闭包把我坑惨了,说好的内存会自动回收呢?
前端·人工智能·后端
Jackson__9 小时前
分享一个横向滚动案例,带悬停暂停,通用性很强
前端
MariaH9 小时前
git rebase的使用
前端
_柳青杨9 小时前
深入理解 JavaScript 事件循环
前端·javascript
阡陌Jony9 小时前
关于前端性能优化的一些问题:
前端
用户6000718191010 小时前
【翻译】简化 TSRX
前端
IT乐手11 小时前
佛德角逼平西班牙,国足还有啥借口?
前端