前言
我们本篇文章带大家一起完成一次vue的组件化开发。在阅读本篇文章前还请阅读
vue入门1.0 和 vue入门2.0,看完之后再看本篇文章,相信对vue的理解一定会更上一层楼!
什么是组件化开发
Vue 的组件化开发是一种软件工程实践,它将应用程序分解为多个独立的、可重用的组件,每个组件封装了自己的模板(HTML)、逻辑(JavaScript)和样式(CSS)。这种方法不仅有助于代码的组织和维护,还能够提高开发效率和代码的可读性。
1. 什么是组件?
在 Vue 中,组件是一个拥有预定义选项的 Vue 实例。组件可以包含以下部分:
- 模板(Template):定义组件的 HTML 结构。
- 脚本(Script):定义组件的逻辑,如数据、方法和生命周期钩子。
- 样式(Style):定义组件的样式。
2. 为什么使用组件化开发?
- 复用性:组件可以在多个地方重复使用,减少代码重复。
- 模块化:将复杂的应用划分为小块,使代码更容易理解和维护。
- 独立性:组件之间相对独立,修改一个组件不会影响其他组件,降低了出错的风险。
- 可测试性:组件可以单独测试,提高了代码的可测试性和稳定性。
准备工作
我们先给大家看一下我们这次的完成效果
我们这次要完成两个页面一个是购物车,一个是todos,当然页面是以我们手动点击来切换的。
建立目录
因为我们是做vue的组件化开发,因此我们在src的下一级建立components文件夹,里面存放我们的两大页面。
<template>
<div class="app">
<button class="btn" @click="changeTab(1)">购物车</button>
<button class="btn" @click="changeTab(2)">todos</button>
<!-- shopping -->
<Shopping v-if="tabIndex === 1"></Shopping>
<!-- todos -->
<Todos v-else></Todos>
</div>
</template>
<script setup>
import { ref } from 'vue'
import Shopping from './components/Shopping.vue'
import Todos from './components/Todos.vue'
let tabIndex = ref(1)
const changeTab = (index) => {
// console.log(index);
tabIndex.value = index
}
</script>
<style lang="css" scoped>
.app{
text-align: center;
}
.btn{
font-size: 20px;
width: 100px;
height: 40px;
margin: 20px;
}
</style>
这段代码是一个基于 Vue 3 的组件,它包含了两个按钮和两个子组件 Shopping 和 Todos。当点击按钮时,会根据按钮的索引值来切换显示不同的子组件。
在 <template> 部分,定义了两个按钮,分别绑定了点击事件 changeTab(1) 和 changeTab(2),用来切换显示不同的子组件。
在 <script setup> 部分,使用了 Composition API 中的 ref 来创建了名为 tabIndex 的响应式数据,并定义了 changeTab 方法,用于改变 tabIndex 的值,从而控制显示的子组件。
在 <style> 部分,定义了组件的样式,其中使用了 scoped 关键字,表示这些样式只对当前组件有效。
我们的App.vue直接引入这两个我们写的vue项目,然后直接放在我们的html中,我们该如何去控制两个页面只显示一个呢?这就要用到我们的v-if了,配合v-else使用,最后看判断逻辑。我们首先将tabIndex设置为1,然后给;购物车和todos按钮绑定点击事件,我们可以绑定相同的事件然后后面接一个参数,这样我们点击购物车tabindex就变成1,点击todostabindex就变成2,也就达到了我们想要的显示效果。然后我们写一些简单的css去进行修饰。
这是我们组件化开发的第一步,也是很重要的一步!
Shopping
<div class="shopping">
<table>
<thead>
<th>序号</th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操作</th>
</thead>
<tbody>
<tr v-for="(book, index) in books">
<td>{{index + 1}}</td>
<td>{{book.name}}</td>
<td>{{book.date}}</td>
<td>{{book.price}}</td>
<td>{{book.count}}</td>
<td>
<button :disabled="book.count <= 0" @click="decrementCount(index)">-</button>
<span class="counter">{{book.count}}</span>
<button @click="addCount(index)">+</button>
</td>
</tr>
</tbody>
</table>
<h3>总价格:{{totalPrice}}</h3>
</div>
在模板中,使用了一个表格来展示书籍的信息,包括序号、书籍名称、出版日期、价格、购买数量和操作按钮。
在 v-for="(book, index) in books" 中对 books 数组进行遍历,然后将书籍的信息逐一展示在表格的每一行中。通过 {{index + 1}} 可以显示书籍的序号,而 {{book.name}}、{{book.date}}、{{book.price}} 和 {{book.count}} 则分别显示了书籍的名称、出版日期、价格和购买数量。
在操作列中,每一行都有两个按钮,一个用于减少购买数量,另一个用于增加购买数量。通过 @click="decrementCount(index)" 和 @click="addCount(index)" 来绑定点击事件,当点击对应的按钮时,会触发相应的方法来增加或减少书籍的购买数量。
最后,使用 {{totalPrice}} 来显示所有书籍的总价格。
我们首先看html部分,我们可以发现主要由2部分组成,table表和总价格。我们的表里面有六列,然后后序的步骤我们结合后面的js一起讲。
<script setup>
import { reactive, computed } from "vue";
const books = reactive(书籍信息数组)
const totalPrice = computed(() => {
let total = 0
books.forEach(item => {
total += item.price * item.count
});
return total
})
const addCount = (index) => {
// console.log(index);
books[index].count++
}
const decrementCount = (index) => {
books[index].count--
}
</script>
这段代码是使用 Vue 3 的 <script setup> 语法编写的组件逻辑部分,它包括导入了 Vue 中的 reactive 和 computed 函数,并且利用这两个函数创建了一个响应式的 books 对象和一个计算属性 totalPrice。其中 books 存储了书籍的信息数组,而 totalPrice 用于计算所有书籍的总价格。另外还定义了两个函数 addCount 和 decrementCount,用于增加和减少某本书籍的购买数量。这样的设计能够让视图自动响应数据的变化,从而实现了一个简单的购物车功能。
我们首先引入我们需要的reactive构造可以响应的变量,然后computed用来返回值,这个js里头可有大学问!首先我们看我们的增加和删除函数,都是绑定在了html的按钮里面,当我们点击时,我们可以根据所传入的下标找到这本书,并且将数量加1或者减1。但是当减为0时,我们就要将其设置为禁止按钮,这里我们直接采用v-bind去绑定属性缩写为:进行数量的判断。
我们再来讲解我们的计算总数部分computed,我们去遍历books的每一项返回最终的count累加值。并将其赋值给totalprice。
我们还通过v-for来循环生成了我们的表格。
<style lang="css" scoped>
table {
margin: 0 auto;
border: 1px solid #e9e9e9;
border-collapse: collapse;
border-spacing: 0;
}
th,
td {
padding: 8px 16px;
border: 1px solid #e9e9e9;
}
.counter {
margin: 0 5px;
}
</style>
然后是我们一些简单的css修饰。
Todos
我们首先 npm i todomvc-app-css,引入好用的css库。
-
最外层的
<section>元素:<section class="todoapp">- 这是应用的根容器,包含了整个 Todo 应用的所有元素。
-
头部
<header>元素:<header class="header"> <h1>todos</h1> <input type="text" class="new-todo" placeholder="想干的事" @keyup.enter="addTodo"> </header>- 这里定义了应用的头部部分。
<h1>标签显示了应用的标题 "todos"。<input>输入框用于添加新的待办事项,@keyup.enter="addTodo"指令表示当用户按下回车键时,会调用addTodo方法(这个方法应该在组件的逻辑部分定义)。
-
主要内容
<section class="main">:<section class="main"> <input type="checkbox" class="toggle-all" id="toggle-all"> <label for="toggle-all">Mark all as complete</label>- 这里是主要的待办事项列表区域。
<input type="checkbox">复选框用于标记所有任务为完成状态。<label for="toggle-all">Mark all as complete</label>是复选框的标签。
-
待办事项列表
<ul>元素:<ul class="todo-list"> <li class="todo" v-for="todo in state.todos"> <div class="view"> <input type="checkbox" class="toggle" v-model="todo.completed"> <label>{{todo.title}}</label> <button class="destroy"></button> </div> </li> </ul>-
<ul class="todo-list">是一个无序列表,用于展示所有的待办事项。 -
使用了 Vue 的
v-for指令来遍历state.todos数组,并为每个待办事项创建一个<li>元素。state.todos应该是一个包含所有待办事项的数组对象,在组件的逻辑部分定义。
-
每个待办事项项包含:
- 一个复选框
<input type="checkbox" class="toggle" v-model="todo.completed">,通过v-model双向绑定到todo.completed属性,用于标记任务是否完成。 - 一个
<label>显示待办事项的标题{{todo.title}}。 - 一个删除按钮
<button class="destroy"></button>,用于删除该待办事项(具体的删除逻辑需要在组件的逻辑部分定义)。
- 一个复选框
-
-
导入
reactive函数:import { reactive } from 'vue'- 从 Vue 中导入
reactive函数,用于创建响应式状态对象。
- 从 Vue 中导入
-
定义
state对象:const state = reactive({ todos: [ { id: 1, title: '学习', completed: false }, { id: 2, title: '吃饭', completed: true }, ] })- 使用
reactive函数创建一个响应式对象state。 state对象包含一个todos数组,数组中有两个默认的待办事项对象,每个对象包含id、title和completed属性。
- 使用