(1) 组件拆分:(1)静态模板 (2)动态模板 (3)数据交互
(2) 组件之间的通信,数值的确定,计算属性的应用,数组的方法
(3) 计算使用,数值的总和,双向数据绑定使用,你的数值变化时候,其他数值也发生变化
(4)本地存储使用
App.vue
<template>
<div class="todo-container">
<div class="todo-wrap">
<todo-header :todos="todos" :addItem="addItem"/>
<todo-list :todos="todos" :DeleteItem="DeleteItem"/>
<todo-footer :todos="todos" :deleteCompleteTodos="deleteCompleteTodos" :selectAll="selectAll"/>
</div>
</div>
</template>
<script>
import TodoFooter from "./components/TodoFooter";
import TodoHeader from "./components/TodoHeader";
import TodoList from "./components/TodoList";
export default {
//默认暴露一个模块
components:{
TodoFooter,
TodoHeader,
TodoList
},
methods:{
addItem(item){
this.todos.splice(0,0,item);
},
DeleteItem(index){
this.todos.splice(index,1);
},
deleteCompleteTodos(){
//删除todolist里面为true的,过滤
this.todos = this.todos.filter((todo)=> todo.complete===false )
},
selectAll(flag){
//所有的都为true表示选中,都为false也勾选,点击的时候勾选
this.todos.forEach((todo) => todo.complete=flag)
}
},
watch:{
todos: {
handler: function (val, oldVal) {
//存入到本地
window.localStorage.setItem("todos_key",JSON.stringify(val))
},
deep: true
}
},
data(){
return{
//页面加载的时候取出
todos:JSON.parse(window.localStorage.getItem("todos_key") ||"[]")
}
}
}
</script>
<style>
.todo-container {
width: 600px;
margin: 0 auto;
}
.todo-container .todo-wrap {
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
}
</style>
TodoHeader.vue
<template>
<div class="todo-header">
<input type="text" @keyup.enter="add" placeholder="请输入你的任务名称,按回车键确认" v-model="title" />
</div>
</template>
<script>
export default {
//默认暴露一个模块
props:{
todos:Array,
addItem:Function
},
data(){
return {
title:""
}
},
methods:{
add(){
//信息添加进去
const {title,addItem} = this;
const item = {
title,
complete:false
}
if(title.trim()){
addItem(item)
}
}
}
}
</script>
<style>
.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);
}
</style>
TodoList.vue
<template>
<ul class="todo-main">
<TodoItem v-for="(todo,index) in todos" :key="index" :todo="todo" :DeleteItem="DeleteItem" :index="index"/>
</ul>
</template>
<script>
import TodoItem from "./TodoItem"
export default {
//默认暴露一个模块
props:{
todos:Array,
DeleteItem:Function
},
components:{
TodoItem
}
}
</script>
<style>
.todo-main {
margin-left: 0px;
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;
}
</style>
TodoItem.vue
<template>
<li @mouseenter="EnterItem(true)" @mouseleave="EnterItem(false)" :style="{background:bgColor }">
<label>
<input type="checkbox" v-model="todo.complete"/>
<span>{{todo.title}}</span>
</label>
<button class="btn btn-danger" v-show="isShow" @click="deleteItem">删除</button>
</li>
</template>
<script>
export default {
//默认暴露一个模块
methods:{
EnterItem(isEnter){
if(isEnter){
//进入显示
this.isShow =true;
this.bgColor = "#aaa"
}else{
this.isShow =false;
this.bgColor = "white";
}
},
deleteItem(){
if(confirm("确认是否删除")){
const {index,DeleteItem} = this;
DeleteItem(index);
}
}
},
data(){
return{
isShow:false,
bgColor:"white"
}
},
props:{
todo:Object,
DeleteItem:Function,
index:Number
},
}
</script>
<style>
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;
}
</style>
TodoFooter.vue
<template>
<div class="todo-footer">
<label>
<input type="checkbox" v-model="checkAll"/>
</label>
<span>
<span>已完成{{completeSize}}</span> / 全部{{todos.length}}
</span>
<button class="btn btn-danger" v-show="completeSize" @click="AllTask">清除已完成任务</button>
</div>
</template>
<script>
export default {
//默认暴露一个模块
props: {
// 需要使用,数组数据,函数,清除,
todos: Array,
deleteCompleteTodos: Function,
selectAll: Function
},
methods: {
AllTask() {
this.deleteCompleteTodos();
}
},
computed: {
completeSize () {
return this.todos.reduce((preTotal, todo) => preTotal + (todo.complete?1:0) ,0)
},
checkAll: {
get () { // 决定是否勾选
return this.completeSize===this.todos.length && this.completeSize>0
},
set (value) {// 点击了全选checkbox value是当前checkbox的选中状态(true/false)
this.selectAll(value)
}
},
}
}
</script>
<style>
.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;
}
</style>