• 【100个前端小项目-2】KnockoutJS 实现To-do list


    最近接手的任务用的是KnockoutJS + TypeScript,所以第二个项目就采用KnockoutJS做一个老生常谈的TODO List。

    https://codepen.io/xinxhe/pen/qBBMoVL
    todo-codepen.gif

    KnockoutJS的特点是双向绑定,在ViewModel中定义一系列的变量,然后用data-bind绑定到对应的HTML元件中即可。做这个项目的时候有几个难点:1.实现输入to-do后按回车键添加; 2. 实现动态组件变化,如点击编辑按钮后变成储存按钮,点击编辑按钮后to-do文字部分变成编辑框; 3. 修改样式让to-do变得好看(没错,这个花费时间最长!)☺

    下面上代码:

    HTML

    <div class="todo-container">
      <div class="todo-sub-container todo-title">
        <h2>To-do list by KnockoutJS</h2>
      </div>
      <div class="todo-sub-container todo-input">
        <input data-bind="value: itemToAdd, valueUpdate: 'afterkeydown', event: { keyup : addItem }"
               placeholder="Add a to-do" />
      </div>
      <div class="todo-sub-container todo-list">
        <ul data-bind="foreach: items" class="todo-items">
          <li class="todo-item">
            <div class="todo-item-text">
              <span data-bind="visible: !$data.isEditMode(), text: $data.name"></span>
              <input data-bind="visible: $data.isEditMode, value: $data.name, hasFocus: isEditMode" />
            </div>
            <div class="todo-item-control">
              <button data-bind="click: $parent.removeItem" 
                      class="icon fas fa-trash-alt"></button>
              <button data-bind="visible: !$data.isEditMode(), click: $parent.editItem" 
                      class="icon fas fa-pen"></button>
              <button data-bind="visible: $data.isEditMode, click: $parent.saveItem" 
                      class="icon fas fa-save"></button>
            </div>
          </li>
        </ul>
      </div>
    </div>
    

    CSS

    * {
      font-family: Arial, Helvetica, sans-serif;
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    .todo-container {
      margin: auto;
       60%;
    ,  height: 100
    }
    
    .todo-sub-container {
      margin: auto;
      min- 500px;
      height: 20vh;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .todo-title {
      background: #ff7f35;
      color: #fff;
      font-size: 25px;
      border-radius: 0 0 5px 5px;
    }
    
    .todo-input {
      height: 15vh;
    }
    
    .todo-input > input {
       100%;
      margin: 0 20px;
      height: 50px;
      border: 4px solid #ff8c3e;
      border-radius: 5px;
      padding: 5px;
      font-size: 18px;
    }
    
    .todo-input > input:focus{
        outline: none;
    }
    
    .todo-list {
      height: 65vh;
      background: #fbffde;
      align-items: flex-start;
      border-radius: 5px 5px 0 0;
    }
    
    .todo-items {
      list-style: none;  
       100%;
      margin: 0 20px;
    }
    
    .todo-item {
      background: #ffe999;
      margin-top: 10px;
      padding: 10px 10px 10px 20px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      min-height: 50px;
      border-radius: 5px;
      border: 2px solid #ffc25c;
    }
    
    .todo-item-text {
      font-size: 18px;
      color: #9a1717;
       80%;
      word-wrap: break-word;
    }
    
    .todo-item-text > input {
      padding: 5px;
      font-size: 18px;
      background: #fbffde;
      border: none;
       100%;
    }
    
    .todo-item-text > input:focus {
      outline: none;
    }
    
    .todo-item-control > button {
      background: #fff6ca;
      margin-left: 5px;
      border: 2px solid #ff7f35;
      border-radius: 20px;
       25px;
      height: 25px;
    }
    
    .todo-item-control > button:hover, .icon {
      background: #fff;
      border-color: #fff;
      cursor: pointer;
      color: #9a1717;
    }
    
    .icon {
      color: #ff7f35;
    }
    

    JS

    function ToDoItem(name) {
      var self = this;
      self.name = ko.observable(name);
      self.isEditMode = ko.observable(false);
    }
    
    var ViewModel = function() {
      var self = this;
      let todoItems = [ new ToDoItem("Exercise one hour"), new ToDoItem("Supermarket")];
      
      self.items = ko.observableArray(todoItems);
      self.itemToAdd = ko.observable("");
      
      self.addItem = function(data, event) {
        if (event.keyCode === 13 && self.itemToAdd() != "") {    
          self.items.push(new ToDoItem(self.itemToAdd()));
          self.itemToAdd("");
        }
      };
      
      self.removeItem = function() {
        self.items.remove(this);
      };
      
      self.editItem = function() {
        this.isEditMode(true);
      };
      
      self.saveItem = function() {
        this.isEditMode(false);
      };
    };
     
    ko.applyBindings(new ViewModel()); 
    

    这个项目花费三个晚上,本来想要用TypeScript,但是因为KnockoutJS的文档是用JS写的,所以为了参考起来方便就直接用了JS。之后可以试着将其改成TypeScript。

  • 相关阅读:
    推荐谷歌浏览器12款常用的扩展
    推荐谷歌浏览器12款常用的扩展
    推荐VSCode12个比较实用的插件
    推荐VSCode12个比较实用的插件
    Linux中Shell循环结构for用法笔记
    django之上传图片
    django之中间件设置
    django之admin站点
    django之管理静态文件
    django之设置分页
  • 原文地址:https://www.cnblogs.com/xinxhe/p/11870527.html
Copyright © 2020-2023  润新知