主要功能展示

1、新增列表功能:在输入框内输入数据,点击键盘上的enter”按钮,将输入的数据添加到列表中,并清空输入框的内容。如果用户没有输入数据,将会提示。

2、高亮和删除功能:鼠标经过列表里的每一项,都会让当前列表背景颜色改变,并显示后面的删除按钮。点击删除将会提示是否删除,如果点击删除,则删除此项列表。鼠标离开时将消失。

3、计算属性:可以根据前面input框前面是否勾选对号来判断当前事项是否完成,并将已完成事项和总事项通过Footer子组件中的computed属性计算得出。

4、一次删除多个选中功能:点击 ‘清除已完成’ 按钮会弹出是否清除的弹窗,点击确定则会将选中的列表项清除,并提示并渲染出对应的列表数据。

5、实现数据存储:实现数据的本地存储,用户添加的选项列表如果没有被删除,则将存储在本地的浏览器中。

6、防止数据被恶意修改:如果主动删除了或更改了Application中的value值,使其不是一个完整的对象,则会自动删除所有数据,并提示本地缓存异常,数据已重置。

案例实现基本思路

在vue脚手架的基础上做案例,

在src文件夹下 新建文件main.js,App.vue。新建文件夹components,里面新建Header.vue,List.vue,Item.vue,Footer.vue,(分别代表不同的组件)编写组件的结构,样式。

这里面的List相当于Item的父组件

组件之间的层级结构图

组件使用步骤

1、定义

2、引入并注册

3、使用

编写程序之前更重要的是分析需求,我是一小块一小块功能实现的。做一做,测一测,遇到问题及时解决。

比如实现添加列表的功能,你可以通过自定义属性去完成。想要添加,输入框是在Header子组件里面,所以你就要在Header子组件里拿到用户输入的内容,然后给输入框绑定key.enter键盘事件,去调用methods里面的对应的方法,方法中首先判断用户输入的内容是否为空,如果不为空根据用户输入内容生成一个Todo对象,然后使用自定义事件去通知App在data中添加一个todo,这里要在App中提前写好对应的方法,将子组件中传递过来的数据进行渲染并放在列表的最前方。最后再清空输入框。最终实现这个小功能。

就这样根据所学知识,以及对功能需求的分析,一步一步来,最终完成案例。对于Vue初学者来说,Todolist这个案例还是很有必要去做一做的,下面是我做的案例对应的源码,上面的注释也很详细,有需要的小伙伴可以参考。

核心代码:

main.js

// 引入Vue
import Vue from 'vue';
// 引入APP
import App from './App.vue'
//关闭生产提示
Vue.config.productionTip = false
new Vue({el:'#app',
/*
vue.runtime.common.js和vue.js有何区别?
vue.runtime.common.js(项目中用的多) : 1.不包含模板解析器,打包后体积小2.配置项中的不能写template,要用render: h => h(App)代替
vue.js : 1.包含解模板析器,打包后体积大2.配置可以写template
*/
// 调用h函数相当于帮你做了3件事
// components:{App},
// template:`<App/>`
// 加上请外援vue-template-compiler(Vue模板解析器)相当于一个loaderrender: h => h(App)
})

App.vue

