Vue2 Todolist案例

TodoList案列Vue2版本

1. TodoList_静态组件

  1. 先把所有的html结构、css样式,都放在App组件中。
  2. 随后拆分成:HeaderListItemFooter组件。
  3. 把:结构、样式,都放在对应的.vue里。

2. TodoList_初始化数据

  1. 需要准备一个todos数组,用于保存多个todo对象。

    todos:[
      {id:'qw7ywqe28',title:'吃饭',done:false},
      {id:'dw3iw92kj',title:'睡觉',done:true},
      {id:'opkmi9s72',title:'学习',done:false},
    ]
    
  2. 观察发现:todos数组,好多组件都要使用,所以我们选择放在App组件中。

    很多组件都用的数据,可以放在他们共同的父组件中,这叫:状态提升(数据提升)。

  3. App组件中:通过props传递给List组件。

    <List :todos="todos"/>
    
  4. List组件中:接收todos数组,使用v-for遍历,生成多个Item组件,同时传递每一个todo对象给Item组件

    <template>
      <ul class="todo-main">
        <Item v-for="t in todos" :key="t.id" :todo="t"/>
      </ul>
    </template>
      
    <script>
    	import Item from './Item.vue'
    	export default {
    		name: "List",
    		components:{Item},
    		props:['todos']
    	};
    </script>
    
  5. Item组件接收todo对象,并展示。

    <template>
      <li>
        <label> 
    			<input type="checkbox" v-model="todo.done"/>
    			<span>{{todo.title}}</span> 
    		</label>
        <button class="btn btn-danger" style="display: none">删除</button>
      </li>
    </template>
    
    <script>
    	export default {
    		name: "Item",
    		props:['todo']
    	};
    </script>
    

3. TodoList_添加todo

  1. 由于数据在App组件中,所以在App中创建一个addTodo方法,专门用于添加todo

  2. App组件中,通过propsaddTodo传给Header组件。

    注意判断重复数据,使用数组的find方法。

    <template>
      <!------------>
      <Header :addTodo="addTodo"/>
      <!------------>
    </template>
    
    <script>
      export default {
        /*****************/
        methods: {
          addTodo(todoObj){
            //find是有返回值的,若找到了返回该条记录,若找不到undefined
            const result = this.todos.find((t)=>{
              return t.title === todoObj.title
            })
            if(result){
              alert('输入重复,请重新输入!')
            }else{
              this.todos.unshift(todoObj)
            }
          }
        },
        /*****************/
      };
    </script>
    
  3. Header组件中,接收addTodo,需要添加的时候,直接调用即可。

    注意点:我们使用了nanoid这个库,去生成唯一标识。

    <template>
    	<div class="todo-header">
    		<input 
    			type="text" 
    			placeholder="请输入你的任务名称,按回车键确认" 
    			@keyup.enter="handleAdd"
    		/>
    	</div>
    </template>
    
    <script>
    	import {nanoid} from 'nanoid'
      
    	export default {
    		name:'Header',
    		props:['addTodo'],
    		methods: {
    			handleAdd(e){
    				//1.获取用户的输入
            let {value} = e.target
            // 2.校验用户的输入
            if(value.trim()){
              //把用户的输入包装成一个todo对象
              let todoObj = {
                id:nanoid(),
                title:value.trim(),
                done:false
              }
              //调用App传递过来的addTodo,去实现添加
              this.addTodo(todoObj)
            }else{
              alert('输入不能为空!')
            }
            //清空用户输入
            e.target.value = ''
    			}
    		},
    	}
    </script>
    

4. TodoList_删除todo

  1. 由于数据在App组件中,所以在App中创建一个deleteTodo方法,用于删除某个todo

    methods: {
      /**********/
      deleteTodo(id){
        this.todos = this.todos.filter((todo)=>{
          return todo.id !== id
        })
      }
      /**********/
    },
    
  2. App组件中,通过propsdeleteTodo传给List组件。

    <List :todos="todos" :deleteTodo="deleteTodo"/>
    
  3. List组件接收到deleteTodo后,进一步传给Item组件

    <template>
      <ul class="todo-main">
        <Item v-for="t in todos" :key="t.id" :todo="t" :deleteTodo="deleteTodo"/>
      </ul>
    </template>
    
    <script>
    	import Item from './Item.vue'
      
    	export default {
    		name: "List",
    		components:{Item},
    		props:['todos','deleteTodo']
    	};
    </script>
    
  4. Item组件中,接收deleteTodo,并在需要删除的时候使用

      <li>
        <label> 
    			<input type="checkbox" v-model="todo.done"/>
    			<span>{{todo.title}}</span> 
    		</label>
        <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
      </li>
    </template>
    
    <script>
    	export default {
    		name: "Item",
    		props:['todo','deleteTodo'],
    		methods: {
    			handleDelete(id){
    				if(confirm('确定删除吗?')){
    					this.deleteTodo(id)
    				}
    			}
    		},
    	};
    </script>
    

5. TodoList_勾选todo

我们之前写的是v-model所以,是双向绑定,所以勾选的时候,App中的数据是自动修改的,无需编码,就已经实现了勾选单个todo

6 . TodoList_底部计算

直接使用计算属性,代码如下:

computed:{
  total(){
    return this.todos.length
  },
  doneCount(){
      // 第一种计算已完成总数的方式
      /* let n = 0
			this.todos.forEach(todo => {
				if(todo.done){
					n++
				}
			});
			return n */

      // 第二种用reduce,最简便的方式去写
      return this.todos.reduce((pre,current)=> pre + (current.done ? 1 : 0) ,0)
  }
}

7. TodoList_全选 or 全不选

  1. Footer组件中

    <input type="checkbox" v-model="isAll"/>
    
  2. isAll改为计算属性

    isAll:{
        get(){
            return this.todos.every((todo)=>{
                return todo.done
            })
        },
        set(checked){
           this.checkAll(checked)
        }
    }
    

8. TodoList_清除已完成

  1. App组件中,通过propsclearAllDone传给Footer组件。

    <Footer :clearAllDone="clearAllDone"/>
    
    <script>
      methods: {
        clearAllDone(){
          this.todos = this.todos.filter( t => !t.done)
        },
      },
    </script>
    
  2. Footer组件中,接收clearAllDone,并使用

    <button class="btn btn-danger" @click="handleClear">清除已完成任务</button>
    
    <script>
      export default {
        name: "Footer",
        props:['clearAllDone','todos'],
        methods:{
          handleClear(){
            if(confirm('确定清除已完成吗?')){
              this.clearAllDone()
            }
          }
        },
      };
    </script>
    

9. TodoList 本地存储版

  1. 需求:刷新页面,关闭浏览器,TodoList列表不清空,依然是之前的数据。

  2. 思路:将数据存储进localStorage中。

  3. 具体操作:在App组件中监视todos数组,只要数组发生变化,就存入localStorage

  4. 具体编码:

    //......
    data() {
      return {
        //所有要做的事
        todos:JSON.parse(localStorage.getItem('todos')) || []
      }
    }
    //......
    watch:{
      todos:{
        deep:true,
          handler(value){
          	localStorage.setItem('todos',JSON.stringify(value))
        }
      }
    }
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值