组件化开发模块
在 Vue 中,组件是作为开发的基本单位,所以在拿到 页面的Layout 和 设计稿 之后,最先需要思考的就是如何将设计转化为有效的组件结构和逻辑,这个页面有哪些结构(例如头部、主体内容区、侧边栏、底部等),有哪些组件是可以复用的,数据的来源与流向等等。
而最直观的就是将页面细化为组件树,例如:
组件化开发的优势:
- 提高代码复用性: 每个组件都是独立的部分,项目的哪里需要就直接搬过去使用即可。例如一个"幻灯片组件"可以在页面的多处使用。
- 增强维护性:每个组件都只负责自己的区域,不会对其他组件产生影响,并且方便定位维护。
- 高灵活性:可以快速调整布局或添加新特性,只需替换或新增相应组件即可。
- 样式隔离 :通过
scoped
CSS等功能,可以避免样式冲突,保持组件外观的一致性。
开发前期准备:
图中的组件树已经直观的拆分好了结构,只需要我们细化设计思路即可。毕竟图中只是粗略的给了个大概结构,我们不妨为其添加部分内部功能。
思路:
- 头部
- 添加少数菜单
- 主体内容区
- 添加评分组件
- 添加内容块
- 侧边栏
- 添加用户组件
项目结构如下:
bash
src/
├── components/
│ ├── AppHeader.vue # 头部
│ ├── AppMain.vue # 主体内容区
│ ├── AppAside.vue # 侧边栏
│ ├── Item.vue # 内容块组件
│ ├── Rate.vue # 评分组件
│ └── User.vue # 用户组件
└── App.vue # 根组件
环境搭建:
-
初始化一个新的Vite项目,在命令行中输入以下内容,执行后输入项目名称
bashnpm init vite
-
选择开发所需的框架Vue,使用键盘右下角的方向键即可选择
-
选择使用的变体JavaScript
-
安装依赖项并启动项目
bash
npm i
npm run dev
在终端中会显示访问地址
实战:
App.vue:
html
<script setup>
import AppHeader from './components/AppHeader.vue'
import AppMain from './components/AppMain.vue'
import AppAside from './components/AppAside.vue'
</script>
<template>
<div class="container">
<AppHeader />
<div class="flx">
<AppMain />
<AppAside />
</div>
</div>
</template>
<style scoped>
.flx {
display: flex;
}
</style>
分析:
- 在根组件中添加
<AppHeader>
、<AppMain>
、<AppAside>
三个子组件。 - 通过
display: flex;
将<AppMain>
、<AppAside>
以弹性盒子的方式排列。
AppHeader.vue:
html
<template>
<header>
<nav>
<ul>
<li>菜单一</li>
<li>菜单二</li>
<li>菜单三</li>
</ul>
</nav>
</header>
</template>
<script setup>
</script>
<style scoped>
header {
height: 100px;
background-color: lightcyan;
}
</style>
分析:
- 在
<header>
内部添加HTML语义化的<nav>
标签用于定义导航链接。 - 在
<nav>
标签内添加菜单选项。
AppMain.vue:
html
<template>
<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'
// 将数据 从父组件 传递给 子组件
const score = ref(3)
</script>
<style scoped>
main {
flex: 1;
height: 500px;
background-color: yellow;
}
</style>
分析:
- 由于需要体现评分,故将数据通过文本插值(
{{ }}
)绑定到模板中。 - 添加了子组件
<Rate>
、<Item>
。 - 通过组合式API
ref
创建了响应式数据score
。 - 通过
:value="score"
将父组件中的score
数据传递给子组件<Rate>
。
Rate.vue:
html
<template>
<div>
{{ rate }}
{{ props.value }}
</div>
</template>
<script setup>
import { defineProps, computed } from 'vue'
let props = defineProps({
value: Number
})
let rate = computed(() => "★★★★★☆☆☆☆☆".slice(5 - props.value, 10 - props.value))
</script>
<style scoped>
</style>
分析:
- 导入API
defineProps
用于定义和接收父组件传递的属性(props)。 - 导入API
computed
用于创建计算属性,当依赖的数据发生变化时自动更新。 - 使用
slice
方法来根据props.value
(评分)的值截取相应的部分。例如,父组件传递的数据为3
,则截取(5-3,10-3)的部分即:"★★★☆☆"
。
由于我的Item.vue部分并无任何实质性的功能,只是展示有这个模块而已,所以此处就省略了。
AppAside.vue:
html
<template>
<aside class="flx">
<User />
<User />
<User />
</aside>
</template>
<script setup>
import User from './User.vue'
</script>
<style scoped>
aside {
width: 200px;
height: 500px;
background-color: green;
}
</style>
分析:
- 添加了子组件
<User>
。
由于我的User.vue部分并无任何实质性的功能,只是展示有这个模块而已,所以此处就省略了。