目录
通过一个小项目进行复习Vue之前的内容,实现最终网页效果如下图所示:
整体组件布局思路
前期准备工作
简单项目文件架构图
App.vue
<template>
<div id="root">
<div class="todo-container">
<div class="todo-wrap">
<AddInputVue/>
<MyList/>
<MyFooter/>
</div>
</div>
</div>
</template>
<script>
import { reactive, toRefs } from 'vue';
import AddInputVue from './components/Header.vue'
import MyList from './components/List.vue'
import MyFooter from './components/Footer.vue'
export default {
components: { AddInputVue, MyList, MyFooter },
}
</script>
Header.vue子组件:
<template>
<div class="todo-header">
<input type="text"
placeholder="请输入你的任务名称,按回车键确认"
/>
</div>
</template>
<script>
export default{
}
</script>
Footer.vue子组件:
<template>
<div class="todo-footer" >
<label>
<input type="checkbox"
/>
</label>
<span>
<span>已完成xxxx</span> / 全部xxxx
</span>
<button class="btn btn-danger">清除已完成任务</button>
</div>
</template>
<script>
import {computed} from 'vue'
export default {
}
</script>
List.vue子组件:
<template>
<ul class="todo-main">
<Item/>
</ul>
</template>
<script>
import Item from './Item.vue'
export default {
components:{Item},
}
</script>
Item.vue子组件:
<template>
<li>
<label>
<input type="checkbox"/>
<span>xxxx</span>
</label>
<button>删除</button>
</li>
</template>
<script>
export default {
}
</script>
配套CSS样式
/* APP.vue */
body {
background: #fff;
}
.btn {
display: inline-block;
padding: 4px 12px;
margin-bottom: 0;
font-size: 14px;
line-height: 20px;
text-align: center;
vertical-align: middle;
cursor: pointer;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
border-radius: 4px;
}
.btn-danger {
color: #fff;
background-color: #da4f49;
border: 1px solid #bd362f;
}
.btn-danger:hover {
color: #fff;
background-color: #bd362f;
}
.btn:focus {
outline: none;
}
.todo-container {
width: 600px;
margin: 0 auto;
}
.todo-container .todo-wrap {
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
}
/* Header.vue*/
.todo-header input {
width: 560px;
height: 28px;
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
padding: 4px 7px;
}
.todo-header input:focus {
outline: none;
border-color: rgba(82, 168, 236, 0.8);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
}
/*Item.vue*/
button{
color: #fff;
background-color: #da4f49;
border: 1px solid #bd362f;
}
button:hover{
color: #fff;
background-color: #bd362f;
}
li {
list-style: none;
height: 36px;
line-height: 36px;
padding: 0 5px;
border-bottom: 1px solid #ddd;
}
li label {
float: left;
cursor: pointer;
}
li label li input {
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
li button {
float: right;
display: none;
margin-top: 3px;
}
li:before {
content: initial;
}
li:last-child {
border-bottom: none;
}
li:hover{
background: #ddd;
}
li:hover button{
display: block;
}
/*List.vue*/
.todo-main {
margin-left: 0;
border: 1px solid #ddd;
border-radius: 2px;
padding: 0px;
}
.todo-empty {
height: 40px;
line-height: 40px;
border: 1px solid #ddd;
border-radius: 2px;
padding-left: 5px;
margin-top: 10px;
}
/*Footer.vue*/
.todo-footer {
height: 40px;
line-height: 40px;
padding-left: 6px;
margin-top: 5px;
}
.todo-footer label {
display: inline-block;
margin-right: 20px;
cursor: pointer;
}
.todo-footer label input {
position: relative;
top: -1px;
vertical-align: middle;
margin-right: 5px;
}
.todo-footer button {
float: right;
margin-top: 5px;
}
/*感谢 技术宅拯救世界 提供CSS样式!*/
现在网页是一个静态页面还不能进行数据相关操作,一下将要进行逐一介绍各个功能的具体实现!
将数据渲染到浏览器界面
这里将数据使用数组的形式写在App.vue中方便后期的调用,将要渲染的数据从父组件发送到子组件中进行具体的显示!
App.vue中的具体代码:
接收数据List.vue
Item.vue进行展示具体的数据
网页显示效果
勾选改变属性数据
由于每一列事件前方含有一个复选框用来显示事件是否完成状态的判断,往往刚刚添加的事件还是未完成状态,通过具体勾选改变todos中的done属性值,由于这里todos数据存在于App.vue中,而勾选存在于Item.vue中,就涉及到Vue中组件之间通信问题,那么我们这里采用使用List.vue充当中间桥方法完成两个组件之间的通信,根据每条Item中的Id值进行遍历充当条件。
App.vue中添加根据Id进行遍历,完成将todos中的done完成取反操作
List.vue充当通信之间的中间桥进行传递数据
Item.vue中进行获取每一条任务的Id并交给App.vue在todos中更具Id进行遍历
此时当我们点击页面复选框按钮时,借助开发者工具就可以看到todos中的done值是否可以随之改变了
接收表单输入数据并渲染到界面
获取用户从表单中输入数据并添加到页面中进行显示,表单存在于Header.vue中,而数据存在于App.vue中,就涉及到了子组件向父组件直接传递数据并进行实时显示!
在Header.vue中完成数据的封装并传输给App.vue
在App.vue进行接收Header.vue传递的数据并添加到todos中
此时当我们向输入框按下回车就可以触发函数并进行渲染到具体页面,过过过啦!
向表单输入数据按下回车之前:
按下回车之后:
删除每一条数据
当我们点击Item.vue中的删除按钮时,页面自动去除要删除的数据部分。这里删除操作在Item.vue中进行获取要删除的数据Id并发送到App.vue中进行添加过滤方法进行从原数组数据中进行删除!
Item.vue点击删除按钮获取要删除的数据Id
List.vue充当通信的中间桥作用进行传递数据
App.vue根据要删除的Id进行数组过滤操作
此时当我们点击就可以轻松完成删除操作啦
点击删除按钮之前:
点击删除按钮之后:
统计条数以及勾选
此时页面下方还不能进行显示已完成的数据以及全部数据,由于todos本身就是一个数组,可以调用本身length方法进行统计获得全部数据再使用插值语法进行显示,已完成可以使用遍历todos数组根据done值为true进行通过就好啦。
统计数据部分
在App.vue中将todos数据发送到Footer.vue中
Footer.vue接收到todos数据进行按照需求进行统计数据
这样Footer.vue下方就就能显示具体条数啦
完成勾选部分
那么Footer.vue中的复选框主要作用在初始化时,当已完成数量与全部数量相等时,就默认自动勾选!当两者不相等时,点击复选框表示全选或者全不选事件!
在App.vue中完成将从Footer.vue中复选框中的check属性进行遍历赋值到todos中的done中,再将函数进行发送到Footer.vue中
Footer.vue中进行接收到App.vue中的函数将复选框的点击状态赋值到App.vue中的方法中就好啦
此时点击Footer.vue中的复选框就可以实现全选or全不选啦
删除所有已完成任务
点击清除已完成任务按钮时,当前页面所有勾选的事件就可以全部清除,我们知道完成的事件的数据done值为true而未完成的数据done值为false,就可以使用filter进行过滤done值为true剩下为false就是我们需要的数据啦!
App.vue中完成过滤操作并将函数发送到Footer.vue中
Footer.vue中进行接收函数并定义一个按钮点击事件进行触发操作
现在点击清除已完成任务按钮就可以清除所有已完成任务啦!
总结项目案例
1.组件化编码流程:
(1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。 (2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用: 一个组件在用:放在组件自身即可。 一些组件在用:放在他们共同的父组件上(状态提升)。 (3).实现交互:从绑定事件开始。
2.props适用于: (1).父组件 ==> 子组件 通信 (2).子组件 ==> 父组件 通信(要求父先给字一个函数)
3.使用v-model是要切记:v-model绑定的值不能是props传过来的值,因为props是不可修改的!