Vue中组件化编码 完成任务的添加、删除、统计、勾选需求(实战练习三完结)

简介: 这篇文章展示了如何在Vue中实现任务添加、删除、勾选和统计功能,通过组件间参数传递和方法实现,提供了App.vue、TheList.vue、TheItem.vue、TheHeader.vue和TheFooter.vue组件的主要代码示例。

上一个章节实现数据在组件之间的传递 。这一章主要是完成添加任务到任务栏、删除任务栏、统计任务完成情况。主要还是参数在各个组件之间的传递。
上一章节的链接地址:https://blog.csdn.net/weixin_43304253/article/details/126238030

文章目录

  • 1、实现的效果演示
  • 2、需求实现的大致流程
  • 3 、代码(这里只给出主要部分代码、详细代码请看第一章节)
    • 3.1 App.vue(省略了样式)
    • 3.2 TheList.vue (省略了样式)
    • 3.3 TheItem.vue(样式改进:删除按钮只有停留在对应行才会显示出来)
    • 3.4 TheHeader.vue (省略了样式)
    • 3.5 TheFooter.vue (省略了样式)
  • 4、实现的效果

1、实现的效果演示

Vue组件实战应用完成任务功能演示

2、需求实现的大致流程

  • 添加任务到任务栏:需要考虑TheHeader中的数据怎样传入到TheList组件中
  • 删除一个任务:需要拿到待删除的任务主键标识、然后在数组对象中删除(遍历的形式)
  • 勾选任务:根据对象中的勾状态、取反
  • 初次加载勾选已完成任务:在checkbox中 根据任务的状态展示完成情况(checked)
  • 统计任务完成情况:根据对象中的任务完成状态 遍历数组。累加计算

3 、代码(这里只给出主要部分代码、详细代码请看第一章节)

3.1 App.vue(省略了样式)

<template>
  <div id="root">
    <div class="todo-container">
      <div class="todo-wrap">
        <TheHeader :addTodo="addTodo" />
        <TheList
          :todos="todos"
          :checkTodo="checkTodo"
          :deleteTodo="deleteTodo"
        />
        <TheFooter
          :todos="todos"
          :checkAllTodo="checkAllTodo"
          :clearAllTodo="clearAllTodo"
        />
      </div>
    </div>
  </div>
</template>

<script>
import TheHeader from "./components/TheHeader";
import TheList from "./components/TheList";
import TheFooter from "./components/TheFooter.vue";

export default {
  name: "App",
  components: { TheHeader, TheList, TheFooter },
  data() {
    return {
      //由于todos是MyHeader组件和MyFooter组件都在使用,所以放在App中(状态提升)
      todos: [
        { id: "001", title: "吃饭", done: true },
        { id: "002", title: "睡觉", done: false },
        { id: "003", title: "打豆豆", done: true },
      ],
    };
  },
  methods: {
    //添加一个todo
    addTodo(todoObj) {
      this.todos.unshift(todoObj);
    },
    //勾选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);
    },
    //全选or取消全选
    checkAllTodo(done) {
      this.todos.forEach((todo) => {
        todo.done = done;
      });
    },
    //清除所有已经完成的todo
    clearAllTodo() {
      this.todos = this.todos.filter((todo) => {
        return !todo.done;
      });
    },
  },
};
</script>

3.2 TheList.vue (省略了样式)

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

<script>
import TheItem from "./TheItem";

export default {
  name: "TheList",
  components: { TheItem },
  //声明接收App传递过来的数据,其中todos是自己用的
  props: ["todos", "checkTodo",'deleteTodo'],
};
</script>

3.3 TheItem.vue(样式改进:删除按钮只有停留在对应行才会显示出来)

