Vue组件树:从设计到实现的全方位指南 🚀
组件化开发:Vue的核心思想
Vue 的核心思想之一就是组件化开发,而组件树(Component Tree)则是 Vue 应用的基础结构。组件化开发不仅能提高代码复用性,还能让项目结构更清晰,便于团队协作和维护。
页面组件化实战
组件化设计示例
如下图的页面,我们将页面组件化后得到右边的组件树:
结合上面的图,用组件化的思想设计出下面的页面结构:
一个实际的页面,将其组件化后得到了一棵包含多个组件的组件树。比如,一个常见的网页布局包含:
- 顶部的导航栏
- 侧边的侧边栏
- 主体内容区域
我们可以把这些部分分别抽象成 AppHeader
、AppAside
、AppMain
组件,再加上 AppAside
的子组件 User
,AppMain
的子组件 Item
。整个页面则由 App
组件来统筹管理这些子组件的组合与交互。
组件树结构
抽象为组件树,即下面的模式:
markdown
App
├── AppHeader
├── AppMain
│ ├── Item
│ └── Rate
└── AppAside
└── User
在 Vue DevTools 中应该呈现出这样的组件树结构:
详细设计思路
设计流程
-
静态页面设计阶段:
markdownApp ├── AppHeader ├── AppMain │ └── Item └── AppAside └── User
-
动态功能扩展阶段 :
在
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
文件中,我们首先导入了AppAside
、AppHeader
和AppMain
组件,以便在模板中使用它们。
模板布局
- 模板中使用
div
元素进行布局,外层的div
设置类为contaner
,内部AppHeader
独占一行,接着是一个类为flx
的div
,在这个弹性布局容器中,AppMain
和AppAside
并列排放,并且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
导入ref
、defineProps
、computed
。使用defineProps
定义value
属性,限制其类型为Number
,这个属性用于接收父组件(如AppMain
)传递过来的评分数据,是组件间通信的重要方式。
巧妙设计评分
ini
let rate = computed(()=>"★★★★★☆☆☆☆☆".slice(5 - props.value, 10 - props.value))
我的思路是 : 用一个长度为五颗星的尺子slice(5,10)置于"★★★★★☆☆☆☆☆"五颗空五角星上 , 之后在"★★★★★☆☆☆☆☆" 上移动 , 移动的距离是 : props.value
而props.value 是父组件 AppMain 传给子组件的值 , 通过 props 属性取出
组件通信总结
在这个示例中,我们展示了组件通信方式:
-
Props 向下传递:
AppMain
向Rate
传递初始评分AppAside
向User
传递用户数据
最佳实践建议
-
组件设计原则:
- 单一职责原则:每个组件只做一件事
- 高内聚低耦合:组件内部紧密相关,与外部关系简单
- 合理的 props 设计:明确类型和默认值
-
可维护性:
- 清晰的组件结构
- 良好的文档注释
- 一致的代码风格
总结
通过这个完整的示例,我们展示了如何:
- 将页面拆分为组件树
- 设计组件间的通信机制
- 实现响应式布局
- 创建可复用的组件
- 遵循 Vue 的最佳实践
组件化开发是 Vue 强大功能的基石,掌握组件树的设计和实现,能够显著提高开发效率和代码质量。