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>
相关推荐
喵叔哟16 分钟前
重构代码之取消临时字段
java·前端·重构
还是大剑师兰特1 小时前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts
王解1 小时前
【深度解析】CSS工程化全攻略(1)
前端·css
一只小白菜~1 小时前
web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
前端·javascript·pdf·windowopen预览pdf
方才coding1 小时前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
man20171 小时前
【2024最新】基于springboot+vue的闲一品交易平台lw+ppt
vue.js·spring boot·后端
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
丶21361 小时前
【WEB】深入理解 CORS(跨域资源共享):原理、配置与常见问题
前端·架构·web
发现你走远了1 小时前
『VUE』25. 组件事件与v-model(详细图文注释)
前端·javascript·vue.js