vue-vue2脚手架5-TodoList案例(2)

vue-vue2脚手架5-TodoList案例

vue-vue2脚手架5-TodoList案例(1)

删除按钮

以下是我的代码对button按钮注释

在这里插入图片描述
在这里插入图片描述

这里我前面给的静态资源有个问题 app里面 css文件时 scope 的,可以把scope删除
这里需要向上一篇文章讲的那样重复讲delete按钮添加

顶部代码:App.vue


<template>
<div id="root">
  <div class="todo-container">
    <div class="todo-wrap">
      <MyHeader :addtodo="addtodo"/>
      <MyList :todos="todos" :deleteTodo="deleteTodo"  />
      <MyFooter/>
      
    </div>
  </div>
</div>

</template>
<script>
	import MyHeader from './components/MyHeader'
   // import MyHeader from './components/MyHeader.vue'
	import MyList from './components/MyList'
	import MyFooter from './components/MyFooter'

	export default {
		name:'App',
		components:{MyHeader,MyList,MyFooter},
		data() {
			return {
				todos:[
					{id:'001',title:'吃饭',done:true},
					{id:'002',title:'睡觉',done:false},
                    {id:'003',title:'玩游戏',done:true}
				]
			}
		},
        methods: {
			//添加一个todo
			addtodo(todo){
				
				console.log('APP.log',todo)
				this.todos.unshift(todo)
			},
			//勾选or取消勾选一个todo
			checkTodo(id){
				this.todos.forEach((todo)=>{
					if(todo.id === id) todo.done = !todo.done
				})
			},
			//删除一个todo
			deleteTodo(id){
				this.todos = this.todos.filter( todo => todo.id !== id )
			}


		},
	}
</script>

中层:MyList.vue

在这里插入图片描述
底层:MyItem.vue

<template>
	<li>
		<label>
			<!-- <input type="checkbox"  :checked="todo.done"  @click="handckeck(todo.id)"/> -->
			<!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,因为修改了props -->
			<input type="checkbox"   v-model="todo.done" />
			
			<span>{{todo.title}}</span>
		</label>
		<button class="btn btn-danger"  @click="ondelete(todo.id)" >删除</button>
	</li>
</template>

<script>
	export default {
		name:'MyItem',
	
		props:['todo','deleteTodo'],

       methods: {
         ondelete(id){
               console.log("获取删除id",id)
                if(confirm('确定删除吗?')){
					//通知App组件将对应的todo对象删除
					this.deleteTodo(id)
				}

        }
	},
		
	}
</script>

<style scoped>
	/*item*/
	li {
		list-style: none;
		height: 36px;
		line-height: 36px;
		padding: 0 5px;
		border-bottom: 1px solid #ddd;
	}

	li label {
		float: left;
		cursor: pointer;
	}

	li label li input {
		vertical-align: middle;
		margin-right: 6px;
		position: relative;
		top: -1px;
	}

	li button {
		float: right;
		display: none;
		margin-top: 3px;
	}

	li:before {
		content: initial;
	}

	li:last-child {
		border-bottom: none;
	}

	li:hover{
		background-color: #ddd;
	}
	
	li:hover button{
		display: block;
	}
</style>

这里 css代码 博主加了 hover时间,如果鼠标点击上去可以对按钮进行block

在这里插入图片描述

其实这种方法很繁琐!后面博主会将更加便利的方法,先从简单的开始

底部统计 reduce的使用

从上一篇将todos 传给 MyFooter.vue,进行数据的统计

底部代码 MyFooter.vue

<template >
	<div class="todo-footer">
        <label>
          <input type="checkbox"/>
        </label>
        <span>
          <span>已完成{{donetotal}}</span> / 全部{{todos.length}}
        </span>
        <button class="btn btn-danger">清除已完成任务</button>
      </div>
