Vue 2 TodoList 案例

组件化编码流程(通用)

1.实现静态组件:抽取组件,使用组件实现静态页面的效果

结构

2.代码

1.App.vue

html 复制代码
<template>
  <div id="appContainer">
    <TodoComponent/>
  </div>
</template>

<script>
import TodoComponent from './components/TodoComponent.vue';
export default {
  name: "App",
  components: {
    TodoComponent
  }
};
</script>

<style>
#appContainer{
  display: flex;
  justify-content: center;
}
</style>

2.TodoComponent.vue

html 复制代码
<template>
  <div id="container">
    <div id="parent">
      <TodoHeader  :addTodo="addTodo"/>
      <TodoList  :todos="todos" />
      <TodoFooter  :finish="finish" :all="all" :clear="clear" :doneAll="doneAll" />
    </div>
  </div>
</template>

<script>
import TodoFooter from "./TodoFooter.vue";
import TodoHeader from "./TodoHeader.vue";
import TodoList from "./TodoList.vue";

export default {
  name: "TodoComponent",
  components: {
    TodoFooter,
    TodoHeader,
    TodoList,
  },
  data() {
    return {
      todos:[
            {id:'001',title:'吃饭',done:true},
            {id:'002',title:'睡觉',done:false},
            {id:'003',title:'喝酒',done:true},
            {id:'004',title:'开车',done:true},
            {id:'005',title:'打游戏',done:false},
            {id:'006',title:'随便',done:false},
            {id:'007',title:'创业',done:false},
        ]
    }
  },
  methods:{
    addTodo(x){
      console.log("我是Todo组件,我收到了数据",x);
      this.todos.unshift(x);
    },
    clear(){
      console.log('清除了');
      
      const idList = this.todos.filter(x=>x.done).map(x=>x.id);
   
      for(let i=0;i<this.todos.length;i++){
        if(idList.includes(this.todos[i].id)){
          this.todos.splice(i,1);
          i--;
        }
      }

      console.log(this.todos);
      
   },
    doneAll(choose){
      this.todos.forEach(x=>x.done=choose)
    }
  },
  computed:{
    finish(){
      return this.todos.filter(x=>x.done).length;
    },
    all(){
      return this.todos.length;
    }

  }
};
</script>

<style scoped>


#parent {
  width: 600px;
  border: 1px solid #ccc;
  display: flex;
  justify-content: center; /*  水平居左 */
  align-items: center; /* 垂直居中 */
  flex-direction: column; /* 垂直排列子元素 */
}
#parent > *{
    margin: 10px 0px;
}


</style>

3.TodoFooter.vue

html 复制代码
<template>
  <div id="container" v-show="all>0">
    <div>
      <input type="checkbox" v-model="allChoose" @change="doneAll(allChoose)"/>
      <label>已完成{{finish}} / 全部{{all}}</label>
    </div>
    <button id="button" @click="clear">清除已完成的任务</button>
  </div>
</template>

<script>
export default {
  name: "TodoFooter",
  data() {
    return {
      allChoose:false
    }
  },
  updated() {
        
        if(this.finish ===this.all && this.all > 0){
          this.allChoose = true;
        }else if(this.finish < this.all && this.all > 0){
           this.allChoose = false;
        }

//双向绑定可以绑定 计算属性 前提是计算属性要写 setter


    },
  props:['finish','all','clear','doneAll']
};
</script>

<style scoped>
#container {
  display: flex;
  justify-content: space-between; /*  水平居左 */
  width: 500px;
  height: 30px;
  padding: 10px;
}
#container *{
  padding: 5px;
}

#button {
  width: 140px;
  height: 28px;
  color: white;
  background-color: #eb1212;
  border: 1px solid #ccc;
  border-radius: 5px;
  padding: 5px;
  margin-right: 15px;
  cursor: pointer; /* 鼠标悬停时显示手型光标 */
  transition: background-color 0.3s ease; /* 平滑过渡 */
}

#button:hover {
  background-color: #d10d0d; /* 鼠标悬停时颜色变化 */
}

#button:active {
  background-color: #a00; /* 按下时颜色变化 */
  transform: translateY(2px); /* 按下时按钮下移效果 */
}

</style>

4.TodoHeader.vue

html 复制代码
<template>
  <div>
    <input
      id="headerInput"
      type="text"
      placeholder="请输入你的任务名称,按回车键确认"
      v-model="title"
      @keyup.enter="submit"
    />
  </div>
</template>

<script>
import { nanoid } from "nanoid"; //函数

