TodoList动画

一.MyFooter.vue

<template><div class="todo-footer" v-show="total"><label><!-- <input type="checkbox" :checked="isAll" @change="checkAll"/> --><input type="checkbox" v-model="isAll"/></label><span><span>已完成{{doneTotal}}</span> / 全部{{total}}</span><button class="btn btn-danger" @click="clearAll">清除已完成任务</button></div>
</template><script>export default {name:'MyFooter',props:['todos'],computed: {//总数total(){return this.todos.length},//已完成数doneTotal(){//此处使用reduce方法做条件统计/* const x = this.todos.reduce((pre,current)=>{console.log('@',pre,current)return pre + (current.done ? 1 : 0)},0) *///简写return this.todos.reduce((pre,todo)=> pre + (todo.done ? 1 : 0) ,0)},//控制全选框isAll:{//全选框是否勾选get(){return this.doneTotal === this.total && this.total > 0},//isAll被修改时set被调用set(value){// this.checkAllTodo(value)this.$emit('checkAllTodo',value)}}},methods: {/* checkAll(e){this.checkAllTodo(e.target.checked)} *///清空所有已完成clearAll(){// this.clearAllTodo()this.$emit('clearAllTodo')}},}
</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>

二.MyHeader.vue

<template><div class="todo-header"><input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="title" @keyup.enter="add"/></div>
</template><script>import {nanoid} from 'nanoid'export default {name:'MyHeader',data() {return {//收集用户输入的titletitle:''}},methods: {add(){//校验数据if(!this.title.trim()) return alert('输入不能为空')//将用户的输入包装成一个todo对象const todoObj = {id:nanoid(),title:this.title,done:false}//通知App组件去添加一个todo对象this.$emit('addTodo',todoObj,1,2,3)//清空输入this.title = ''}},}
</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>

三.MyItem.vue

<template><li><label><input type="checkbox" :checked="todo.done" @change="handleCheck(todo.id)"/><!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,因为修改了props --><!-- <input type="checkbox" v-model="todo.done"/> --><span v-show="!todo.isEdit">{{todo.title}}</span><input type="text" v-show="todo.isEdit" :value="todo.title" @blur="handleBlur(todo,$event)"ref="inputTitle"></label><button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button><button v-show="!todo.isEdit" class="btn btn-edit" @click="handleEdit(todo)">编辑</button></li>
</template><script>import pubsub from 'pubsub-js'export default {name:'MyItem',//声明接收todoprops:['todo'],methods: {//勾选or取消勾选handleCheck(id){//通知App组件将对应的todo对象的done值取反// this.checkTodo(id)this.$bus.$emit('checkTodo',id)},//删除handleDelete(id){if(confirm('确定删除吗?')){//通知App组件将对应的todo对象删除// this.deleteTodo(id)// this.$bus.$emit('deleteTodo',id)pubsub.publish('deleteTodo',id)}},//编辑handleEdit(todo){if(todo.hasOwnProperty('isEdit')){todo.isEdit = true}else{// console.log('@')this.$set(todo,'isEdit',true)}this.$nextTick(function(){this.$refs.inputTitle.focus()})},//失去焦点回调(真正执行修改逻辑)handleBlur(todo,e){todo.isEdit = falseif(!e.target.value.trim()) return alert('输入不能为空!')this.$bus.$emit('updateTodo',todo.id,e.target.value)}},}
</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;}li:hover{background-color: #ddd;}li:hover button{display: block;}
</style>

四.MyList.vue

<template><ul class="todo-main"><transition-group name="todo" appear><MyItem v-for="todoObj in todos":key="todoObj.id" :todo="todoObj" /></transition-group></ul>
</template><script>import MyItem from './MyItem'export default {name:'MyList',components:{MyItem},//声明接收App传递过来的数据props:['todos']}
</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;}.todo-enter-active{animation: atguigu 0.5s linear;}.todo-leave-active{animation: atguigu 0.5s linear reverse;}@keyframes atguigu {from{transform: translateX(100%);}to{transform: translateX(0px);}}
</style>

五.App.vue

<template><div id="root"><div class="todo-container"><div class="todo-wrap"><MyHeader @addTodo="addTodo"/><MyList :todos="todos"/><MyFooter :todos="todos" @checkAllTodo="checkAllTodo" @clearAllTodo="clearAllTodo"/></div></div></div>
</template><script>import pubsub from 'pubsub-js'import MyHeader from './components/MyHeader'import MyList from './components/MyList'import MyFooter from './components/MyFooter'export default {name:'App',components:{MyHeader,MyList,MyFooter},data() {return {//由于todos是MyHeader组件和MyFooter组件都在使用,所以放在App中(状态提升)todos:JSON.parse(localStorage.getItem('todos')) || []}},methods: {//添加一个todoaddTodo(todoObj){this.todos.unshift(todoObj)},//勾选or取消勾选一个todocheckTodo(id){this.todos.forEach((todo)=>{if(todo.id === id) todo.done = !todo.done})},//更新一个todoupdateTodo(id,title){this.todos.forEach((todo)=>{if(todo.id === id) todo.title = title})},//删除一个tododeleteTodo(_,id){this.todos = this.todos.filter( todo => todo.id !== id )},//全选or取消全选checkAllTodo(done){this.todos.forEach((todo)=>{todo.done = done})},//清除所有已经完成的todoclearAllTodo(){this.todos = this.todos.filter((todo)=>{return !todo.done})}},watch: {todos:{deep:true,handler(value){localStorage.setItem('todos',JSON.stringify(value))}}},mounted() {this.$bus.$on('checkTodo',this.checkTodo)this.$bus.$on('updateTodo',this.updateTodo)this.pubId = pubsub.subscribe('deleteTodo',this.deleteTodo)},beforeDestroy() {this.$bus.$off('checkTodo')this.$bus.$off('updateTodo')pubsub.unsubscribe(this.pubId)},}
</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-edit {color: #fff;background-color: skyblue;border: 1px solid rgb(103, 159, 180);margin-right: 5px;}.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>

六.main.js

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false//创建vm
new Vue({el:'#app',render: h => h(App),beforeCreate() {Vue.prototype.$bus = this},
})

36.TodoList动画相关推荐

  1. iOS核心动画学习整理

    最近利用业余时间终于把iOS核心动画高级技巧(https://zsisme.gitbooks.io/ios-/content/chapter1/the-layer-tree.html)看完,对应其中一 ...

  2. iOS 动画 - 从不会到熟练应用

    原文链接:http://www.jianshu.com/p/3f48fabaca19 一个很好的讲动画的文章, 基本涵盖了 80% 的动画知识点. -- 由 抱紧我的小鲤鱼 分享 原创内容,转载请注明 ...

  3. 慕课 简书项目 个人笔记

    第1章 课程导学 本章主要介绍学习react的重要性,课程的知识大纲,学习前提,讲授方式及预期收获. 1-1 课程导学 React由Fackbook 2013年5月推出开源框架,函数式编程React ...

  4. jQuery笔记综合

    jQuery笔记 一. jQuery入门 目标: 能够说出什么是jQuery 能够说出jquery的优点 能够简单使用jquery 能够说出dom对象和jquery对象的区别 1.jQuery概述 仓 ...

  5. IOS Animation-CAShapeLayer、UIBezierPath与Animation的结合

    IOS Animation-CAShapeLayer.UIBezierPath与Animation的结合 在阅读本文之前,对CAShapeLayer.UIBezierPath不熟悉的话,可以先阅读文章 ...

  6. 全屏背景:15个jQuery插件实现全屏背景图像或媒体

    动态网站通常利用背景图像或预加载屏幕,以保证所有资源都加载到页面上,在浏览器中充分呈现.现在很多网站都炫耀自己的图像作为背景图像全屏背景,追溯到旧的Flash网站却用自己的方式在HTML资源重布局. ...

  7. 国漫《大闹天宫》4K修复版上线西瓜视频、鲜时光

    2月15日消息,今日,西瓜视频独家上线4K版<大闹天宫>,该版本由西瓜视频联合火山引擎共同修复. <大闹天宫>原片由上海美术电影制片厂在上世纪60年代出品,是新中国成立后的第一 ...

  8. 走入 Cocos Creator视频教程-姜威-专题视频课程

    走入 Cocos Creator视频教程-137人已学习 课程介绍         Cocos Creator游戏视频培训课程设计上,由一个简单的游戏,引入课程主体.先熟练开发流程,在熟练API,后熟 ...

  9. WEB 前端面试题 (高能)

    文章目录 `HTML . CSS .浏览器 相关:` *1.网络中使用最多的图片格式有哪些* : *2. 请简述 css 盒子模型* : *3. 视频 / 音频标签的使用* : *4.HTML5 新增 ...

最新文章

  1. 被黑客们使用的代码混淆技术
  2. 关于Angularjs中自定义指令一些有价值的细节和技巧
  3. SpringBoot实用小技巧之动态设置SpringBoot日志级别
  4. anglarjs引入HTML头,请问怎么在html引入angularjs?
  5. pythonpostapi_python post接口测试第一个用例日记
  6. PHP对Excel导入导出操作
  7. 解决mxnet错误:OSError: libcudart.so.10.0: cannot open shared object file: No such file or directory
  8. 启动马达接线实物图_星三角降压启动电路图实物接线图
  9. ios-团购代码的重构
  10. [命令模式]在游戏开发中的应用
  11. Go语言strings和strconv包
  12. 电商网站详情页系统架构
  13. CCSP(Certified Cloud Security Professional) 国际注册云安全专家
  14. 【工程师学算法】工程常用算法(二)—— 卡尔曼滤波(Kalman Filter)
  15. 岁月让人从批判走向了建设
  16. 安全圈年终大趴,FIT 2019首日盛况全程回顾
  17. 猫狗数据集百度网盘链接
  18. 找工作神器,提取各大网站有效的招聘信息(前程无忧、智联招聘、猎聘网)
  19. Spring中常用的SpEl表达式
  20. 盘点:史上最全数据挖掘方法!我火速收藏!

热门文章

  1. 汕头大学应用数学硕士专业
  2. 10862 - Connect the Cable Wires
  3. javaWeb实现邮件发送
  4. 续上一个LOL皮肤爬虫:用pyinstaller打包成exe
  5. 【AGV机器人智能取物】企业都能用得起的WMS/RFID系统立体智能仓库
  6. 双线性插值法(Bilinear Interpolation)
  7. 商业银行智能语音识别技术-笔记
  8. RS485应用电路图
  9. 羡慕!因工作琐事太多,女子果断从体制内裸辞
  10. 通信原理_基于 2ASK 调制解调的无线收发_gnuradio+USRP2920_含实现流图