app.vue
<template>
<section class="todoapp">
<!-- 除了驼峰, 还可以使用-转换链接 -->
<todo-header @create="createFn"></todo-header>
<todo-main :arr="showArr" @del="deleteFn"></todo-main>
<todo-fooder :farr="showArr" @changeType="typeFn" @clear="clearFn"></todo-fooder>
</section>
</template>
<script>
// 1.0 样式引入
import "./styles/base.css";
import "./styles/index.css";
import TodoHeader from "./components/TodoHeader.vue";
import TodoFooder from "./components/TodoFooder.vue";
import TodoMain from "./components/TodoMain.vue";
export default {
components: {
TodoHeader,
TodoMain,
TodoFooder,
},
data() {
return {
list: JSON.parse(localStorage.getItem('todoList')) || [],
getSet: "all", //默认显示的是all,no,yes
};
},
methods: {
//新增
createFn(taskName) {
let id =
this.list.length == 0 ? 100 : this.list[this.list.length - 1].id + 1;
this.list.push({
id: id,
name: taskName,
isDone: false,
});
},
//删除
deleteFn(theID) {
let index = this.list.findIndex((obj) => obj.id === theID);
this.list.splice(index, 1);
},
//选中按钮 全部 完成 未完成
typeFn(str) {
this.getSet = str;
},
//删除已完成
clearFn(){
this.list= this.list.filter(obj=>obj.isDone===false);
}
},
computed: {
showArr() {
if (this.getSet === "yes") {
//显示已完成
return this.list.filter((obj) => obj.isDone === true);
} else if (this.getSet === "no") {
//显示未完成
return this.list.filter((obj) => obj.isDone === false);
} else {
return this.list;
}
},
},
watch:{
list:{
deep:true,
handler(){
localStorage.setItem('todoList',JSON.stringify(this.list))
}
}
}
};
</script>
TodoHeader
<template>
<header class="header">
<h1>todos</h1>
<input id="toggle-all" class="toggle-all" type="checkbox" />
<label for="toggle-all" @click="allFn"></label>
<input
class="new-todo"
placeholder="输入任务名称-回车确认"
autofocus
@keydown.enter="downFn"
v-model="task"
/>
</header>
</template>
<script>
export default {
data() {
return {
task: "",
};
},
methods: {
downFn() {
if (this.task.trim().length === 0) {
alert("任务名字不能为空");
return;
}
this.$emit("create", this.task);
this.task = "";
},
allFn(){
}
},
};
</script>
TodoMain
<template>
<ul class="todo-list">
<!-- completed: 完成的类名 -->
<li :class="{ completed: obj.isDone }" v-for="obj in arr" :key="obj.id">
<div class="view">
<input class="toggle" type="checkbox" v-model="obj.isDone" />
<label>{{ obj.name }}</label>
<button class="destroy" @click="delFn(obj.id)"></button>
</div>
</li>
</ul>
</template>
<script>
export default {
props: ["arr"],
methods: {
delFn(id) {
this.$emit("del", id);
},
},
};
</script>
TodoFooder
<template>
<footer class="footer">
<span class="todo-count"
>剩余<strong>{{ count }}</strong></span
>
<ul class="filters" @click="fn">
<li>
<a
:class="{ selected: isSet === 'all' }"
href="javascript:; "
@click="isSet = 'all'"
>全部</a
>
</li>
<li>
<a
:class="{ selected: isSet === 'no' }"
href="javascript:;"
@click="isSet = 'no'"
>未完成</a
>
</li>
<li>
<a
:class="{ selected: isSet === 'yes' }"
href="javascript:;"
@click="isSet = 'yes'"
>已完成</a
>
</li>
</ul>
<button class="clear-completed" @click="clearFn">清除已完成</button>
</footer>
</template>
<script>
export default {
props: ["farr"],
computed: {
count() {
return this.farr.length;
},
},
data() {
return {
isSet: "all", //全部 ‘all’ 已完成 ‘yes’ 未完成 ‘no’
};
},
methods: {
fn() {
this.$emit("changeType", this.isSet);
},
clearFn() {
this.$emit("clear");
},
},
};
</script>