<template>
  <li>
    <label>
      <input
        type="checkbox"
        :checked="todo.done"
        @change="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、checkTodo、deleteTodo
  props: ["todo", "checkTodo",'deleteTodo'],

  methods: {
    //勾选or取消勾选
    handleCheck(id) {
      //通知App组件将对应的todo对象的done值取反
      this.checkTodo(id);
    },
    //删除
    handleDelete(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>

3.4 TheHeader.vue (省略了样式)

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

<script>
import { nanoid } from "nanoid";
export default {
  name: "TheHeader",
    //接收从App传递过来的addTodo
        props:['addTodo'],
  data() {
    return {
      //收集用户输入的title
      title: "",
    };
  },
  methods: {
    add() {
      //校验数据
      if (!this.title.trim()) return alert("输入不能为空");
      //将用户的输入包装成一个todo对象
      const todoObj = { id: nanoid(), title: this.title, done: false };
      //通知App组件去添加一个todo对象
      this.addTodo(todoObj);
      //清空输入
      this.title = "";
    },
  },
};
</script>

3.5 TheFooter.vue (省略了样式)

<template>
    <div class="todo-footer" v-show="total">
        <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:'TheFooter',
        props:['todos','checkAllTodo','clearAllTodo'],
        computed: {
            //总数
            total(){
                return this.todos.length
            },
            //已完成数
            doneTotal(){
                //此处使用reduce方法做条件统计
                /* const x = this.todos.reduce((pre,current)=>{
                    console.log('@',pre,current)
                    return pre + (current.done ? 1 : 0)
                },0) */
                //简写
                return this.todos.reduce((pre,todo)=> pre + (todo.done ? 1 : 0) ,0)
            },
            //控制全选框
            isAll:{
                //全选框是否勾选
                get(){
                    return this.doneTotal === this.total && this.total > 0
                },
                //isAll被修改时set被调用
                set(value){
                    this.checkAllTodo(value)
                }
            }
        },
        methods: {
            /* checkAll(e){
                this.checkAllTodo(e.target.checked)
            } */
            //清空所有已完成
            clearAll(){
                this.clearAllTodo()
            }
        },
    }
</script>

4、实现的效果

在这里插入图片描述


整理不易、欢迎白嫖党一键三连 !!! 哈哈哈哈哈哈哈哈哈。曾经我也是白嫖党

相关文章
|
4天前
|
JavaScript
Vue基础知识总结 4:vue组件化开发
Vue基础知识总结 4:vue组件化开发
|
4天前
|
存储 JavaScript
Vue 状态管理工具vuex
Vue 状态管理工具vuex
|
9天前
|
JavaScript
如何在 Vue 中使用具名插槽
【10月更文挑战第25天】通过使用具名插槽,你可以更好地组织和定制组件的模板结构,使组件更具灵活性和可复用性。同时,具名插槽也有助于提高代码的可读性和可维护性。
14 2
|
9天前
|
JavaScript
Vue 中的插槽
【10月更文挑战第25天】插槽的使用可以大大提高组件的复用性和灵活性,使你能够根据具体需求在组件中插入不同的内容,同时保持组件的结构和样式的一致性。
12 2
|
11天前
|
数据采集 监控 JavaScript
在 Vue 项目中使用预渲染技术
【10月更文挑战第23天】在 Vue 项目中使用预渲染技术是提升 SEO 效果的有效途径之一。通过选择合适的预渲染工具,正确配置和运行预渲染操作,结合其他 SEO 策略,可以实现更好的搜索引擎优化效果。同时,需要不断地监控和优化预渲染效果,以适应不断变化的搜索引擎环境和用户需求。
|
14天前
|
JavaScript
Vue 指令速查表
【10月更文挑战第12天】Vue 指令速查表
|
11天前
|
缓存 JavaScript 搜索推荐
Vue SSR(服务端渲染)预渲染的工作原理
【10月更文挑战第23天】Vue SSR 预渲染通过一系列复杂的步骤和机制,实现了在服务器端生成静态 HTML 页面的目标。它为提升 Vue 应用的性能、SEO 效果以及用户体验提供了有力的支持。随着技术的不断发展,Vue SSR 预渲染技术也将不断完善和创新,以适应不断变化的互联网环境和用户需求。
30 9
|
10天前
|
缓存 JavaScript UED
Vue 中实现组件的懒加载
【10月更文挑战第23天】组件的懒加载是 Vue 应用中提高性能的重要手段之一。通过合理运用动态导入、路由配置等方式,可以实现组件的按需加载,减少资源浪费,提高应用的响应速度和用户体验。在实际应用中,需要根据具体情况选择合适的懒加载方式,并结合性能优化的其他措施,以打造更高效、更优质的 Vue 应用。
|
9天前
|
前端开发 JavaScript 容器
在 vite+vue 中使用@originjs/vite-plugin-federation 模块联邦
【10月更文挑战第25天】模块联邦是一种强大的技术,它允许将不同的微前端模块组合在一起,形成一个统一的应用。在 vite+vue 项目中,使用@originjs/vite-plugin-federation 模块联邦可以实现高效的模块共享和组合。通过本文的介绍,相信你已经了解了如何在 vite+vue 项目中使用@originjs/vite-plugin-federation 模块联邦,包括安装、配置和使用等方面。在实际开发中,你可以根据自己的需求和项目的特点,灵活地使用模块联邦,提高项目的可维护性和扩展性。
|
10天前
|
JavaScript 前端开发 UED
vue 提高 tree shaking 的效果
【10月更文挑战第23天】提高 Vue 中 Tree shaking 的效果需要综合考虑多个因素,包括模块的导出和引用方式、打包工具配置、代码结构等。通过不断地优化和调整,可以最大限度地发挥 Tree shaking 的优势,为 Vue 项目带来更好的性能和用户体验。