Vue.js做todo日常事务任务列表

来源:互联网 发布:mac jenkins 配置文件 编辑:程序博客网 时间:2024/05/29 02:18

目标:用Vue.js制作一个todo任务列表

功能:
1.增删便签任务
2. 编辑便签任务
3. 深度监控数据
4. 利用hash过滤数据

知识点:
1. 常见指令的使用
2. 双向数据绑定(v-model)
3. 动态添加class
4. 循环(v-for)
5. 数据监控
5. 自定义属性
6. 过滤器
7. 计算属性
8. hash过滤数据
9. 事件修饰符

最终效果:
未添加任务前:
未添加任务前

添加3个任务
添加3个任务

标记一个已完成
一个已完成

筛选未完成任务
筛选未完成任务

筛选已完成任务
筛选已完成任务

html代码

<!DOCTYPE html><html><head>    <meta charset="utf-8" />    <title></title>    <link rel="stylesheet" type="text/css" href="style.css" />    <script src="https://unpkg.com/vue/dist/vue.js"></script></head><body>    <section>        <div class="page-top">            <div class="page-content">                <h2>任务计划列表</h2>            </div>        </div>        <div class="main" id="main">            <h3 class="title">添加任务</h3>            <!--:keyup.enter事件修饰符的用法-->            <input type="text" class="task-input" placeholder="输入任务,按下回车键即可添加新任务" v-model='todo' v-on:keyup.enter='addTodo' />            <ul class="task-count" v-show='list.length'>                <li><strong style="color: #EE0000;">{{noCheckedNum}}</strong>个任务未完成</li>                <li class="action">                    <a href="#all" :class="{active:visibility === 'all'}">所有任务</a>                    <a href="#unfinished" :class="{active:visibility === 'unfinished'}">未完成</a>                    <a href="#finished" :class="{active:visibility === 'finished'}">已完成</a>                </li>            </ul>            <h3 class="title">任务列表</h3>            <div class="tasks">                <span class="no-task-tip" v-show='!list.length'>还没有添加任何任务</span>                <ul class="todo-list">                    <li class="todo" v-bind:class='{completed: item.isChecked,editing: item === editTodos}' v-for='item in filteredList'>                        <div class="view">                            <input type="checkbox" class="toggle" v-model='item.isChecked' />                            <label for="" @dblclick="editTodo(item)">{{item.title}}</label>                            <a class="destroy" v-on:click='deleteTodo(item)'></a>                        </div>                        <input type="text" class="edit" v-myfocus='editTodos === item' v-on:blur='edited(item)' v-on:keyup.13='edited(item)' v-on:keyup.esc='cancelEdit(item)' v-model='item.title' />                    </li>                </ul>            </div>        </div>    </section>    <script src="app.js" type="text/javascript" charset="utf-8"></script></body></html>

JavaScript代码:

//存取localStorage中的数据var store = {    save(key, value) { //存数据        localStorage.setItem(key, JSON.stringify(value));    },    fetch(key) { //取数据        return JSON.parse(localStorage.getItem(key)) || [];    }}//所有的listvar list = store.fetch('vue-dotolist'); //fetch的key值可自定义//过滤任务的三种状态var filter = {    all: function(list) {        return list;    },    unfinished: function(list) {        return list.filter(function(item) {            return !item.isChecked;        });    },    finished: function(list) {        return list.filter(function(item) {            return item.isChecked;        });    }};var vm = new Vue({    el: '.main',    data: {        list: list,        todo: '', //记录新增任务的数据        editTodos: '', //记录正在编辑任务的数据        beforTitle: '', //记录正在编辑的数据的原title        visibility: 'all' //通过这个属性值的变化对数据筛选    },    watch: {        //浅复制        /*list: function(){ //监控list属性,当该值发生变化时调用函数            store.save('vue-dotolist', this.list);        }*/        //深复制        list: {            handler: function() {                store.save('vue-dotolist', this.list);            },            deep: true        }    },    methods: {        addTodo(e) { //添加任务            //向list中添加一项任务            //事件处理函数中的list指向的是当前根实例            this.list.push({                title: this.todo,                isChecked: false //新增任务默认不勾选            });            this.todo = '';        },        deleteTodo(todo) { //删除任务            var index = this.list.indexOf(todo); //找出在数组中的下标            this.list.splice(index, 1);        },        editTodo(todo) { //编辑任务            //   console.log(todo);            //编辑任务时先记录这条任务的title,以便取消编辑时能保留之前的title            this.beforTitle = todo.title;            this.editTodos = todo;        },        edited(todo) { //编辑完成            //按下enter键(keyCode为13)或者失去焦点完成编辑            this.editTodos = '';        },        cancelEdit(todo) { //按下esc键取消编辑,保持原任务内容            todo.title = this.beforTitle;            this.beforTitle = '';            //让div显示出来,input隐藏掉,也就是去掉li的class名editing            this.editTodos = '';        }    },    computed: { //计算属性        noCheckedNum: function() { //计算未完成任务数            return this.list.filter(function(item) { //筛选出isChecked为false的任务,即未完成                return !item.isChecked            }).length        },        filteredList: function() { //过滤任务状态            //找到过滤函数就返回过滤后的数据,如果没有则返回所有函数            return filter[this.visibility] ? filter[this.visibility](list) : list;        }    },    directives: { //自定义事件,        'myfocus': { //自定义事件名称            update(el, binding) { //数据更新时                //     console.log(binding);  //可查看到value属性值                if (binding.value) { //如果value属性值为true执行获取焦点focus                    el.focus();                }            }        }    }});// 监测hash改变,过滤任务function watchHashChange() {    var hash = window.location.hash.slice(1);    vm.visibility = hash;    console.log(hash)}//进入页面就执行函数watchHashChange();//hash改变时也执行函数window.addEventListener('hashchange', watchHashChange);

CSS代码

ul, li {    list-style: none;}section {    display: block;    width: 300px;    margin: 30px auto;    text-align: center;}.main input[class='task-input'] {    line-height: 24px;    width: 230px;    height: 24px;    padding: 3px;    outline: none;}.title {    color: #008b8b;}.task-count li {    margin-top: 10px;}.action a {    text-decoration: none;}.active{    border: 1px solid #B22222;    border-radius: 3px;    padding: 3px;}.completed .view label {    text-decoration: line-through;    color: #aaa;}input.edit {    display: none;    height: 24px;}.todo-list li {    text-align: left;}.editing {    text-align: center;}.editing div.view {    display: none;}.editing .edit {    display: block;    text-align: center;}.view input, .view label, .view a {    line-height: 20px;    height: 20px;    vertical-align: middle;}a.destroy {    display: inline-block;    width: 20px;    background: url(dele.png) no-repeat center center;}
0 0
原创粉丝点击