💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
案例效果图:
咱们可以把记事本原有的结构拆成三部分内容:头部(TodoHeader)、列表(TodoMain)、底部(TodoFooter)
列表渲染
思路分析:
-
提供数据:提供在公共的父组件 App.vue
-
通过父传子,将数据传递给TodoMain
-
利用v-for进行渲染
添加功能
思路分析:
-
收集表单数据 v-model
-
监听时间 (回车+点击 都要进行添加)
-
子传父,将任务名称传递给父组件App.vue
-
父组件接受到数据后 进行添加 unshift(自己的数据自己负责)
删除功能
-
监听时间(监听删除的点击)携带id
-
子传父,将删除的id传递给父组件App.vue
-
进行删除 filter (自己的数据自己负责)
底部功能及持久化存储
-
底部合计:父组件传递list到底部组件 —>展示合计
-
清空功能:监听事件 —> 子组件通知父组件 —>父组件清空
-
持久化存储:watch监听数据变化,持久化到本地
源码分享
App.vue
<template>
<!-- 主体区域 -->
<section id="app">
<TodoHeader @add="handleAdd"></TodoHeader>
<TodoMain @del="handleDel" :list="list"></TodoMain>
<TodoFooter @clear="handleClear" :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: "踢足球" },
{ id: 3, name: "打棒球" },
],
};
},
methods: {
handleAdd(todoName) {
this.list.unshift({
id: +new Date(),
name: todoName,
});
},
handleDel(id) {
this.list = this.list.filter((item) => item.id != id);
},
handleClear() {
this.list = [];
},
},
watch: {
list: {
deep: true,
handler(newValue) {
localStorage.setItem("list", JSON.stringify(newValue));
},
},
},
components: {
TodoHeader,
TodoMain,
TodoFooter,
},
};
</script>
<style>
</style>
TodoHeader.vue
<template>
<!-- 输入框 -->
<header class="header">
<h1>记事本</h1>
<input
@keyup.enter="handleAdd"
v-model="todoName"
placeholder="请输入任务"
class="new-todo"
/>
<button @click="handleAdd" class="add">添加任务</button>
</header>
</template>
<script>
export default {
data() {
return {
todoName: "",
};
},
methods: {
handleAdd() {
if (this.todoName.trim() === "") {
alert("任务名称不能为空");
return;
}
this.$emit("add", this.todoName);
this.todoName = "";
},
},
};
</script>
<style>
</style>
TodoMain.vue
<template>
<!-- 列表区域 -->
<section class="main">
<ul class="todo-list">
<li v-for="(item, index) in list" :key="item.id" class="todo">
<div class="view">
<span class="index">{{ index + 1 }}.</span>
<label>{{ item.name }}</label>
<button @click="handleDel(item.id)" class="destroy"></button>
</div>
</li>
</ul>
</section>
</template>
<script>
export default {
props: {
list: Array,
},
methods: {
handleDel(id) {
this.$emit("del", id);
},
},
};
</script>
<style>
</style>
TodoFooter.vue
<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 {
props: {
list: Array,
},
methods: {
clear() {
this.$emit("clear");
},
},
};
</script>
<style>
</style>
❤️❤️❤️小郑是普通学生水平,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