基于Vue组件实现TodoList

51 篇文章 2 订阅
35 篇文章 3 订阅
本文详细解析了一个基于Vue的TodoList应用的实现,包括任务渲染、内容添加、任务计数、复选框交互及任务删除等功能。通过组件化的方式,分别介绍了UserHeader、UserList和UserFooter组件的实现细节,涉及数据传递、计算属性和事件处理等关键点,为读者提供了完整的Vue组件交互示例。
摘要由CSDN通过智能技术生成

查看整体的效果哈 

实现功能:

1、将已有的任务渲染到页面

2、在输入框中输入内容后按enter键,即可把内容添加到下面的列表中(如果内容为空则不添加)

3、动态计算有几个已完成的任务以及所有的任务

4、点击复选框,实现选中或不选中效果(即完成或未完成)

5、删除单个任务以及删除已完成任务

下面这个图是我分析拆分组件的 

所拆分的组件有:管理所有的组件App[ Header组件、List组件[Item组件]、Footer组件]

💗 功能一:将已有的任务渲染到页面

我们知道data数据是放到所对应的组件里面,由于功能都需要用到data数据,则将数据放到管理所有子组件的父组件App上面

通过v-for指令将数据渲染到页面

UserList组件

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


<script>
import UserItem from "./UserItem.vue";

export default {
  name: "UserList",
  components: { UserItem },
  props: ["todos", "checktodo", "deletetodo"],
};
</script>

UserItem组件

<template>
  <li>
    <label>
      <input
        type="checkbox"
        :checked="todo.done"
      />
      <span>{{ todo.title }}</span>
    </label>
    <button class="btn btn-danger"">删除</button>
  </li>
</template>

<script>
export default {
  name: "UserItem",
  props: ["todo"]
};
</script>

💗 功能二: 在输入框中输入内容后按enter键,即可把内容添加到下面的列表中(如果内容为空则不添加)

在UserHeader.vue组件里面为表单绑定一个回车事件,配置一个add事件,添加一个任务

 <input
      type="text"
      placeholder="请输入你的任务名称,按回车键确认"
      @keyup.enter="add"
      v-model="title"
    />

如何通知App组件去添加一个todo对象 也就是将包装好的todoObj对象传递给App组件?

利用props配置可以实现父组件给子组件传值的操作,此功能需求得实现子组件传值给父组件的操作

因为添加任务的是由UserHeader组件添加数据到UserList组件,而两者的关系是兄弟关系,只有借助它们共同的父组件进行间接传值的操作

思路:父组件提前给子组件传递一个函数,子组件将需要传递给父组件的值通过参数的形式传递

 App组件提前给子组件传递一个函数addtodo

 <UserHeader :addtodo="addtodo" />

 methods: {
    //添加一个todoObj
    addtodo(todoObj) {
      //往data里面添加数据,data数据改变了,重新解析模版
      this.todos.unshift(todoObj);
    },

UserHeader子组件:

随机生成一个唯一的id

安装:  npm i nanoid 

导入:import {nanoid} from 'nanoid'

使用:id: nanoid()

 props: ["addtodo"],
  methods: {
    add() {
      //校验数据
      if (!this.title.trim()) {
        alert("数据不能为空");
      }
      //添加一个信息 也可以直接用e.target.value拿到这个输入的值
      // 将用户的输入包装成一个todoObj对象
      const todoObj = { id: nanoid(), title: this.title, done: false };
      //通知App组件去添加一个todo对象 也就是将包装好的todoObj对象传递给App组件
      this.addtodo(todoObj);
      //清空输入
      this.title = " ";
    },
  },

💗 功能三: 动态计算有几个已完成的任务以及所有的任务

此时需要在UserFooter组件中通过计算属性计算得出已完成的任务

computed: {
    doneTotal() {
      return this.todos.reduce((pre, todo) => pre + (todo.done ? 1 : 0), 0);
    },
  },

arry.reduce()方法:

reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

返回值分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值


第一个参数:累计器累计回调的返回值; 它是上一次调用回调时返回的累积值

第二个参数:数组中正在处理的元素。 

计算所有的任务

方法一:最简单的方法

todos.length

 第二种:计算得出

 total() {
      return this.todos.length;
    },

💗 功能四、点击复选框,实现选中或不选中效果(即完成或未完成)双向绑定

借助UserList 组件实现UserItem和App组件之间互相传值

UserItem组件:

<script>
export default {
  name: "UserItem",
  props: ["todo", "checktodo"],
  methods: {
    handlechack(id) {
      //通知App组件将对应的todo对象的done值取反
      this.checktodo(id);
    },
  },
};
</script>

UserFooter组件:

isAll: {
      get() {
        //返回的是布尔值
        return this.doneTotal === this.total && this.total > 0;
      },
      set(value) {
        this.checkAlltodo(value);
      },
    },

App 组件:

methods: {

    //勾选或者取消勾选一个todo
    checktodo(id) {
      this.todos.forEach((todo) => {
        if (todo.id === id) {
          todo.done = !todo.done;
        }
      });
    },
    //全选或不全选todoObj
    checkAlltodo(done) {
      this.todos.forEach((todo) => {
        todo.done = done;
      });
    },
  },

💗 功能五、删除单个任务以及删除已完成任务

App.vue 组件

<template>
  <div id="root">
    <div class="todo-container">
      <div class="todo-wrap">
        <!-- 为了让儿子能给父亲传递值,所以父亲准备一个函数接受儿子传递过来的参数 -->
        <UserHeader :addtodo="addtodo" />
        <UserList
          :todos="todos"
          :checktodo="checktodo"
          :deletetodo="deletetodo"
        />
        <UserFooter
          :todos="todos"
          :checkAlltodo="checkAlltodo"
          :clearAlltodo="clearAlltodo"
        />
      </div>
    </div>
  </div>
</template>


methods: {
  
    //删除选中的todoObj
    deletetodo(id) {
      this.todos = this.todos.filter((todo) => {
        //将id不等于当前删除的那个id,的todoObj筛选出来重新渲染
        return todo.id !== id;
      });
    },
    
    //删除已完成
    clearAlltodo() {
      this.todos = this.todos.filter((todo) => {
        return !todo.done;
      });
    },
  },

UserItem.vue组件 - 删除单个任务

<template>
    <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
</template>

<script>
export default {
  name: "UserItem",
  props: ["deletetodo"],
  methods: {
    handleDelete(id) {
      if (confirm("确定删除吗? ")) {
        //通知App组件将对应的todo对象删除
        this.deletetodo(id);
      }
    },
  },
};
</script>

 UserFooter.vue 组件-- 删除已完成任务

  methods: {
    //删除已完成
    clearAll() {
      this.clearAlltodo();
    },
  },

以上就是基于Vue组件实现的一个TodoList 案例,代码不全,但是每个功能都分析了,我相信你是可以哒

 

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奶茶丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值