• TODOS案例


    目标成品图:
    在这里插入图片描述
    css样式从简

    结构样式

    1:创建3个组件和里面的代码还有样式

    2:APP.vue中引入三个组件

    渲染任务列表

    需求:把任务列表展示到页面TodoMain.vue中
    需求:选中状态 设置相关的样式
    
    • 1
    • 2

    步骤:

    • App.vue 中定义数组传入TodoMain.vue组件中
    • v-for循环展示数据
    • v-model绑定复选框选中状态
    • 根据选中状态 设置样式
    //app.vue
    <todo-main :arr="list"></todo-main>
    data() {
        return {
          list: [
            { id: 100, name: '吃饭', ischeck: false },
            { id: 101, name: '睡觉', ischeck: false },
            { id: 102, name: '打豆豆', ischeck: false },
          ],
        }
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    //TodoMain.vue
    <template>
      <div class="main">
        <ul>
          <li v-for="item in arr" :key="item.id">
            <div class="left">
              <input type="checkbox" v-model="item.ischeck" />
              <span :class="{ undeline: item.ischeck }">
                {{ item.name }}
              span>
            div>
            <button>删除button>
          li>
        ul>
      div>
    template>
    
    <script>
    export default {
      props: ['arr'],
    }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    添加任务

    需求:输入任务回车,新增任务
    
    • 1
    • TodoHead.vue 输入框 --键盘事件—回车

    • 子传父 把任务 —App.vue中 加入到数组中

    • 数组改变,所有用到数组的地方都会更新

    • 输入框为空,提示用户必须输入内容

      //TodoHead.vue
      <input type="text" v-model="name" @keyup.enter="addFn" />
      
        methods: {
          addFn() {
            // 非空判断
            if (this.name.trim().length === 0) {
              alert('任务内容不能为空')
              return
            }
            // 子传父
            this.$emit('create', this.name)
      
            this.name = ''
          },
        },
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      //App.vue
      <todo-head @create="createFn"></todo-head>
      
      methods: {
          createFn(name) {
            var id =
              this.list.length === 0 ? 100 : this.list[this.list.length - 1].id + 1
            this.list.push({
              id: id,
              name: name,
              ischeck: false,
            })
          },
        },
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14

    删除任务

    • 删除按钮–点击事件 传id
    • 子传父-把id传给App.vue 删除数组list里对应的对象
    • 数组改变所有用到数组的地方都会更新
    //App.vue
    <todo-main :arr="list" @delEvent="deleteFn"></todo-main>
    
      methods: {
        deleteFn(id) {
          // 删除
          let index = this.list.findIndex((item) => item.id === id)
          this.list.splice(index, 1)
        },
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    //TodoMain.vue
     <button @click="delFn(item.id)">删除</button>
     
       methods: {
        delFn(id) {
          // 子传父
          this.$emit('delEvent', id)
        },
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    顶部统计

    统计当前任务的条数

    步骤:

    • App.vue中把数组list传给TodoFoot组件
    • 直接在标签上显示or使用计算属性显示
    //TodoFoot.vue
    <template>
      <div class="todo-foot">
        <div>剩余{{ farr.length }}---{{ allNum }}div>
        <ul>
          <li>全部li>
          <li class="active">已完成li>
          <li>未完成li>
        ul>
        <button>清除已完成button>
      div>
    template>
    
    <script>
    export default {
      props: ['farr'],
      computed: {
        // 计算属性
        allNum() {
          return this.farr.length
        },
      },
    }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    数据切换

    点击底部切换,点谁谁有边框样式

    对应切换不同的数据展示

    步骤:

    • TodoFoot.vue中,定义isSel 值为all,yes,no中的一个,默认为all
    • 多个class分别判断谁应该有类名active
    • 点击修改isSel的值
    • 子传父,把isSel传到App.vue中
    • 定义计算属性,从list过滤数据 给TodoMain
    //App.vue
    <todo-main :arr="showArr" @delEvent="deleteFn">todo-main>
    <todo-foot :farr="showArr" @changType="typeFn">todo-foot>
    
    <script>
    export default {
      data() {
        return {
    
          getSel: 'all', //默认显示全部
        }
      },
      computed: {
        showArr() {
          switch (this.getSel) {
            case 'all':
              return this.list
              break
            case 'yes':
              return this.list.filter((item) => item.ischeck === true)
              break
            case 'no':
              return this.list.filter((item) => item.ischeck === false)
              break
          }
        },
      },
      methods: {
        typeFn(sel) {
          //点击底部的类型
          this.getSel = sel
        },
      },
    }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    //TodoFoot.vue
    <ul @click="fn">
          <li @click="isSel = 'all'" :class="{ active: isSel === 'all' }">全部</li>
          <li @click="isSel = 'yes'" :class="{ active: isSel === 'yes' }">
            已完成
          </li>
          <li @click="isSel = 'no'" :class="{ active: isSel === 'no' }">未完成</li>
    </ul>
    
    export default {
      data() {
        return {
          // 1变量isSel
          isSel: 'all', //all 全部  yes已完成  no未完成
        }
      },
      methods: {
        fn() {
          // 点击全部,已完成,未完成
          // 2子--->父  把isSel的值传给App.vue
          this.$emit('changType', this.isSel)
        },
      },
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    清除已完成

    点击清空按钮,把已完成的任务清空

    步骤:

    • 给按钮添加点击事件
    • 子传父 --App.vue 调用清空方法
    • 过滤未完成的覆盖list数组
    //TodoFoot.vue
    <button @click="clearFn">清除已完成</button>
    
    methods:{
     fn() {
          // 点击全部,已完成,未完成
          // 2子--->父  把isSel的值传给App.vue
          this.$emit('changType', this.isSel)
     },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    //App.vue
     methods: {
        clearFun() {
          // 清空已完成
          this.list = this.list.filter((item) => item.ischeck == false)
        },
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    数据缓存

    页面刷新后数据还存在

    步骤:

    • App.vue中监听list–存储到本地
    • data中list 从本地读取
    
    data() {
        return {
          list: JSON.parse(localStorage.getItem('list') || '[]'),
          getSel: 'all', //默认显示全部
        }
      },
      watch: {
        list: {
          deep: true,
          handler(newval) {
            localStorage.setItem('list', JSON.stringify(newval))
          },
        },
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    全选

    点击全选 —小选框状态和全选状态一样

    小选框都选中(手选)—全选会自动选中

    步骤:

    • TodoHeader.vue 计算属性----isAll
    • App.vue 给TodoHeader.vue传入数组list 在isAll的set里影响小选框
    • isAll的get里统计小选框最后状态,影响isAll —影响全选状态
    • 考虑无数据情况—全选不应该勾选
    //TodoHead.vue
    
    <input type="checkbox" v-model="isAll" />
     
     computed: {
        isAll: {
          set(checked) {
            // 影响数组里每个小选框绑定的ischeck属性
            this.list.forEach((item) => {
              item.ischeck = checked
            })
          },
          get() {
            // 小选框统计状态--->全选框
            return (
              this.list.length !== 0 &&
              this.list.every((item) => item.ischeck === true)
            )
          },
        },
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    //App.vue
    <todo-head :list="list" @create="createFn">todo-head>
    
    • 1
    • 2

    哪天需要了,可以去下载地址

  • 相关阅读:
    Centos使用tomcat部署jenkins
    基于Java的医院预约挂号管理系统设计与实现(源码+lw+部署文档+讲解等)
    SpringBoot集成百度AI实现人脸识别
    分布式任务调度Schedulerx2.0工作原理
    1022D进制的A+B(满分)
    Linux:文件IO
    反碎片化技术(外部碎片)的原理
    高性能计算和并行计算的关系
    http头各字段含义
    高效人生的12个关键点
  • 原文地址:https://blog.csdn.net/qq_45025670/article/details/126365848