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>
相关推荐
秋子aria2 分钟前
模块的原理及使用
前端·javascript
菜市口的跳脚长颌2 分钟前
一个 Vite 打包配置,引发的问题—— global: 'globalThis'
前端·vue.js·vite
胖虎2652 分钟前
实现无缝滚动无滚动条的 Element UI 表格(附完整代码)
前端·vue.js
小左OvO3 分钟前
基于百度地图JSAPI Three的城市公交客流可视化(一)——线路客流
前端
星链引擎5 分钟前
企业级智能聊天机器人 核心实现与场景落地
前端
GalaxyPokemon7 分钟前
PlayerFeedback 插件开发日志
java·服务器·前端
爱加班的猫7 分钟前
深入理解防抖与节流
前端·javascript
用户12039112947268 分钟前
从零实现AI Logo生成器:前端开发者的DALL-E 3实战指南
javascript
信码由缰12 分钟前
Java智能体框架的繁荣是一种代码异味
javascript·ai编程
自由日记22 分钟前
学习中小牢骚1
前端·javascript·css