文章目录

  • 效果图
  • 代码

效果图

代码

主要代码:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><link rel="stylesheet" href="./04.css" /></head><body><div id="app"><!-- todos 标题的开始 --><app-todo-header></app-todo-header><!-- todos 标题的结束 --><!-- 中间内容的开始 --><div class="app-todo-content"><div class="todo-content-top"><span:class="[{'content-top-allCheck':true},{active:allChecked}]"@click.stop="handleAllCheck">></span><!-- 1. input上面添加 键盘事件 => 按下 enter => 保存 2. v-model 值绑定--><inputtype="text"v-focusv-model="inputVal"@keyup.enter="saveTodo"/></div><div class="todo-content-bottom"><!-- 代办清单列表 --><div class="content-bottom-list"><divclass="bottom-list-item"v-for="(item,index) in filterTodos":key="item.id"@dblclick="editTodo(index)"><input type="checkbox" name="" id="" v-model="item.checked" /><div><span:class="[{'title':true}, {hidden:selectIndex===index},{'complete':item.checked}]">{{item.text}}</span><inputtype="text"v-model="item.text"@blur="saveChangedTodo":class="[{hidden:selectIndex!=index}]"v-todo-focus/></div><span class="delete-item" @click="deleteTodo(index)">X</span></div></div></div></div><!-- 中间内容结束 --><!-- todos 底部工具栏开始 --><div class="todo-bottom"><div class="todo-bottom-left">{{remaining}} 项剩下</div><div class="todo-bottom-mid"><div@click.stop="handleItemClick('all')":class="[{'bottom-mid-left':true},{active:activeItem==='all'}]">全部</div><div@click.stop="handleItemClick('active')":class="[{'bottom-mid-mid':true},{active:activeItem==='active'}]">激活</div><div@click.stop="handleItemClick('complete')":class="[{'bottom-mid-right':true},{active:activeItem==='complete'}]">完成</div></div><div class="todo-bottom-right" @click.stop="clearCompleted">清除已完成</div></div><!-- todos 底部工具栏结束 --></div></body><script src="./node_modules/vue/dist/vue.js"></script><script src="./storageUtil.js"></script><script>/* 定义一个 v-focus 可以使得 input 自动聚焦指令名字: focus全局指令*/// Vue.directive("focus",{//   bind:function(el,binding,vnode,oldNode){//     console.log("指令已经绑定到元素上面");//   },//   // 指令所在的元素 已经插到 父节点中//   inserted:function(el,binding,vNonde,oldNode){//     console.log(el);//     el.focus();//   }// })let vm = new Vue({el: "#app",watch:{todos:{handler:function(value,oldValue){storageUtil.save("todos",value);},deep:true}},computed: {// 过滤之后的 todosfilterTodos: function () {// activeItem// allif (this.activeItem === "all") {return this.todos;} else if (this.activeItem === "active") {// active => checked === falsereturn this.todos.filter((todo, index) => {if (!todo.checked) {return true;}});} else {// completereturn this.todos.filter((todo, index) => {// complete => checked === trueif (todo.checked) {return true;}});}},// 剩下的todosremaining: function () {// todos => todo.checked => false => 挑选出来let remainTodos = this.todos.filter((todo, index) => {if (!todo.checked) {return true;}});return remainTodos.length;},allChecked: function () {// 检查todos 如果todos 中有没有被选中的值 allChecked falselet checked = true;// 如果 todos 为空的情况下 checked = false// bug fixif (!this.todos.length) {checked = false;}this.todos.map((todo, index) => {if (!todo.checked) {checked = false;}});return checked;},},data: {activeItem: "all", // all 全部的todos active 激活的todos complete 完成的todos// allChecked: false,// 全选 默认情况下没有被选中selectIndex: -1, // -1 没有编辑项 0 正在编辑第一项 1 正在编辑第二项inputVal: "",/*{id: Date.now(),text:"ssss",checked:false}*/todos: storageUtil.fetch("todos"),},methods: {// 点击 全部 激活 完成的点击事件handleItemClick: function (activeItem) {this.activeItem = activeItem;},// 清除已完成clearCompleted: function () {// 过滤掉 todos => todo=> todo.checked === true// todo.checked === true 已完成// todo.checked === false 未完成let filterTodos = this.todos.filter((todo, index) => {if (!todo.checked) {return true;}});this.todos = filterTodos; // 替换todos},handleAllCheck: function () {let newTodos = JSON.parse(JSON.stringify(this.todos));// newTodos.forEach(())this.todos.map((todo, index) => {todo.checked = true;});// 现在所有的todo 都被选中了//   this.allChecked = true;},// 保存todosaveChangedTodo: function () {this.selectIndex = -1; // -1 表示没有双击编辑任何的 todo},// 编辑todoeditTodo: function (index) {this.selectIndex = index;},// 删除 tododeleteTodo: function (index) {// splice(index,1)this.todos.splice(index, 1);},saveTodo: function () {console.log("获取到input 值", this.inputVal);if (!this.inputVal) {alert("输入不能为空!");return;}this.todos.push({id: Date.now(),text: this.inputVal,checked: false,});},},components: {"app-todo-header": {template: `<div class="app-todo-header"><span>todos</span></div>   `,},},// 局部指令directives: {// "todo-focus":{//   // 节点插入父节点//   inserted:function(el,binding){//     el.focus();//   },//   // 节点更新的时候 update//   update:function(el,binding){//     console.log(el);//     el.focus();//   }// },// 如果 inserted 和 update 的时候 执行的相同的行为  可以写成以下形式"todo-focus": function (el, binding) {el.focus();},focus: {bind: function (el, binding, vNode, oldNode) {},inserted: function (el, binding, vNode, oldNode) {el.focus();},},},});</script>
</html>

