素材领取:点击我领取素材
提取码:1024
我们的需求如下:
1.拆分基础组件
2.渲染待办任务
3.添加任务
4.删除任务
5.底部合计 和 清空功能
6.持久化存储
分析:
渲染功能:
1.提供数据: 提供在公共的父组件 App.vue
2.通过父传子,将数据传递给TodoMain
3.利用 v-for渲染
添加功能:
1.手机表单数据 v-model
2.监听事件(回车+点击都要添加)
3.子传父,讲任务名称传递给父组件 App.vue
4.进行添加 unshift(自己的数据自己负责)
5.清空文本框输入的内容
6.对输入的空数据 进行判断
删除功能
1.监听事件(监听删除的点击) 携带id
2.子传父,讲删除的id传递给父组件的App.vue
3.进行删除filter(自己的数据 自己负责)
底部合计:父传子 传list 渲染
清空功能:子传父 通知父组件 → 父组件进行更新
持久化存储:watch深度监视list的变化 -> 往本地存储 ->进入页面优先读取本地数据
父组件代码:
<template>
<!-- 主体区域 -->
<section id="app">
<!-- 监听子组件 -->
<TodoHeader @add="handlerAdd"></TodoHeader>
<!-- 我们父传子给子组件传入list 监听del -->
<TodoMain :list="list" @handlerDel="del"></TodoMain>
<TodoFooter @clear="handlerClear" :list="list"></TodoFooter>
</section>
</template>
<script>
import TodoHeader from "./components/TodoHeader.vue"
import TodoMain from "./components/TodoMain.vue"
import TodoFooter from "./components/TodoFooter.vue"
export default {
data() {
return {
// 准备一个数组存放数据 持久保存到本地
list: JSON.parse(localStorage.getItem("list")) || [
{ id: 1, name: "打篮球" },
{ id: 2, name: "踢足球" }
]
}
},
methods: {
handlerAdd(values) {
// 我们使用unshift()方法向数组的最前面添加数据
this.list.unshift({
// 使用时间戳作为id值
id: +new Date(),
name: values
})
},
del(id) {
// 使用filter去过滤数组完成删除
this.list = this.list.filter(item => item.id !== id)
},
handlerClear() {
this.list = []
}
},
watch: {
list: {
deep: true,
handler(newValue) {
localStorage.setItem("list", JSON.stringify(newValue))
}
}
},
components: {
TodoHeader,
TodoMain,
TodoFooter
}
}
</script>
子组件TodoHeader代码:
<template>
<!-- 输入框 -->
<header class="header">
<h1>小黑记事本</h1>
<!-- 使用v-model双向数据绑定 -->
<!-- 我们点击按钮 与 回车都需要监听 -->
<input @keyup.enter="handlerAdd" v-model="msg" placeholder="请输入任务" class="new-todo" />
<!-- 添加功能 需要使用到子传父 -->
<button @click="handlerAdd" class="add">添加任务</button>
</header>
</template>
<script>
export default {
data() {
return {
msg: ""
};
},
methods: {
handlerAdd() {
// 当msg为空时 我们需要返回
if (this.msg.trim() == "") {
alert("请输入值")
return
}
// 子传父 使用this.$emit()
this.$emit('add', this.msg);
// 添加完之后 我们需要把表单的值赋为空
this.msg = ""
}
},
};
</script>
子组件TodoMain代码:
<template>
<!-- 列表区域 -->
<section class="main">
<ul class="todo-list">
<!-- 我们使用v-for去渲染页面 -->
<li class="todo" v-for="(item, index) in list" :key="item.id">
<div class="view">
<!-- 需要使用到index -->
<span class="index">{{ index + 1 }}.</span> <label>{{ item.name }}</label>
<!-- 我们需要借助id去删除数据 -->
<button @click="del(item.id)" class="destroy"></button>
</div>
</li>
</ul>
</section>
</template>
<script>
export default {
// 我们使用props
props: {
list: Array
},
methods: {
del(id) {
// 子传父
this.$emit('handlerDel', id);
}
},
};
</script>
子组件TodoFooter代码:
<template>
<!-- 统计和清空 -->
<footer class="footer">
<!-- 统计 -->
<!-- 我们只需要判断数组的长度即可 -->
<span class="todo-count">合 计:<strong> {{ list.length }} </strong></span>
<!-- 清空 -->
<!-- 我们只需把数组覆盖即可 使用 数组名 = [] -->
<!-- 绑定点击事件 -->
<button @click="clear" class="clear-completed">
清空任务
</button>
</footer>
</template>
<script>
export default {
// 我们把list通过父传子的方法传入
props: {
list: Array
},
methods: {
clear() {
// 子传父
this.$emit('clear');
}
},
};
</script>
感谢大家的阅读,如有不对的地方,可以向我提出,感谢大家!