一、需求
-
新增内容;
-
删除内容;
-
统计操作;
-
清空数据。
示例图:
二、代码演示
1、基础准备
-
index.css代码
html, body { margin: 0; padding: 0; } body { background: #fff ; } button { margin: 0; padding: 0; border: 0; background: none; font-size: 100%; vertical-align: baseline; font-family: inherit; font-weight: inherit; color: inherit; -webkit-appearance: none; appearance: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } body { font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 1.4em; background: #f1b7b7; color: #4d4d4d; min-width: 230px; max-width: 550px; margin: 0 auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-weight: 300; } :focus { outline: 0; } .hidden { display: none; } #app { background: #fff; margin: 180px 0 40px 0; position: relative; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); } #app input::-webkit-input-placeholder { font-style: italic; font-weight: 300; color: #e6e6e6; } #app input::-moz-placeholder { font-style: italic; font-weight: 300; color: #e6e6e6; } #app input::input-placeholder { font-style: italic; font-weight: 300; color: gray; } #app h1 { position: absolute; top: -160px; width: 100%; font-size: 60px; font-weight: 100; text-align: center; color: rgba(175, 47, 47, .8); -webkit-text-rendering: optimizeLegibility; -moz-text-rendering: optimizeLegibility; text-rendering: optimizeLegibility; } .new-todo, .edit { position: relative; margin: 0; width: 100%; font-size: 24px; font-family: inherit; font-weight: inherit; line-height: 1.4em; border: 0; color: inherit; padding: 6px; border: 1px solid #999; box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); box-sizing: border-box; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .new-todo { padding: 16px; border: none; background: rgba(0, 0, 0, 0.003); box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03); } .main { position: relative; z-index: 2; border-top: 1px solid #e6e6e6; } .toggle-all { width: 1px; height: 1px; border: none; /* Mobile Safari */ opacity: 0; position: absolute; right: 100%; bottom: 100%; } .toggle-all + label { width: 60px; height: 34px; font-size: 0; position: absolute; top: -52px; left: -13px; -webkit-transform: rotate(90deg); transform: rotate(90deg); } .toggle-all + label:before { content: "❯"; font-size: 22px; color: #e6e6e6; padding: 10px 27px 10px 27px; } .toggle-all:checked + label:before { color: #737373; } .listview { margin: 0; padding: 0; list-style: none; max-height: 420px; overflow: auto; } .listview li { position: relative; font-size: 24px; border-bottom: 1px solid #ededed; height: 60px; box-sizing: border-box; } .listview li:last-child { border-bottom: none; } .listview .view .index { position: absolute; color: gray; left: 10px; top: 20px; font-size: 16px; } .listview li .toggle { text-align: center; width: 40px; /* auto, since non-WebKit browsers doesn't support input styling */ height: auto; position: absolute; top: 0; bottom: 0; margin: auto 0; border: none; /* Mobile Safari */ -webkit-appearance: none; appearance: none; } .listview li .toggle { opacity: 0; } .listview li .toggle + label { /* Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433 IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/ */ background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: center left; } .listview li .toggle:checked + label { background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E"); } .listview li label { word-break: break-all; padding: 15px 15px 15px 60px; display: block; line-height: 1.2; transition: color 0.4s; } .listview li.completed label { color: #d9d9d9; text-decoration: line-through; } .listview li .destroy { display: none; position: absolute; top: 0; right: 10px; bottom: 0; width: 40px; height: 40px; margin: auto 0; font-size: 30px; color: #cc9a9a; margin-bottom: 11px; transition: color 0.2s ease-out; } .listview li .destroy:hover { color: #af5b5e; } .listview li .destroy:after { content: "×"; } .listview li:hover .destroy { display: block; } .listview li .edit { display: none; } .listview li.editing:last-child { margin-bottom: -1px; } .footer { color: #777; padding: 10px 15px; height: 20px; text-align: center; border-top: 1px solid #e6e6e6; } .footer:before { content: ""; position: absolute; right: 0; bottom: 0; left: 0; height: 50px; overflow: hidden; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6, 0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6, 0 17px 2px -6px rgba(0, 0, 0, 0.2); } .todo-count { float: left; text-align: left; } .todo-count strong { font-weight: 300; } .filters { margin: 0; padding: 0; list-style: none; position: absolute; right: 0; left: 0; } .filters li { display: inline; } .filters li a { color: inherit; margin: 3px; padding: 3px 7px; text-decoration: none; border: 1px solid transparent; border-radius: 3px; } .filters li a:hover { border-color: rgba(175, 47, 47, 0.1); } .filters li a.selected { border-color: rgba(175, 47, 47, 0.2); } .clear-completed, html .clear-completed:active { float: right; position: relative; line-height: 20px; text-decoration: none; cursor: pointer; } .clear-completed:hover { text-decoration: underline; } .info { margin: 50px auto 0; color: #bfbfbf; font-size: 15px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); text-align: center; } .info p { line-height: 1; } .info a { color: inherit; text-decoration: none; font-weight: 400; } .info a:hover { text-decoration: underline; } /* Hack to remove background from Mobile Safari. Can't use it globally since it destroys checkboxes in Firefox */ @media screen and (-webkit-min-device-pixel-ratio: 0) { .toggle-all, .listview li .toggle { background: none; } .listview li .toggle { height: 40px; } } @media (max-width: 430px) { .footer { height: 50px; } .filters { bottom: 10px; } }
-
模板代码
<html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <title>待办清单list</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <meta name="robots" content="noindex, nofollow" /> <meta name="googlebot" content="noindex, nofollow" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" type="text/css" href="./css/index.css" /> </head> <body> <!-- VUE示例接管区域 --> <section id="app"> <!-- 输入框 --> <header class="header"> <h1>待办清单</h1> <input autofocus="autofocus" autocomplete="off" placeholder="输入日程" class="new-todo" /> </header> <!-- 列表区域 --> <section class="main"> <ul class="listview"> <li class="todo"> <div class="view"> <span class="index">1.</span> <label>待办事项1</label> <button class="destroy"></button> </div> </li> </ul> </section> <!-- 统计和清空 --> <footer class="footer"> <span class="todo-count"> <strong>1</strong> items left </span> <button class="clear-completed">Clear</button> </footer> </section> <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </body> </html>
2、新增功能
-
实现步骤
- 生成列表结构(v-for 数组)
- 获取用户输入(v-model 双向绑定)
- 回车,新增数据(v-on .enter事件修饰符)
- 页面布局不熟悉,可以通过审查元素的方式快速找到元素
-
修改js代码
<html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <title>待办清单list</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <meta name="robots" content="noindex, nofollow" /> <meta name="googlebot" content="noindex, nofollow" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" type="text/css" href="./css/index.css" /> </head> <body> <!-- VUE示例接管区域 --> <section id="app"> <!-- 输入框 --> <header class="header"> <h1>待办清单</h1> <!-- 添加 数据绑定 和 回车添加进model数据列表的事件绑定--> <input autofocus="autofocus" autocomplete="off" placeholder="输入日程" class="new-todo" v-model="inputValue" @keyup.enter="add" /> </header> <!-- 列表区域 --> <section class="main"> <ul class="listview"> <!-- 添加循环 --> <li v-for="(item, index) in todoList" class="todo"> <div class="view"> <span class="index">{{index+1}}.</span> <label>{{item}}</label> <button class="destroy"></button> </div> </li> </ul> </section> <!-- 统计和清空 --> <footer class="footer"> <span class="todo-count"> <strong>1</strong> items left </span> <button class="clear-completed">Clear</button> </footer> </section> <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </body> <script src="./js/vue.min.js"></script> <script> var VM = new Vue({ el: "#app", data: { inputValue: "待输入待办事项", todoList: ["事件1", "事件2"], }, methods: { add: function () { this.todoList.push(this.inputValue); }, }, }); </script> </html>
-
测试结果
3、删除内容
-
步骤
- 点击删除指定的内容( 根据索引删除元素)
- 在methods中添加一个删除的方法,使用splice函数进行删除
-
代码修改
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <!-- 导入css资源 --> <link rel="stylesheet" href="./css/inputNum.css" /> </head> <body> <!-- 显示区域 --> <div id="app"> <input type="button" class="btn btn_plus" @click="add" /> <span>{{num}}</span> <input type="button" class="btn btn_minus" @click="sub" /> </div> </body> <script src="js/vue.min.js"></script> <script> var Vm = new Vue({ el: "#app", data: { num: 1, }, methods: { add: function () { if (this.num < 10) { this.num++; } else { alert("数字到达上限10!"); } }, sub: function () { if (this.num > 0) { this.num--; } else { alert("数字减到下限0!"); } }, }, }); </script> </html>
-
测试结果
点击即可删除。
4、统计操作
-
步骤
- 统计页面信息的个数,就是列表中的元素的个数.
- 获取 list数组的长度,就是信息的个数
-
修改代码
<html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <title>待办清单list</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <meta name="robots" content="noindex, nofollow" /> <meta name="googlebot" content="noindex, nofollow" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" type="text/css" href="./css/index.css" /> </head> <body> <!-- VUE示例接管区域 --> <section id="app"> <!-- 输入框 --> <header class="header"> <h1>待办清单</h1> <!-- 添加 数据绑定 和 回车添加进model数据列表的事件绑定--> <input autofocus="autofocus" autocomplete="off" placeholder="输入日程" class="new-todo" v-model="inputValue" @keyup.enter="add" /> </header> <!-- 列表区域 --> <section class="main"> <ul class="listview"> <!-- 添加循环 --> <li v-for="(item, index) in todoList" class="todo"> <div class="view"> <span class="index">{{index+1}}.</span> <label>{{item}}</label> <!-- 删除按钮 --> <button class="destroy" @click="remove(index)"></button> </div> </li> </ul> </section> <!-- 统计和清空 --> <footer class="footer"> <span class="todo-count"> <!-- 此处添加数据的统计信息 --> <strong>{{todoList.length}}</strong> items left </span> <button class="clear-completed">Clear</button> </footer> </section> <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </body> <script src="./js/vue.min.js"></script> <script> var VM = new Vue({ el: "#app", data: { inputValue: "待输入待办事项", todoList: ["事件1", "事件2"], }, methods: { add: function () { this.todoList.push(this.inputValue); }, //删除方法 remove: function (index) { //使用splice(元素索引,删除几个) 根据索引删除 //双向绑定数据,均只需要操作数据即可 this.todoList.splice(index, 1); }, }, }); </script> </html>
-
测试结果
5、清空数据
-
步骤
- 点击clear清空所有数据,只需要清空数组即可
-
代码修改
<html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <title>待办清单list</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <meta name="robots" content="noindex, nofollow" /> <meta name="googlebot" content="noindex, nofollow" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" type="text/css" href="./css/index.css" /> </head> <body> <!-- VUE示例接管区域 --> <section id="app"> <!-- 输入框 --> <header class="header"> <h1>待办清单</h1> <!-- 添加 数据绑定 和 回车添加进model数据列表的事件绑定--> <input autofocus="autofocus" autocomplete="off" placeholder="输入日程" class="new-todo" v-model="inputValue" @keyup.enter="add" /> </header> <!-- 列表区域 --> <section class="main"> <ul class="listview"> <!-- 添加循环 --> <li v-for="(item, index) in todoList" class="todo"> <div class="view"> <span class="index">{{index+1}}.</span> <label>{{item}}</label> <!-- 删除按钮 --> <button class="destroy" @click="remove(index)"></button> </div> </li> </ul> </section> <!-- 统计和清空 --> <footer class="footer"> <span class="todo-count"> <!-- 此处添加数据的统计信息 --> <strong>{{todoList.length}}</strong> items left </span> <!-- 此处添加清空数组事件绑定 --> <button class="clear-completed" @click="clear">Clear</button> </footer> </section> <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </body> <script src="./js/vue.min.js"></script> <script> var VM = new Vue({ el: "#app", data: { inputValue: "待输入待办事项", todoList: ["事件1", "事件2"], }, methods: { add: function () { this.todoList.push(this.inputValue); }, //删除方法 remove: function (index) { //使用splice(元素索引,删除几个) 根据索引删除 //双向绑定数据,均只需要操作数据即可 this.todoList.splice(index, 1); }, //清空数组 clear: function () { this.todoList = []; }, }, }); </script> </html>
-
测试结果
点击即可清空。