<template><div class="todo-container"><div class="todo-wrap"><!-- 头部 使用自定义事件去实现--><Header @add-todo="addtodo"/><!-- 列表 --><List  :todos='todos' :updateTodo="updateTodo" :deleteTodo="deleteTodo"/><!-- 底部 --><Footer :todos='todos' :updateAll="updateAll" :clearAll="clearAll"/></div></div>
</template><script>
import Header from './components/Header'
import List from './components/List'
import Footer from './components/Footer'export default {name:'App',components:{Header,List,Footer},data(){//数据const localData = localStorage.getItem('todos')let todostry {//尝试解析localStorage中的数据,如有数据,直接使用,无数据,使用空数组。todos = JSON.parse(localData) || []} catch (error) {alert('本地缓存数据异常,数据已重置')localStorage.removeItem('todos')todos = []}return {todos}},methods: {//添加一个Todoaddtodo(todoObj){//unshift后添加的东西往前放this.todos.unshift(todoObj)},//更新一个todo----通过ID// updateTodo(id,done) {//  this.todos= this.todos.map((todo)=>{//     if(id===todo.id) return {...todo,done:done}//     else return todo//   })// },//更新一个todo----通过indexupdateTodo(index,done) {this.todos[index].done=done},//删除一个TododeleteTodo(index){this.todos.splice(index,1)// console.log(index);},//全选or全不选updateAll(done){this.todos=this.todos.map((todo)=>{return {...todo,done}})},// 清除所有已完成clearAll(){this.todos=this.todos.filter((todoObj)=>{return !todoObj.done})},},watch:{todos:{deep:true, //开启深度监视handler(value){localStorage.setItem('todos',JSON.stringify(value))}}}}
</script><style>
/*base*/
body {background: #fff;
}.btn {display: inline-block;padding: 4px 12px;margin-bottom: 0;font-size: 14px;line-height: 20px;text-align: center;vertical-align: middle;cursor: pointer;box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);border-radius: 4px;
}.btn-danger {color: #fff;background-color: #da4f49;border: 1px solid #bd362f;
}.btn-danger:hover {color: #fff;background-color: #bd362f;
}.btn:focus {outline: none;
}.todo-container {width: 600px;margin: 0 auto;
}
.todo-container .todo-wrap {padding: 10px;border: 1px solid #ddd;border-radius: 5px;
}
</style>

Header.vue

<template><div class="todo-header"><inputv-model="name" @keyup.enter="add"type="text" placeholder="请输入你的任务名称,按回车键确认"/></div>
</template><script>export default {name:'Header',data(){return{name}},methods:{add(){if(!this.name.trim()) return alert('输入信息不能为空')//根据用户输入内容生成一个Todo对象const todoObj={id:Date.now(),name:this.name,done:false}//使用自定义事件去通知App在data中添加一个todothis.$emit('add-todo',todoObj)//清空输入this.name=''}}}
</script><style scoped>
/*header*/
.todo-header input {width: 560px;height: 28px;font-size: 14px;border: 1px solid #ccc;border-radius: 4px;padding: 4px 7px;
}.todo-header input:focus {outline: none;border-color: rgba(82, 168, 236, 0.8);box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
}</style>

Footer.vue

<template><div class="todo-footer"><label><input type="checkbox" v-model="isAll"/></label><span><span>已完成{{doneCount}}</span> / 全部{{total}}</span><button class="btn btn-danger" @click="clearAllDone">清除已完成任务</button></div>
</template><script>export default {name:'Footer',props:['todos','updateAll','clearAll'],computed:{doneCount(){//这里引入一些reduce的知识点// arr.reduce(function(prev,cur,index,arr){// ...// }, init);// 其中,// arr 表示原数组;// prev 表示上一次调用回调时的返回值,或者初始值 init;// cur 表示当前正在处理的数组元素;// index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;// init 表示初始值。// 例子:// var arr = [3,9,4,3,6,0,9];// var sum = arr.reduce(function (prev, cur) {//   return prev + cur;// },0);// 由于传入了初始值0,所以开始时prev的值为0,cur的值为数组第一项3,// 相加之后返回值为3作为下一轮回调的prev值,然后再继续与下一个数组项相加,// 以此类推,直至完成所有数组项的和并返回。return this.todos.reduce((pre,current)=>pre+=current.done?1:0,0)},total(){return this.todos.length},isAll:{//使用计算属性的set去实现全选set(flag){this.updateAll(flag)},get(){return this.doneCount === this.total && this.total>0}}},methods:{//  使用方法去全选//  checkAll(event){//     console.log('@',event.target.checked);//   this.updateAll(event.target.checked)  //  }clearAllDone(){if(confirm('确定清除所有已完成的tido吗?')){this.clearAll()}}}}
</script><style scoped>
/*footer*/
.todo-footer {height: 40px;line-height: 40px;padding-left: 6px;margin-top: 5px;
}.todo-footer label {display: inline-block;margin-right: 20px;cursor: pointer;
}.todo-footer label input {position: relative;top: -1px;vertical-align: middle;margin-right: 5px;
}.todo-footer button {float: right;margin-top: 5px;
}</style>

Item.vue

<template><li@mouseenter="isEnter=true"@mouseleave="isEnter=false":class="{'high-light':isEnter}"><!-- 当更改数据和点击事件同时存在时,事件优先 --><label><input type="checkbox":checked="todo.done"@click="update(index,$event)"/><span>{{todo.name}}</span></label><button class="btn btn-danger" :style="{display:isEnter ?'block':'none'}"@click="deleteT(index)">删除</button>  </li></template><script>export default {name:'Item',                     props:['todo','updateTodo',"deleteTodo",'index'],data(){return{isEnter:false//标识鼠标是否移入}},methods: {//用id去更新//    update(id,event){//      console.log(id,event.target.checked);//      //通知app去更新这个todo//      const{checked}=event.target//      this.updateTodo(id,checked)//    }//  },//用index去更新deleteT(index){if(confirm('确定删除吗')){this.deleteTodo(index)//  this.deteleTodo(index)           }},update(index,event){//  console.log(id,event.target.checked);//通知app去更新这个todoconst{checked}=event.targetthis.updateTodo(index,checked)}},}
</script><style scoped>
/*item*/
li {list-style: none;height: 36px;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: -1px;
}li button {float: right;display: none;margin-top: 3px;
}li:before {content: initial;
}li:last-child {border-bottom: none;
}
.high-light{background-color: #bbb;
}
</style>

List.vue

<template>
<div><ul class="todo-main"><Item v-for="(t,index) in todos" :key="t.id" :todo="t":updateTodo="updateTodo":index='index':deleteTodo="deleteTodo"/></ul></div>
</template>
<script>
import Item from './Item'export default {name:'List',components:{Item},props:['todos','updateTodo','deleteTodo']//声明接收props,声明后可以在vc上找的到}
</script><style scoped>
/*main*/
.todo-main {margin-left: 0px;border: 1px solid #ddd;border-radius: 2px;padding: 0px;
}.todo-empty {height: 40px;line-height: 40px;border: 1px solid #ddd;border-radius: 2px;padding-left: 5px;margin-top: 10px;
}
</style>

TodoList案例相关推荐

  1. Vue之Todolist案例和ES6语法

    2.7 Todolist案例 2.7.1 准备工作 <!DOCTYPE html> <html> <head><meta charset="utf- ...

  2. Vue.js-Day02-AM【Vue表单、核心指令(单选框、密码框、多行文本框、单选、多选、勾选、下拉列表)、组件汇总案例、ToDoList案例、计算属性(computed)、watch监听】

    Vue.js实训[基础理论(5天)+项目实战(5天)]博客汇总表[详细笔记] 目   录 1.Vue表单 原生JS实现异步表单提交 运行截图 代码 核心指令 单选框.密码框.多行文本框 单选 多选 勾 ...

  3. Vue版todolist案例

    Vue版todolist案例 todolist – 记录你的待办事项 <!DOCTYPE html> <html><head><meta charset=&q ...

  4. vue2.0-脚手架-todolist案例

    一 vue脚手架2.0 安装 npm install vue-cli -g 查阅一下脚手架可支持的模板 vue list可以查到 template-name 使用脚手架生成项目(以下命令得运行在项目的 ...

  5. 【Vue2.0】— TodoList案例(十七)

    [Vue2.0]- TodoList案例(十七) <template><div id="root"><div class="todo-con ...

  6. 尚硅谷todolist案例

    vue todolist案例 1 拆分组件 一共拆分为4个组件 TodoHeader TodoItem TodoList TodoFooter item是list的子组件 2 组件化编码流程 实现静态 ...

  7. ToDoList 案例完整 尚硅谷

    总结ToDoList案例: 1.组件化编码流程: (1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突. (2).实现动态组件:考虑好数据的存放位置,数据是一个组件再用,还是一些组件 ...

  8. 基于vue的todolist案例

    前言:todolist案例真的算是经典了,不管你是学习原生js,还是学习jq,还是学习vue,亦或者是react,todolist是练习必不可少的练习demo了,下面我们来看看这个案例.需要完整代码的 ...

  9. 「后端小伙伴来学前端了」Vue中Props 实现组件通信TodoList案例

    自己拍的小云彩 源码在文末. 前言 上篇文章写了个V利用Props进行组件之间的通信,这不立马就安排上这个案例拉丫.光学不敲等于没学哈(资深大佬除外哈) 目标就是实现如下的样子: 能够进行增删改查,并 ...

  10. Redux 使用指南(todoList 案例)

    Redux 使用指南 前言 案例需求 实现思路 第一步:定义 Action 第二步:定义 Reducer 第三步:整合 Reducer 第四步:定义 Store 第五步:处理业务逻辑 第六步:注意事项 ...

最新文章

  1. pymssql 安装后只有 .disk-info_变频空调安装注意事项
  2. IT职场规划和学习方法
  3. 《代码整洁之道》阅读笔记
  4. JMeter入门案例
  5. wxpython下载很慢_为什么WxPythons运动检测速度如此之慢?
  6. 【HDU - 5968】异或密码(思维,STLmap)
  7. hive load data外部表报错_生产SparkSQL如何读写本地外部数据源及排错
  8. NOI Linux2.0使用系列视频集
  9. Ubuntu16.04--code::blocks16.01 的代码拷贝到Windows 8.1--visual studio 2013 注意事项
  10. SpringBoot的日志框架
  11. JavaScript in Action
  12. UGUI的Slider
  13. javaint接收float_Java Float intValue()用法及代码示例
  14. Tcmalloc优化Mysql内存管理
  15. USB协议 - UVC标准协议规范(二)
  16. 极大似然估计的通俗理解
  17. java青蛙跳台阶问题
  18. python短信验证码登录_Python实现短信验证
  19. 转行学习java自学好还是去培训学校学习好?系统学习路线推荐
  20. Linux Get命令

热门文章

  1. SpringBoot+Vue项目实战-QG
  2. SQL Server 事物日志空间收缩
  3. R语言 ggplot2 多图排列 Part(1)
  4. oracle添加外键约束的方法
  5. 计算机bootmgr丢失,如何修复Bootmgr压缩错误,及压缩导致的数据丢失问题?
  6. 称重管理系统服务器不通,如何解决在无人值守称重管理系统的漏洞
  7. origin中文版散点图拟合曲线_Origin绘图:3D散点图如何绘制拟合线、如何给数据图“化妆”...
  8. linux系统程序下载,Linux平台的下载程序
  9. 小波变换在地震信号降噪方面的应用
  10. 微软的DreamSpark计划-学生可免费使用vs2008 pro,sql server Dev 2005,Expression Studio等产品...