</template>
<script>
	export default {
		name:'MyFooter',

		props:['todos'],

		computed: {
            donetotal(){
				//  第一遍简单偏离方式
                // let i=0
                // this.todos.forEach((todo) => {
				// 	if(todo.done) i++

				// });
                // return i

            //   第二种写法
            //   const x=  this.todos.reduce((pre,current)=>{
			// 		console.log('@',pre,current)
			// 		return pre + (current.done ? 1 : 0)
            //     },0)
			//    return x

              //简写
               return this.todos.reduce((pre,current) => pre + (current.done ? 1 : 0) ,0)
           
                  
			}

		}
	}
</script>

底部全选框实现1

MyFooter.vue

<template >
	<div class="todo-footer">
        <label>
          <input type="checkbox"  :checked="isAll" @change="checkall"/>
        </label>
        <span>
          <span>已完成{{donetotal}}</span> / 全部{{total}}
        </span>
        <button class="btn btn-danger">清除已完成任务</button>
      </div>
</template>
<script>
	export default {
		name:'MyFooter',

		props:['todos','checkalltodo'],

		computed: {
             total(){
               return this.todos.length
            },

            donetotal(){
              //简写
               return this.todos.reduce((pre,current) => pre + (current.done ? 1 : 0) ,0)
             
			},
            isAll() {
                    console.log("那哦草" ,this.donetotal === this.total && this.total > 0)
                    return this.donetotal === this.total && this.total > 0
			}

		},
		methods: {
			checkall(e){
				console.log(e.target.checked)
                   this.checkalltodo(e.target.checked)
			}
		},
	}
</script>

App.vue


<template>

<div id="root">
  <div class="todo-container">
    <div class="todo-wrap">
      <MyHeader :addtodo="addtodo"/>
      <MyList :todos="todos" :deleteTodo="deleteTodo"  />
      <MyFooter :todos="todos" :checkalltodo="checkalltodo"/>
      
    </div>
  </div>
</div>

</template>



<script>
	import MyHeader from './components/MyHeader'
   // import MyHeader from './components/MyHeader.vue'
	import MyList from './components/MyList'
	import MyFooter from './components/MyFooter'

	export default {
		name:'App',
		components:{MyHeader,MyList,MyFooter},
		data() {
			return {
				todos:[
					{id:'001',title:'吃饭',done:true},
					{id:'002',title:'睡觉',done:false},
                    {id:'003',title:'玩游戏',done:true}
				]
			}
		},
        methods: {
			//添加一个todo
			addtodo(todo){
				
				console.log('APP.log',todo)
				this.todos.unshift(todo)
			},
			//勾选or取消勾选一个todo
			checkTodo(id){
				this.todos.forEach((todo)=>{
					if(todo.id === id) todo.done = !todo.done
				})
			},
			//删除一个todo
			deleteTodo(id){
				this.todos = this.todos.filter( todo => todo.id !== id )
			},
			// 全选/全不选
            checkalltodo(done){
               this.todos.forEach((todo)=>{
                todo.done=done
               })

			}

		},
	}
</script>

底部全选框升级2

升级版可以用   <input type="checkbox"  v-model="isAll" /> 来实现该操作
不过有个问题就是点击全选的时候会出现你没有set命令。类似java bean的属性

在这里插入图片描述

<template >
	<div class="todo-footer">
        <label>
        <!--  <input type="checkbox"  :checked="isAll" @change="checkall"/>  --> 

        <input type="checkbox"  v-model="isAll" />
        </label>
        <span>
          <span>已完成{{donetotal}}</span> / 全部{{total}}
        </span>
        <button class="btn btn-danger">清除已完成任务</button>
      </div>
</template>
<script>
	export default {
		name:'MyFooter',

		props:['todos','checkalltodo'],

		computed: {
             total(){
               return this.todos.length
            },

            donetotal(){
				
              //简写
               return this.todos.reduce((pre,current) => pre + (current.done ? 1 : 0) ,0)
             
			},
            isAll : {
                   get(){
                        return this.donetotal === this.total && this.total > 0
                    },
                   set(value){
                        this.checkalltodo(value)
                   } 
			}

		},
		methods: {

			checkall(e){
				console.log(e.target.checked)
                   this.checkalltodo(e.target.checked)
			}
		},
	}
