【Vue案例】使用Vue实现doList任务队列

本文详细介绍了Vue.js项目中的关键配置文件、组件结构和数据传递。主要包括Vue.config.js中关于依赖转译和ESLint检查的配置,main.js和App.vue的入口文件及组件引用,以及App.vue、MyHeader.vue、MyList.vue和MyFooter.vue组件的模板、脚本和样式,展示了组件间如何通过props和事件进行数据交换。

效果图


文件关系图


1.Vue.config.js

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave:false
})

Vue.js项目的配置文件。使用@vue/cli-service模块中的defineConfig方法定义配置对象

配置项:

  1. transpileDependencies:true:表示在构建过程中对依赖进行转译,确保项目的兼容性。默认情况下,Babel只会对Vue CLI创建的项目自身代码进行转译,而不会对依赖的第三方库进行转译;

  2. lintOnSave:false:表示在保存文件时,是否启用ESLint进行代码检查。设置为false后保存文件不会触发ESLint的检查;


2. main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

Vue.js应用程序的入口文件

  • 导入Vue.js模块,并赋值给变量Vue;

  • 从当前目录导入App.vue文件,并赋值给变量App;

  1. Vue.config.productionTip=false:禁用生产模式下的一些提示信息;

  2. new Vue():创建一个Vue实例,将App组件作为根组件进行渲染。在render函数中使用箭头函数的简写语法将h(createElement)参数传递进去,并返回了App组件的渲染结果;

  3. $mount('#app')将Vue实例挂载到HTML中具有id="app"的元素上,并显示在页面上;


3. App.vue

3.1.template

<template>
  <div id="App">
    <MyHeader :addTodo="addTodo"></MyHeader>
    <MyList :deleteTodo="deleteTodo" :checkTodo="checkTodo" :todos="todos"></MyList>
    <MyFooter :todos="todos" :checkAllTodo="checkAllTodo" :clearAllTodo="clearAllTodo"></MyFooter>
  </div>
</template>

App.vue的template部分的描述

  1. 定义一个idAppdiv块级元素;

  2. 使用自定义组件MyHeader传递一个属性addTodoaddTodo属性指向父组件中的一个方法addTodo,实现子组件向父组件传递数据的功能;

  3. 使用自定义组件MyList传递三个属性deleteTodocheckTodotodos,这些属性指向父组件中的三个方法和一个数据,实现子组件向父组件传递数据和方法的功能;

  4. 使用自定义组件MyFooter传递三个属性todoscheckAllTodoclearAllTodo,这些属性指向子组件中的一个数据和两个方法,实现子组件向父组件传递数据和方法的功能;

3.2.script

<script>
import MyHeader from "@/components/MyHeader.vue";
import MyList from "@/components/MyList.vue";
import MyFooter from "@/components/MyFooter.vue";

export default {
  name: 'App',
  data(){
    return{
      todos:[
        {id:'001',title:'测试数据A',done:false},
        {id:'002',title:'测试数据B',done:false},
        {id:"003",title:'测试数据C',done:false}
      ]
    }
  },
  methods:{
    //添加任务
    addTodo(todoObj){

      this.todos.unshift(todoObj);
      console.log("addTodo("+todoObj+")");
    },
    //勾选或者取消一个任务
    checkTodo(id){
      this.todos.forEach(item =>{
        if(item.id == id){
          item.done = !item.done;
          console.log("checkTodo("+id+"):"+item.done!=item.done);
          return;
        }
      })
    },
    deleteTodo(id){
      this.todos = this.todos.filter(item =>{
        console.log("deleteTodo("+id+"):"+item.id !=id);
        return item.id !=id;
      })
    },
    checkAllTodo(done){
      console.log("checkAllTodo("+done+")");
      this.todos.forEach(item=> item.done =done);
    },
    clearAllTodo(){
      console.log("clearAllTodo():"+ this.todos.filter(item => !item.done));
      this.todos = this.todos.filter(item => !item.done);
    }
  },
  components: {MyFooter, MyList, MyHeader}
}
</script>

