gitHub地址:https://github.com/gaozhixiao...

功能拆分:

  1. 渲染数据
  2. 键盘事件:添加事项
  3. 鼠标点击事件:移除事项
  4. 显示未办事项数据
  5. 全部事项、未办事项、已办事项状态切换
  6. 清除全部完成事项
  7. 全选、取消全选
  8. LocalStorage读取,保存事项数据
  9. 鼠标双击事件:双击修改数据
  10. 键盘事件:Enter键盘事件完成修改
  11. 键盘事件:Esc键盘事件取消修改
  12. 自定义事件
  13. 加载事件:获取焦点
  14. 失去焦点事件:保存事项

1 渲染数据

指令: v-for v-for指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名
指令: v-bind v-bind:class = {} 动态绑定class。缩写为:class

    <li 
        class="todo"
        v-for="(item, index) in todoList" 
        :key="index"
        :class="{completed: item.selected}"
        <div class="view">
            <input 
                class="toggle" 
                type="checkbox"
            >
            <label
            >{{ item.title }}</label>
            <button 
                class="destroy"
            ></button>
        </div>
    </li>

数据:

    {
        id: 1,
        title: "todo1",
        selected: false
    }

2 Enter键盘事件: 添加事项

指令: v-on v-on指令监听 DOM 事件。缩写为@
按键修饰符: .enter: enter按键按下时触发
指令: v-model 双向数据绑定,它会根据控件类型自动选取正确的方法来更新元素

    <input 
        class="new-todo" 
        autofocus 
        autocomplete="off" 
        placeholder="What needs to be done?"
        @keyup.enter="add"
        v-model="todoValue"
    >
    
    add: function () {
        let todoLength = this.todoList.length;
        this.todoList.push({
            "id": todoLength + 1,
            "title": this.todoValue,
            "selected": false
        })
        this.todoValue = ""
    },

3 鼠标点击事件:移除事项

    <button 
        class="destroy"
        @click="remove(index)"
    ></button>
    
    remove: function (index) {
        this.todoList.splice(index, 1);
    },

4 显示未办事项数目

    // 未办事项
    unSeleted: function () {
        return this.todoList.filter((item, index, array) => {
            return !item.selected;
        })
    },
    
    <span class="todo-count">
        <strong>{{ unSeleted.length }}</strong> item left
    </span>

5 全部事项、未办事项、已办事项状态切换

Hash:hash是url的一部分,从#开始
Array.filter: array.filter(function(currentValue,index,arr), thisValue) filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
_.filter: _.filter(collection, [predicate=_.identity])。引自: lodash.js 参考地址:https://www.lodashjs.com/

    // 将状态栏设置成hash属性
    <a 
        href="#/all"
        :class="{ selected: hashActive === 'all' }"
    >All</a>
    
    // 默认状态为全部事项
    hashActive: "all"
    
    // 已办事项
    selelted: function () {
        return _.filter(this.todoList, function (item) {
            return item.selected;
        })
    },
    // 未办事项
    unSeleted: function () {
        return this.todoList.filter((item, index, array) => {
            return !item.selected;
        })
    },
    // 事项状态切换
    hashFilter: function () {
        if (this.hashActive === 'all') {
            return this.todoList;
        } else if (this.hashActive === 'active') {
            return this.unSeleted;
        } else if (this.hashActive === 'completed'){
            return this.selelted;
        } else {
            return this.todoList;
        }
    }
    
    // 已办事项,未办事项返回值都是一个数组,故更新渲染数据
    <li 
        class="todo"
        v-for="(item, index) in hashFilter" 
        :key="index"
        :class="{completed: item.selected}"
    >

6 清除全部完成事项

指令:v-if: v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。

    <button 
        class="clear-completed"
        @click="clearCompleted"
        v-if="selelted.length"
    >
        Clear completed
    </button>
    
    // 清空已办事项
    clearCompleted: function () {
        this.todoList = this.unSeleted;
    },

7 全选、取消全选

