目标成品图:
css样式从简
1:创建3个组件和里面的代码还有样式
2:APP.vue中引入三个组件
需求:把任务列表展示到页面TodoMain.vue中
需求:选中状态 设置相关的样式
步骤:
//app.vue
<todo-main :arr="list"></todo-main>
data() {
return {
list: [
{ id: 100, name: '吃饭', ischeck: false },
{ id: 101, name: '睡觉', ischeck: false },
{ id: 102, name: '打豆豆', ischeck: false },
],
}
},
//TodoMain.vue
<template>
<div class="main">
<ul>
<li v-for="item in arr" :key="item.id">
<div class="left">
<input type="checkbox" v-model="item.ischeck" />
<span :class="{ undeline: item.ischeck }">
{{ item.name }}
span>
div>
<button>删除button>
li>
ul>
div>
template>
<script>
export default {
props: ['arr'],
}
script>
需求:输入任务回车,新增任务
TodoHead.vue 输入框 --键盘事件—回车
子传父 把任务 —App.vue中 加入到数组中
数组改变,所有用到数组的地方都会更新
输入框为空,提示用户必须输入内容
//TodoHead.vue
<input type="text" v-model="name" @keyup.enter="addFn" />
methods: {
addFn() {
// 非空判断
if (this.name.trim().length === 0) {
alert('任务内容不能为空')
return
}
// 子传父
this.$emit('create', this.name)
this.name = ''
},
},
//App.vue
<todo-head @create="createFn"></todo-head>
methods: {
createFn(name) {
var id =
this.list.length === 0 ? 100 : this.list[this.list.length - 1].id + 1
this.list.push({
id: id,
name: name,
ischeck: false,
})
},
},
//App.vue
<todo-main :arr="list" @delEvent="deleteFn"></todo-main>
methods: {
deleteFn(id) {
// 删除
let index = this.list.findIndex((item) => item.id === id)
this.list.splice(index, 1)
},
}
//TodoMain.vue
<button @click="delFn(item.id)">删除</button>
methods: {
delFn(id) {
// 子传父
this.$emit('delEvent', id)
},
},
统计当前任务的条数
步骤:
//TodoFoot.vue
<template>
<div class="todo-foot">
<div>剩余{{ farr.length }}---{{ allNum }}div>
<ul>
<li>全部li>
<li class="active">已完成li>
<li>未完成li>
ul>
<button>清除已完成button>
div>
template>
<script>
export default {
props: ['farr'],
computed: {
// 计算属性
allNum() {
return this.farr.length
},
},
}
script>
点击底部切换,点谁谁有边框样式
对应切换不同的数据展示
步骤:
//App.vue
<todo-main :arr="showArr" @delEvent="deleteFn">todo-main>
<todo-foot :farr="showArr" @changType="typeFn">todo-foot>
<script>
export default {
data() {
return {
getSel: 'all', //默认显示全部
}
},
computed: {
showArr() {
switch (this.getSel) {
case 'all':
return this.list
break
case 'yes':
return this.list.filter((item) => item.ischeck === true)
break
case 'no':
return this.list.filter((item) => item.ischeck === false)
break
}
},
},
methods: {
typeFn(sel) {
//点击底部的类型
this.getSel = sel
},
},
}
script>
//TodoFoot.vue
<ul @click="fn">
<li @click="isSel = 'all'" :class="{ active: isSel === 'all' }">全部</li>
<li @click="isSel = 'yes'" :class="{ active: isSel === 'yes' }">
已完成
</li>
<li @click="isSel = 'no'" :class="{ active: isSel === 'no' }">未完成</li>
</ul>
export default {
data() {
return {
// 1变量isSel
isSel: 'all', //all 全部 yes已完成 no未完成
}
},
methods: {
fn() {
// 点击全部,已完成,未完成
// 2子--->父 把isSel的值传给App.vue
this.$emit('changType', this.isSel)
},
},
}
点击清空按钮,把已完成的任务清空
步骤:
//TodoFoot.vue
<button @click="clearFn">清除已完成</button>
methods:{
fn() {
// 点击全部,已完成,未完成
// 2子--->父 把isSel的值传给App.vue
this.$emit('changType', this.isSel)
},
}
//App.vue
methods: {
clearFun() {
// 清空已完成
this.list = this.list.filter((item) => item.ischeck == false)
},
}
页面刷新后数据还存在
步骤:
data() {
return {
list: JSON.parse(localStorage.getItem('list') || '[]'),
getSel: 'all', //默认显示全部
}
},
watch: {
list: {
deep: true,
handler(newval) {
localStorage.setItem('list', JSON.stringify(newval))
},
},
},
点击全选 —小选框状态和全选状态一样
小选框都选中(手选)—全选会自动选中
步骤:
//TodoHead.vue
<input type="checkbox" v-model="isAll" />
computed: {
isAll: {
set(checked) {
// 影响数组里每个小选框绑定的ischeck属性
this.list.forEach((item) => {
item.ischeck = checked
})
},
get() {
// 小选框统计状态--->全选框
return (
this.list.length !== 0 &&
this.list.every((item) => item.ischeck === true)
)
},
},
},
//App.vue
<todo-head :list="list" @create="createFn">todo-head>
哪天需要了,可以去下载地址