App.vue的script部分的表述

  1. 使用import引入MyHeaderMyListMyFooter三个自定义组件;

  2. 通过export default导入当前Vue组件的配置;

  3. components属性是一个对象,包含了三个键值对,对应引入的三个自定义组件:MyFooterMyListMyHeader;

  • name属性用于指定当前组件的名称;

  • data方法返回一个对象,对象中有一个todos的属性,包含了三个任务对象;每个任务对象都有id:任务的唯一标识,title:标题,done:完成状态;

  • addTodo方法用于向任务列表中添加一个新的任务对象,通过unshift方法将任务对象插入到todos数组的开头;

  • checkTodo方法用于勾选或取消一个任务,通过遍历todos数组找到对应的任务,并修改done属性的值;

  • deleteTodo方法用于删除一个任务,通过使用filter方法过滤掉要删除的任务,并重新赋值给todos数组;

  • checkAllTodo方法用于全选或取消全选任务,遍历todos数组将所有任务的done属性设置为传入的值;

  • clearAllTodo方法用于清楚所有已完成的任务,通过使用filter方法过滤掉已完成的任务,并重新赋值给todos数组;

3.3.style

<style>
h2{
  color: orange;
}
</style>

4. MyHeader.vue

4.1.template

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

MyHeader.vue的template部分的描述

  1. 定义一个包含输入框<input>元素的<div>块级元素;

  2. 使用v-model绑定title属性;

  3. 使用@keydown.enter="add"监听键盘的Enter事件,触发时调用add方法;

4.2.script

<script>
import {nanoid} from "nanoid";
export default {
  name: "MyHeader",
  props:['addTodo'],
  data(){
    return{
      title:''
    }
  },
  methods:{
    add(){
      let todoObj ={id:nanoid(),title:this.title,done:false};
      console.log("MyHeader:add():"+todoObj);
      this.addTodo(todoObj);
      this.title ='';
    }
  }
}
</script>

MyHeader.vue的script部分的描述

  1. 导入nanoid函数;

  2. 通过export default导入当前Vue组件的配置;

  • 定义名为MyHeader的组件;

  • 使用props属性声明一个名为addTodo的prop菜鸟教程对prop的描述

  • data方法中初始化一个名为title的属性;

  • 定义一个名为add的方法,在用户按下Enter键时会创建一个包含输入内容的todo对象,然后通过addTodoprop将该对象传递给父组件,最后清空输入框内容;

4.3.style

<style scoped>
.header input {
  width: 560px;
  height: 28px;
  font-size: 14px;
  border: 1px solid #ccc;
  border-radius: 4px;
  padding: 4px 7px;
}

.header input:focus {
  outline: none;
  border-color: rgba(82, 168, 236, 0.8);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(82, 168, 236, 0.6);
}
</style>

5. MyItem.vue

5.1.template

<template>
  <li>
    <label>
      <input type="checkbox" @click="handleCheck(todo.id)" :checked="todo.done"/>
      <span>{{todo.title}}</span>
    </label>
    <button class="btn" @click="handleDelete(todo.id,todo.title)">删除</button>
  </li>
</template>

MyItem.vue的template部分的描述

  1. 定义一个type属性为checkbox的复选框输入类型的input元素;

  2. 通过@click事件监听器绑定一个handleCheck(todo.id)的点击事件处理函数,复选框被点击时触发;

  3. :checked用于动态绑定复选框的选中状态;

  4. 绑定todo.done属性根据todo对象的done属性确定是否选中复选框;

  5. 定义一个button元素,通过@click事件监听器绑定一个;handleDelete(todo.id,todo.title)点击事件处理函数,当按钮被点击时会触发,并传递todo.idtodo.title作为参数;

5.2.script

<script>
export default {
  name: "MyItem",
  props:['todo',"checkTodo",'deleteTodo'],
  methods: {
    handleCheck(id) {
      console.log("MyItem:handleCheck("+id+")");
      this.checkTodo(id);
    },
    handleDelete(id, title) {
      if (confirm("确定删除" + title + "任务吗?")) {
        console.log("MyItem:handleDelete("+id,title+")");
        this.deleteTodo(id);
      }
    }
  }
}
</script>

MyItem.vue的scirpt部分的描述

  1. 通过export default导入当前Vue组件的配置;

  • name属性用于指定当前组件的名称;

  • props属性是一个数组,数组中的字符串元素代表了父组件可以通过这些属性向当前组件传递数据或方法;

  • handleCheck方法接受一个参数id,使用this.checkTodo调用父组件传递过来的checkTodo方法,并将id作为参数传递;

  • hendleDelete方法接受两个参数idtitle,通过弹窗confirm确认是否删除,如果确认,则调用this.deleteTodo(id)方法,this.deleteTodo(id)调用父组件传递过来的deleteTodo方法,并将id作为参数传递;

5.3.style

<style scoped>
li {
  list-style: none;
  height: 36px;
  width: 560px;
  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: -1;
}