04.css代码

#app {width: 700px;margin: 0 auto;border: 1px solid #ddd;min-height: 300px;
}
#app .app-todo-header {height: 50px;text-align: center;color: #ead7d7;font-weight: 100;font-size: 30px;
}
#app .app-todo-content .todo-content-top {display: flex;justify-content: center;align-items: center;
}
#app .app-todo-content .todo-content-top .content-top-allCheck {display: inline-block;transform: rotate(90deg);
}
#app .app-todo-content .todo-content-top .active {color: #e91f50;
}
#app .app-todo-content .todo-content-top input {width: 90%;height: 30px;
}
#app .app-todo-content .todo-content-bottom .content-bottom-list .bottom-list-item {height: 30px;display: flex;justify-content: space-between;padding: 5px;border-bottom: 1px solid #ddd;
}
#app .app-todo-content .todo-content-bottom .content-bottom-list .bottom-list-item .hidden {display: none;
}
#app .app-todo-content .todo-content-bottom .content-bottom-list .bottom-list-item .complete {color: #d9d9d9;text-decoration: line-through;
}
#app .app-todo-content .todo-content-bottom .content-bottom-list .bottom-list-item .delete-item {visibility: hidden;
}
#app .app-todo-content .todo-content-bottom .content-bottom-list .bottom-list-item:hover .delete-item {visibility: visible;
}
#app .todo-bottom {height: 50px;display: flex;justify-content: space-between;padding: 5px;align-items: center;
}
#app .todo-bottom .todo-bottom-mid {display: flex;align-items: center;
}
#app .todo-bottom .todo-bottom-mid .active {border: 1px solid #ddd;color: red;
}
#app .todo-bottom .todo-bottom-mid .bottom-mid-left {margin-right: 5px;
}
#app .todo-bottom .todo-bottom-mid .bottom-mid-mid {margin-right: 5px;
}
#app .todo-bottom .todo-bottom-mid .bottom-mid-right {margin-right: 5px;
}

storageUtil.js