</script>

前面说的 v-model 不好是因为他是直接修改了 props, 这里用的是 方法,是正规手段

清除已完成任务

 同上啊,这些操作

App.vue


<template>

<div id="root">
  <div class="todo-container">
    <div class="todo-wrap">
      <MyHeader :addtodo="addtodo"/>
      <MyList :todos="todos" :deleteTodo="deleteTodo"  />
      <MyFooter :todos="todos" :checkalltodo="checkalltodo" :clearAllTodo="clearAllTodo" />
      
    </div>
  </div>
</div>

</template>



<script>
	import MyHeader from './components/MyHeader'
   // import MyHeader from './components/MyHeader.vue'
	import MyList from './components/MyList'
	import MyFooter from './components/MyFooter'

	export default {
		name:'App',
		components:{MyHeader,MyList,MyFooter},
		data() {
			return {
				todos:[
					{id:'001',title:'吃饭',done:true},
					{id:'002',title:'睡觉',done:false},
                    {id:'003',title:'玩游戏',done:true}
				]
			}
		},
        methods: {
			//添加一个todo
			addtodo(todo){
				
				console.log('APP.log',todo)
				this.todos.unshift(todo)
			},
			//勾选or取消勾选一个todo
			checkTodo(id){
				this.todos.forEach((todo)=>{
					if(todo.id === id) todo.done = !todo.done
				})
			},
			//删除一个todo
			deleteTodo(id){
				this.todos = this.todos.filter( todo => todo.id !== id )
			},
			// 全选/全不选
            checkalltodo(done){
               this.todos.forEach((todo)=>{
                todo.done=done
               })

			},
			clearAllTodo(){
                 this.todos = this.todos.filter((todo)=>{
					return !todo.done
				})

			}

		},
	}
</script>

MyFooter.vue

<template >
	<div class="todo-footer">
        <label>
        <!--  <input type="checkbox"  :checked="isAll" @change="checkall"/>  --> 

        <input type="checkbox"  v-model="isAll" />
        </label>
        <span>
          <span>已完成{{donetotal}}</span> / 全部{{total}}
        </span>
        <button class="btn btn-danger" @click="clearAll">清除已完成任务</button>
      </div>
</template>
<script>
	export default {
		name:'MyFooter',

		props:['todos','checkalltodo','clearAllTodo'],

		computed: {
             total(){
               return this.todos.length
            },

            donetotal(){
				// diyiban
                // let i=0
                // this.todos.forEach((todo) => {
				// 	if(todo.done) i++

				// });
                // return i

            //   第二种写法
            //   const x=  this.todos.reduce((pre,current)=>{
			// 		console.log('@',pre,current)
			// 		return pre + (current.done ? 1 : 0)
            //     },0)
			//    return x

              //简写
               return this.todos.reduce((pre,current) => pre + (current.done ? 1 : 0) ,0)
             
			},
            isAll : {
                   get(){
                        return this.donetotal === this.total && this.total > 0
                    },
                   set(value){
                        this.checkalltodo(value)
                   } 
			}

		},
		methods: {

			checkall(e){
				console.log(e.target.checked)
                   this.checkalltodo(e.target.checked)
			},
			//清空所有已完成
            clearAll(){
				this.clearAllTodo()
             }
		},
	}
</script>

总结TodoList案例

  1. 组件化编码流程:
​	(1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。

​	(2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:

​			1).一个组件在用:放在组件自身即可。

​			2). 一些组件在用:放在他们共同的父组件上(<span style="color:red">状态提升</span>)。

​	(3).实现交互:从绑定事件开始。
  1. props适用于:
    (1).父组件 ==> 子组件 通信
    (2).子组件 ==> 父组件 通信(要求父先给子一个函数)
  1. 使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!
  1. props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。

最终项目分享

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值