列表操作案例
<template>
<div id="root">
<div class="formLists">
<FormListAdd :addTodos="addTodos"></FormListAdd>
<FormLists :todos="todos" :todoState="todoState" :delTodos="delTodos"></FormLists>
<FormCheckbox :todos="todos" :checkAllTodos="checkAllTodos" :clearAllTodos="clearAllTodos"></FormCheckbox>
</div>
</div>
</template>
<script>
import FormListAdd from "./components/FormListAdd";
import FormLists from "./components/FormLists";
import FormCheckbox from "./components/FormCheckbox";
export default {
name: "App",
components: { FormListAdd, FormLists, FormCheckbox },
data() {
return {
todos: [
{ id: "1", name: "吃饭", state: false },
{ id: "2", name: "睡觉", state: false },
{ id: "3", name: "打豆豆", state: false },
{ id: "4", name: "游戏", state: false },
{ id: "5", name: "喝茶", state: false },
{ id: "6", name: "搓麻将", state: false },
],
};
},
methods: {
// 增加
addTodos(obj){
this.todos.unshift(obj)
},
// 改
todoState(id){
this.todos.forEach((list)=>{
if (list.id === id) {
list.state = !list.state
}
})
},
// 删除
delTodos(id){
this.todos = this.todos.filter((list)=>{
return list.id != id
})
},
// 全选
checkAllTodos(state){
this.todos.forEach(e => {
e.state = state
});
},
// 删除已完成
clearAllTodos(){
this.todos = this.todos.filter((list)=>{
return !list.state
})
}
},
};
</script>
<style lang="scss" scoped>
.formLists {
border: 1px solid #f7f7f7;
padding: 1rem;
border-radius: 0.25rem;
}
</style>
<template>
<div id="root">
<div class="formLists">
<FormListAdd :addTodos="addTodos"></FormListAdd>
<FormLists :todos="todos" :todoState="todoState" :delTodos="delTodos"></FormLists>
<FormCheckbox :todos="todos" :checkAllTodos="checkAllTodos" :clearAllTodos="clearAllTodos"></FormCheckbox>
</div>
</div>
</template>
<script>
import FormListAdd from "./components/FormListAdd";
import FormLists from "./components/FormLists";
import FormCheckbox from "./components/FormCheckbox";
export default {
name: "App",
components: { FormListAdd, FormLists, FormCheckbox },
data() {
return {
// todos: [
// // { id: "1", name: "吃饭", state: false },
// // { id: "2", name: "睡觉", state: false },
// // { id: "3", name: "打豆豆", state: false },
// // { id: "4", name: "游戏", state: false },
// // { id: "5", name: "喝茶", state: false },
// // { id: "6", name: "搓麻将", state: false },
// ],
todos:JSON.parse(localStorage.getItem('todos')) || []
};
},
methods: {
// 增加
addTodos(obj){
this.todos.unshift(obj)
},
// 改
todoState(id){
this.todos.forEach((list)=>{
if (list.id === id) {
list.state = !list.state
}
})
},
// 删除
delTodos(id){
this.todos = this.todos.filter((list)=>{
return list.id != id
})
},
// 全选
checkAllTodos(state){
this.todos.forEach(e => {
e.state = state
});
},
// 删除已完成
clearAllTodos(){
this.todos = this.todos.filter((list)=>{
return !list.state
})
}
},
watch:{
todos:{
deep:true,
handler(n){
localStorage.setItem('todos',JSON.stringify(n))
}
}
}
};
</script>
<style lang="scss" scoped>
.formLists {
border: 1px solid #f7f7f7;
padding: 1rem;
border-radius: 0.25rem;
}
</style>
<template>
<div class="formLists-header">
<input class="btn" type="text" v-model="todoName" placeholder="请输入你的任务名,按回车键确认" @keyup.enter="addTodo">
</div>
</template>
<script>
import { nanoid } from "nanoid";
export default {
name: 'FormListAdd',
props:['addTodos'],
data() {
return {
todoName:''
}
},
methods: {
addTodo(e){
if (!this.todoName) return alert('输入不能为空')
const todoObj = {id:nanoid(),name:e.target.value,state:false}
this.addTodos(todoObj)
this.todoName = ''
// console.log(todoObj)
}
},
}
</script>
<style lang="scss" scoped>
.formLists-header{
display: flex;
.btn{
display: block;
width: 100%;
height: calc(1.5em + 0.75rem + 2px);
padding: 0.375rem 0.75rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: 0.25rem;
}
}
</style>
<template>
<div class="formLists-body">
<ul>
<FormList
v-for="(t,id) in todos"
:key="id"
:todo="t"
:todoState="todoState"
:delTodos="delTodos">
</FormList>
</ul>
</div>
</template>
<script>
import FormList from "./FormList.vue";
export default {
name: "FormLists",
components: { FormList },
props:['todos','todoState','delTodos']
};
</script>
<style lang="scss" scoped>
.formLists-body{
border: 1px solid #999999;
border-radius: 0.25rem;
overflow: hidden;
margin-top: 1rem;
&>ul{
display: flex;
flex-direction: column;
margin-bottom: 0;
padding: 0;
margin: 0;
}
}
</style>
<template>
<li class="lists-item"><input type="checkbox" name="state" :checked="todo.state" @click="upState(todo.id)" /><span>{{todo.name}}</span> <button class="btn" @click="delItem(todo.id)">删除</button></li>
<!-- 不建议使用 v-model 因为v-model 违背了不修改props 的原则 -->
<!-- <li class="lists-item"><input type="checkbox" name="state" v-model="todo.state" /><span>{{todo.name}}</span> <button>删除</button></li> -->
</template>
<script>
export default {
name: 'FormList',
data() {
return {
}
},
props:['todo','todoState','delTodos'],
methods:{
delete(id){
console.log(id)
},
upState(id){
this.todoState(id)
},
delItem(id){
if(confirm('确定删除该选项吗?')) this.delTodos(id)
}
}
}
</script>
<style lang="scss" scoped>
.lists-item{
position: relative;
display: block;
padding: 0.75rem 1.25rem;
background-color: #fff;
border-bottom: 1px solid rgba(0,0,0,.125);
&:last-child {
border: none;
}
&:hover{
background-color: #f7f7f7;
.btn{
display: inline-block;
}
}
.btn{
display: none;
}
}
</style>
<template>
<div class="formLists-footer" v-show="total">
<div class="fLeft">
<!-- <input type="checkbox" name="" id="" :checked="isAll" @change="checkAll">已选{{doneTotal}},全部{{total}} -->
<input type="checkbox" name="" id="" v-model="isAll" >已选{{doneTotal}},全部{{total}}/
</div>
<div class="fRight">
<button class="btn" type="submit" @click="clearAll">删除已完成</button>
</div>
</div>
</template>
<script>
export default {
name: 'FormCheckbox',
data() {
return {
}
},
props:['todos','checkAllTodos','clearAllTodos'],
computed: {
// doneTotal(){
// let i = 0
// this.todos.forEach(e => {
// if(e.state) i++
// });
// reduc
// return i
// }
doneTotal(){
// return this.todos.reduce((pre,current)=>{
// // console.log('@',pre,current.state)
// return pre + (current.state ? 1 : 0)
// },0)
return this.todos.reduce((pre,current)=> pre + (current.state ? 1 : 0) ,0)
},
total(){
return this.todos.length
},
isAll:{
get(){
return this.doneTotal === this.total && this.total > 0
},
set(value){
this.checkAllTodos(value)
}
}
},
methods: {
checkAll(e){
this.checkAllTodos(e.target.checked)
},
clearAll(){
if(confirm('确认删除已完成')) this.clearAllTodos()
}
},
}
</script>
<style lang="scss" scoped>
.formLists-footer{
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 1rem;
.fLeft{
font-size: 14px;
color: #999999;
display: flex;
align-items: center;
}
.btn{
display: inline-block;
font-weight: 400;
text-align: center;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 1px solid transparent;
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: 0.25rem;
color: #fff;
background-color: #0069d9;
border-color: #0062cc;
}
}
</style>