基于vue实现待办清单案例

一、需求

  • 新增内容;

  • 删除内容;

  • 统计操作;

  • 清空数据。

    示例图:

    在这里插入图片描述

二、代码演示

1、基础准备

  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;
     }
    }
    
    
  2. 模板代码

    <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、新增功能

  1. 实现步骤

    • 生成列表结构(v-for 数组)
    • 获取用户输入(v-model 双向绑定)
    • 回车,新增数据(v-on .enter事件修饰符)
    • 页面布局不熟悉,可以通过审查元素的方式快速找到元素
  2. 修改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. 测试结果

在这里插入图片描述

3、删除内容

  1. 步骤

    • 点击删除指定的内容( 根据索引删除元素)
    • 在methods中添加一个删除的方法,使用splice函数进行删除
  2. 代码修改

    <!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>
    
    
  3. 测试结果

    在这里插入图片描述

    点击即可删除。

4、统计操作

  1. 步骤

    • 统计页面信息的个数,就是列表中的元素的个数.
    • 获取 list数组的长度,就是信息的个数
  2. 修改代码

    <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>
    
    
  3. 测试结果

    在这里插入图片描述

5、清空数据

  1. 步骤

    • 点击clear清空所有数据,只需要清空数组即可
  2. 代码修改

    <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>
    
    
  3. 测试结果

    在这里插入图片描述

    点击即可清空。

  • 14
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值