export default {
  name: "TodoHeader",
  data() {
    return {
      title: "",
    };
  },
  props: ["addTodo"],
  methods: {
    submit() {
      //将用户的输入包装成一个todo对象
      if (this.title.trim() === "") {
        alert("输入不能为空");
        return;
      }

      const todoObj = {
        id: nanoid(),
        title: this.title,
        done: false,
      };
     this.addTodo(todoObj);
     this.title = "";

      //安装一些 nanoid  npm i nanoid
    },
  },
};
</script>

<style scoped>
#headerInput {
  width: 498px;
  height: 30px;
  border: 1px solid #ccc;
  border-radius: 2px;
  padding-left: 10px;
}
</style>

5.TodoItem.vue

html 复制代码
<template>
  <div id="container" @mouseover="handleMouseOver"  @mouseleave="handleMouseLeave" >
    <div id="d" >
      <input type="checkbox" v-model="todo.done" />
      <span @click="info">{{ todo.title }}</span>
    </div>
    <button id="button" v-show="showDelete" @click="deleteTodo">删除</button>
  </div>
</template>

<script>
export default {
  name: "TodoItem",
  data() {
    return {
      todo: this.todoObj,
      showDelete: false,
    };
  },
  methods: {
    info() {
      console.log(this.todo);
    },
    handleMouseOver() {
      this.showDelete = true;
    },
    handleMouseLeave() {
      this.showDelete = false;
    },
    deleteTodo(){
        this.removeTodo(this.todoObj.id)
    }
  },
  props: {
    todoObj: {
      //传入的若是引用对象 则里面修改了,外面同样生效
      type: Object,
      required: true,
    },
    removeTodo:{
      type:Function,
    }
  },
};
</script>

<style scoped>

#container:hover{
  background-color: #a09a9a;
}

#container {
  display: flex;
  justify-content: space-between; /*  水平居左 */
  align-items: center; /* 垂直居中 */
  width: 500px;
  height: 30px;
  border: 0.1px solid #ccc;
  border-radius: 2px;
  padding-left: 10px;
  padding-top: 5px;
  padding-bottom: 5px;
}

#container * {
  padding: 5px;
}



#button {
  width: 50px;
  height: 28px;
  color: white;
  background-color: #eb1212;
  border: 1px solid #ccc;
  border-radius: 5px;
  padding: 5px;
  margin-right: 15px;
  cursor: pointer; /* 鼠标悬停时显示手型光标 */
  transition: background-color 0.3s ease; /* 平滑过渡 */
}
#button:hover {
  background-color: #d10d0d; /* 鼠标悬停时颜色变化 */
}

#button:active {
  background-color: #a00; /* 按下时颜色变化 */
  transform: translateY(2px); /* 按下时按钮下移效果 */
}
</style>

6. TodoList.vue

html 复制代码
<template>
  <div>
    <TodoItem v-for="item in todosList" :key="item.id" :todoObj="item" :removeTodo="deleteTodo" />
   
  </div>
</template>

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

export default {
    name:'TodoList',
    components:{
      TodoItem
    },
    data() {
      return {
        todosList: this.todos
      }
    },
    methods:{
      deleteTodo(id){
        
          for(var i=0;i<this.todosList.length;i++){
            if(this.todosList[i].id===id){
              console.log(i,"下标");
              
              break;
            }
          }

         this.todosList.splice(i,1);

      }

    },
    props:['todos']

}
</script>

<style scoped>

</style>
相关推荐
red润3 分钟前
使用 HTML5 Canvas 实现动态蜈蚣动画
前端·html·html5
sg_knight11 分钟前
VSCode如何修改默认扩展路径和用户文件夹目录到D盘
前端·ide·vscode·编辑器·web
一个处女座的程序猿O(∩_∩)O20 分钟前
完成第一个 Vue3.2 项目后,这是我的技术总结
前端·vue.js
mubeibeinv21 分钟前
项目搭建+图片(添加+图片)
java·服务器·前端
逆旅行天涯27 分钟前
【Threejs】从零开始(六)--GUI调试开发3D效果
前端·javascript·3d
m0_748255261 小时前
easyExcel导出大数据量EXCEL文件,前端实现进度条或者遮罩层
前端·excel
长风清留扬1 小时前
小程序毕业设计-音乐播放器+源码(可播放)下载即用
javascript·小程序·毕业设计·课程设计·毕设·音乐播放器
web147862107231 小时前
C# .Net Web 路由相关配置
前端·c#·.net
m0_748247801 小时前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
飞的肖1 小时前
前端使用 Element Plus架构vue3.0实现图片拖拉拽,后等比压缩,上传到Spring Boot后端
前端·spring boot·架构