Array.foreach: array.forEach(function(currentValue, index, arr), thisValue) forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。

    // 当事项未全部选择时-> 全选,反之,反选
    <input 
        id="toggle-all" 
        class="toggle-all" 
        type="checkbox"
        @click="toggleAll"
    >
    
    toggleAll: function () {
        let selectedAll = this.todoList.every(function (item, index, array) {
            return item.selected;
        })
    
        if (selectedAll) {
            this.todoList.forEach(item => {
                item.selected = false;
            });
        } else {
            this.todoList.forEach(item => {
                item.selected = true;
            });
        }
    },

8 LocalStorage读取,保存事项数据

localStorage.getItem: var aValue = localStorage.getItem(keyName); 从localStorage中读取数据
localStorage.setItem: localStorage.setItem(keyName, keyValue); 写入到localStorage中

    // LocalStorage读取事项
    let todoList = localStorage.getItem('todoList');
    if (todoList) {
        todoList = JSON.parse(todoList)
    } else {
        todoList = [];
    }
    
    // 渲染数据修改为从localStorage中获取
    data: {
        todoList: todoList
    },
    
    // 保存事项到localStorage, 采用监听属性对象内部的改变
    watch: {
        todoList: {
            deep: true,
            handler: function () {
                localStorage.setItem('todoList', JSON.stringify(this.todoList));
            }
        }
    },

9 鼠标双击事件:双击修改数据

    // 双击事件
     <label
        v-on:dblClick="edit(item, $event)"
    >{{ item.title }}</label>

    // 双击后,修改框显示双击前的数据
    // 此处注意的是:绑定的是item数据,这样做可以任意修改该条数据
    <li 
        class="todo"
        v-for="(item, index) in hashFilter" 
        :key="index"
        :class="{completed: item.selected, editing: editValue === item}"
    >
    
    edit: function (item, el) {
        this.editValue = item;
        this.cancelValue = item.title;
    },
    
    <input 
        class="edit" 
        type="text" 
        v-model="item.title"
    >

10 键盘事件:Enter键盘事件完成修改

    <input 
        class="edit" 
        type="text" 
        v-model="item.title"
        @keyup.enter="editDone(item, index)"
    >
    
    // 当编辑的数据为空时,删除该条数据, 同时重置该属性
    editDone: function (item, index) {
        if (!item.title) {
            this.todoList.splice(index, 1)
        }
        this.editValue = ""
    },

11 键盘事件:Esc键盘事件取消修改

按键修饰符: .Esc: Esc按键按下时触发

    <input 
        class="edit" 
        type="text" 
        v-model="item.title"
        @keyup.enter="editDone(item, index)"
        @keyup.esc="cancelDone(item, index)"
    >
    
    cancelDone: function (item, index) {
        item.title = this.cancelValue;
        this.editValue = "";
        this.cancelValue = "";
    }

12 自定义事件

自定义指令: directives

    // 当双击修改事项时,获取焦点
    <input 
        class="edit" 
        type="text" 
        v-model="item.title"
        v-todo-focus="editValue == item"
        @keyup.enter="editDone(item, index)"
        @keyup.esc="cancelDone(item, index)"
    >
    
    todoFocus: function (el) {
        el.focus();
    }

13 加载事件:获取焦点

window.onload: 文档加载完成后执行

    // 程序加载,获取焦点
    function getFocus () {
        let newTodo = document.getElementsByClassName('new-todo')[0];
        newTodo.focus();
    }
    window.onload = getFocus;
    
    // 切换状态,获取焦点
    hashFilter: function () {
        getFocus();
        ...
    }

14 失去焦点事件:保存事项

    <input 
        class="edit" 
        type="text" 
        v-model="item.title"
        v-todo-focus="editValue == item"
        @blur="editDone(item, index)"
        @keyup.enter="editDone(item, index)"
        @keyup.esc="cancelDone(item, index)"
    >

高志鹏
171 声望16 粉丝

努力强大自己,竭力去做一个伟大的产品