Vue技术之经典案例todolist

前言

todolist案例在学习很多技术上都很适合新手练手。在这篇文章中将用Vue技术来实现该案例。此外感兴趣的小伙伴可以点击下方链接来获取案例源码哦!案例源码
链接:https://github.com/lingjing-wq/Vue-todolist

案例效果展示

在这里插入图片描述

案例功能介绍

  1. 任务的添加
  2. 任务的删除
  3. 任务的数量统计(已完成、总数量)
  4. 任务的状态切换(打钩or不打勾)
  5. 清除所用已完成的任务
  6. 任务的全选

案例主要技术

  1. Vue脚手架
  2. 模块化
  3. props的应用
  4. 组件通信
  5. Vue常用指令(v-for、v-bind、v-show等)
  6. Vue事件处理
  7. 计算属性

案例搭建过程

1. 首先使用脚手架新建项目

Vue create vue_test01

2. 切换到vue_test01文件夹下,并启动项目

cd vue_test01
npm run serve

3. 组件化案例
原则是根据案例的功能点来进行拆分。如下
在这里插入图片描述
将案例的骨架搭建好
在这里插入图片描述
4. 具体代码的实现

App.vue文件

<template>
  <div id="app">
    <div class="todo-container">
      <div class="todo-wrap">

        <MyHeader :receive="receive" />

        <MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo" />

        <MyFooter :todos="todos" :checkAllTodo='checkAllTodo' :clearAllTodo='clearAllTodo' />
      </div>
    </div>
  </div>
</template>

<script>
import MyHeader from './components/MyHeader.vue'
import MyList from './components/MyList.vue'
import MyFooter from './components/MyFooter.vue'
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: {
    //往对象数组中添加新的对象数据
    receive(e) {
      // console.log("收到数据了",e);
      this.todos.unshift(e);
      //勾选or取消勾选
    },
    //勾选or取消勾选
    checkTodo(id) {
      this.todos.forEach((todo) => {
        if (todo.id === id)
          todo.done = !todo.done;
      })
    },
    //删除
    deleteTodo(id) {
      this.todos = this.todos.filter((todo) => {
        return todo.id !== id;
      })
    },
    //全选or全不选
    checkAllTodo(done) {
      this.todos.forEach((todo) => {
        todo.done = done;
      })
    },
    //清除所有已完成的任务
    clearAllTodo() {
      this.todos = this.todos.filter((todo) => {
        return !todo.done
      })
    }
  },
}
</script>

MyHeader.vue文件

<template>
    <div class="todo-header">
        <input type="text" placeholder="请输入你的任务名称,按回车键确认" @keyup.enter="add" />
    </div>
</template>

<script>
import { nanoid } from 'nanoid'
export default {
    name: 'MyHeader',
    //接收从APP内传来的函数receive
    props:['receive'],
    methods: {
        add(event) {
            // console.log(event.target.value)
            if(!event.target.value.trim()) return;//校验数据:输入不为空  &  trim()去掉前后空格
            //将用户的输入包包装成一个todo对象
            const todoObj = { id: nanoid(), title: event.target.value, done: false }
            // console.log(todoObj)
            this.receive(todoObj);//将需要添加的数据传给App
            //添加完后将值置为空
            event.target.value=''
        }
    },
}
</script>

MyList.vue文件

<template>
    <ul class="todo-main">
        <MyItem v-for="todoObj in todos" :key="todoObj.id" :todo="todoObj" :checkTodo="checkTodo" :deleteTodo="deleteTodo"/>
    </ul>
</template>

<script>
import MyItem from './MyItem.vue'

export default {
    name: 'MyList',
    components: {
        MyItem
    },
    //接收从App组件中来的数据
    props:['todos','checkTodo','deleteTodo']
}
</script>

MyItem.vue文件

<template>
    <li>
        <label>
            <input type="checkbox" :checked="todo.done" @click="handleCheck(todo.id)" />
            <span>{{ todo.title }}</span>
        </label>
        <button class="btn btn-danger" @click="handledelete(todo.id)">删除</button>
    </li>
</template>

<script>
export default {
    name: 'MyItem',
    //声明接受todo对象
    props: ['todo', 'checkTodo','deleteTodo'],//接收从MyList组件中传来的数据
    methods: {
        handleCheck(id) {
            // console.log(id)
            //通知APP组件将对应的todo对象的done值取反
            this.checkTodo(id)
        },
        //删除
        handledelete(id) {
            if(confirm('确定删除吗?')){
                // console.log(id);
                this.deleteTodo(id);
            }
        }
    },
}
</script>

MyFooter.vue文件

<template>
    <div class="todo-footer" v-show="todos.length"> 
        <label>
            <input type="checkbox" @change='checkAll'/>
        </label>
        <span>
            <span>已完成{{doneTotal}}</span> / 全部{{todos.length}}
        </span>
        <button class="btn btn-danger" @click="clearAll">清除已完成任务</button>
    </div>
</template>

<script>
export default {
    name: 'MyFooter',
    props:['todos','checkAllTodo','clearAllTodo'],
    computed:{
        doneTotal(){
            //计已完成的个数
            let i=0;
            this.todos.forEach((todo) => {
                if(todo.done)
                i++;
            });
            return i;
        }
    },
    methods:{
        checkAll(e){
            // console.log(e.target.checked)
            this.checkAllTodo(e.target.checked);
        },
        clearAll(){
            this.clearAllTodo();
        }
    },
}
</script>

案例总结

1.组件化编码流程:
(1). 拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突.
(2). 实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:
1). 一个组件在用:放在组件自身即可.
​ 2).一些组件在用:放在他们共同的父组件上(状态提升)。
(3). 实现交互:从绑定事件开始.

2.props适用于:
​ (1). 父组件——>子组件 通信
(2).子组件——>父组件通信(要求父先给子一个函数)
注意:
props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。

3.使用v-model时要切记:
v-model绑定的值不能是props传过来的值,因为props是不可以修改的!

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以参考以下代码实现一个简单的 Vue TodoList: ``` <template> <div class="todo-list"> <h1>Vue TodoList</h1> <form @submit.prevent="addItem"> <input type="text" v-model="newItem" placeholder="Add item..."> <button type="submit">Add</button> </form> <ul> <li v-for="(item, index) in items" :key="index"> <span>{{ item }}</span> <button @click="deleteItem(index)">Delete</button> </li> </ul> </div> </template> <script> export default { data() { return { newItem: '', items: [] } }, methods: { addItem() { if (this.newItem !== '') { this.items.push(this.newItem); this.newItem = ''; } }, deleteItem(index) { this.items.splice(index, 1); } } } </script> <style> .todo-list { margin: 0 auto; max-width: 600px; } ul { list-style: none; margin: 0; padding: 0; } li { display: flex; justify-content: space-between; align-items: center; margin: 10px 0; padding: 10px; border: 1px solid #ccc; border-radius: 5px; } button { background-color: #f44336; color: #fff; border: none; border-radius: 5px; padding: 5px 10px; cursor: pointer; } button:hover { background-color: #d32f2f; } input[type="text"] { padding: 10px; border-radius: 5px; border: 1px solid #ccc; margin-right: 10px; font-size: 16px; } </style> ``` 在这个 TodoList 中,我们使用了 `v-model` 指令绑定 `newItem` 变量,通过 `addItem` 方法向 `items` 数组中添加新的项目,并使用 `v-for` 指令渲染出每个项目。同时,在每个项目中,我们添加了一个 `Delete` 按钮,用于删除对应的项目。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值