/* 1. fetch(key) => 获取localStorage 中key 的记录 返回对象2. save(key,obj) => 保存 key 为 key对象 => localStorage*/
(function () {let storageUtil = {};storageUtil.fetch = function (key) {let rawObj = localStorage.getItem(key) || "[]"; // 字符串return JSON.parse(rawObj);};storageUtil.save = function (key, obj) {localStorage.setItem(key, JSON.stringify(obj));};window.storageUtil = storageUtil;
})();

此处没有用脚手架 直接安装vue插件完成的

npm install --save vue

然后在HTML内根据安装的路径引用安装的vue.js

一个简单todos的例子相关推荐

  1. mvc登录实例 mysql_spring mvc + mybatis + mysql 调整的一个简单的登录例子

    spring mvc + mybatis + mysql 整合的一个简单的登录例子 今天用spring跟mybatis整合写了一个简单的登录例子,第一次整合,给自己做个笔记,可能注释写的有点少,做的不 ...

  2. boost::log模块实现一个简单日志的例子

    boost::log模块实现一个简单日志的例子 实现功能 C++实现代码 实现功能 boost::log模块实现一个简单日志的例子 C++实现代码 #include <boost/log/tri ...

  3. 轻松创建nodejs服务器(1):一个简单nodejs服务器例子

    这篇文章主要介绍了一个简单nodejs服务器例子,本文实现了一个简单的hello world例子,并展示如何运行这个服务器,需要的朋友可以参考下 我们先来实现一个简单的例子,hello world. ...

  4. 一个简单的CORBA例子

    因为对CORBA分析的需要,这里写一个简单的CORBA例子.从JDK1.2开始,JDK中集成了ORB的实现,本例子使用了JDK1.7,对于JDK1.2+应该都没有问题.这个例子实现一个简单的加减乘除的 ...

  5. 使用Multiplayer Networking做一个简单的多人游戏例子-1/3(Unity3D开发之二十五)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51006463 ...

  6. java servlet例子_Servlet学习教程(三)---- 一个简单的Servlet例子

    我们用个最简单的Servlet例子来解说一下Servlet简单配置以及Servlet类实现类的写法. 第一,我们新建一个Dynamic Web Project,起名Servlet 点击NEXT,设置D ...

  7. Python网络爬虫 - 一个简单的爬虫例子

    下面我们创建一个真正的爬虫例子 爬取我的博客园个人主页首页的推荐文章列表和地址 scrape_home_articles.py from urllib.request import urlopen f ...

  8. python网页爬虫例子_Python网络爬虫 - 一个简单的爬虫例子

    下面我们创建一个真正的爬虫例子 爬取我的博客园个人主页首页的推荐文章列表和地址 scrape_home_articles.py from urllib.request importurlopenfro ...

  9. 决策树分析例题经典案例_决策树原理及一个简单的小例子

    首先通过两个图来引入什么是决策树. 是否学习的决策过程 决策树是仿树结构来进行决策的,例如上图来说,我们要对'是否学习'这个问题进行决策时,通常伴随一系列的子决策.先看是否有'对象',有的话是否需要' ...

  10. mysql设计一个简单的系统_一个简单数据库设计例子

    一个曾经做过的简单的管理系统中数据库设计的例子,包括设计表.ER图.建模.脚本. 项目信息 Project Name: Book Manager System DB: MySQL5.5 DB Name ...

最新文章

  1. 【转】jqGrid学习之参数
  2. TensorFlow超级指南 | 你能想到的TF教程和资源都在这里(附链接视频)
  3. 常用python编程软件-学习编程语言常用的10个工具、库——每个程序员都应该知道...
  4. Nodejs的express使用教程
  5. 转:集群和分布式的区别
  6. mysql trace工具_100% 展示 MySQL 语句执行的神器-Optimizer Trace
  7. idea修改maven项目版本号
  8. mac+php版本切换+cli,Mac环境下php版本切换
  9. android 应用性能优化1
  10. mysql 开发复制协议_MySQL组复制MGR(一)– 技术概述
  11. 判断给定的IP地址是否是内网IP
  12. docker pxc mysql_docker安装pxc集群的详细教程
  13. Rust语言编程实例100题-036
  14. 微信公众号微信支付提示 调用支付JSAPI缺少参数:appId
  15. C语言wifi程序代码,STM32F103 WIFI程序 C语言.docx
  16. 好佳居窗帘十大品牌 窗帘的发展故事
  17. 三种设置session有效时间的方法
  18. Vector-常用CAN工具(软件篇)-CANoe Trace
  19. 计算机维修的入门知识
  20. Windows Phone 7.5及诺基亚Lumia 800使用感受

热门文章

  1. 固态硬盘是什么接口_固态硬盘都有哪些接口,是否通用吗?
  2. 体制内名校生和普校生发展有无差别?看懂这3个潜规则,越混越好
  3. 对抗样本:知其然,知其所以然
  4. 六级(2020/12-2) Section B
  5. 关于cocos2d引擎写的手游加速
  6. 汽车之家论坛字体反爬
  7. 软素质面试题分享以及一些面试技巧和面试礼仪
  8. 我的理想是学计算机,我的理想作文(精选10篇)
  9. 前端入门篇(四十)JS基础7浏览器原理和BOM
  10. 计算机cad比例尺1 150,CAD图纸里面 1:50 和:1:100和1:150三个比例分别怎么换算...