li button {
  float: right;
  display: none;
  margin-top: 5px;
}

li:before {
  cursor: inherit;
}

li:last-child {
  border-bottom: none;
}

li:hover {
  background-color: #eee;
}

li:hover button {
  display: block;
}
</style>

6. MyList.vue

6.1.template

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

MyList.vue的template部分的描述

  1. 定义一个ul元素;

  2. 使用v-for遍历名为todos的数组,数组中的每个元素都会生成一个MyItem组件的实例;

  3. :key用来设置每个生产实例的唯一标识,这里使用每个todo对象的id属性;

  4. 通过:todo属性将遍历到的todo对象传递给子组件;

  5. :checkTodo:deleteTodo属性传递两个函数checkTododeleteTodo用于处理点击事件;

6.2.script

<script>
import MyItem from "@/components/MyItem.vue";

export default {
  name: "MyList",
  props: ['todos', "checkTodo",'deleteTodo'],
  components: {MyItem}
}
</script>

MyList.vue的script部分的描述

  1. 使用ES6的模块导入语法导入名为MyItem的组件;

  2. 通过export default导入当前Vue组件的配置;

  • name属性用于指定当前组件的名称;

  • props属性是一个数组,数组中的字符串元素代表了父组件通过这些属性名向当前组件传递数据或方法;

  • components属性代表将MyItem组件注册为当前组件的局部组件;

6.3.style

<style scoped>
.main {
  width: 570px;
  margin-left: 0px;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding: 0px;
}
</style>

7. MyFooter.vue

7.1.template

<template>
  <div class="footer" v-show="true">
    <label>
      <input type="checkbox" v-model="isAll"/>
      全选
    </label>
    <span>
      <span>已完成{{doneTotal}}</span>/全部{{total}}
    </span>
    <button @click="clearAll">删除已完成任务</button>
  </div>
</template>

MyFooter.vue的template部分的描述

  1. v-show将一个classfooterdiv块元素始终显示在页面上;

  2. type属性为checkbox的复选框用v-model绑定在isAll属性,表示是否全部选中;

  3. 使用插值表达式{{}}动态显示doneTotaltotal变量的值;

  4. 定义<button>元素,通过@click事件监听器绑定一个clearAll点击事件处理函数,当按钮被点击时会触发;

7.2.script

<script>
export default {
  name: "MyFooter",
  props:['todos','checkAllTodo','clearAllTodo'],
  computed:{
    doneTotal(){
      console.log("MyFooter:doTotal():"+this.todos.reduce((pre,todo) =>pre + (todo.done ? 1:0),0));
      return this.todos.reduce((pre,todo) =>pre + (todo.done ? 1:0),0);
    },
    total(){
      console.log("MyFooter:total():"+this.todos.length);
      return this.todos.length;
    },
    isAll:{
      get(){
        console.log("MyFooter:isAll:get():"+this.total===this.doneTotal && this.total >0);
        return this.total === this.doneTotal && this.total >0;
      },
      set(value){
        console.log("MyFooter:isAll:set("+value+"):"+this.checkAllTodo(value));
        this.checkAllTodo(value);
      }
    }
  },
  methods:{
    clearAll(){
      console.log("MyFooter:clearAll():"+this.clearAllTodo);
      this.clearAllTodo();
    }
  }
}
</script>

MyFooter.vue的script部分的描述

  1. 通过export default导入当前Vue组件的配置;

  • name属性用来指定当前组件的名称;

  • props属性是一个数组,数组中的字符串元素代表了父组件可以通过这些属性向当前组件传递数据或方法;

  • doneTotal计算已完成任务的数量,使用reduce方法遍历todos数组并统计done属性为true的元素数量;

  • total计算总任务的数量,直接返回todos数组的长度;

  • isAll计算用于控制全选复选框的状态。通过get函数和set函数实现对全选状态的监听和修改;

  • clearAll方法用于清除所有已完成任务,当触发清除按钮时会调用父组件传递过来的clearAllTodo方法;

7.3.style

<style scoped>

.footer {
  width: 570px;
  height: 40px;
  line-height: 40px;
  padding-left: 7px;
  margin-top: 5px;
}

.footer label {
  display: inline-block;
  margin-right: 20px;
  cursor: pointer;
}

.footer label input {
//position: relative; vertical-align: middle; margin-right: 5px;
}

.footer button {
  float: right;
  margin-top: 5px;
}
</style>

时贰肆年壹月捌日凌晨

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值