【IMWeb训练营作业】Todolist

这几天参加了腾讯课堂的IMWeb训练营加薪课程,学习了Vue的相关知识,现在我来谈谈这几天的收获吧。。。

前言

Vue是一个现在比较流行的基于MVVM的渐进式框架,作者是尤雨溪大大!何谓渐进式?就是说Vue.js的核心库只关注视图层,也就是ViewModel这一层,这样Vue.js的核心库就会很小,然后如果你还需要其他功能,再根据功能需求加上不同的功能就是。在它官网首页有一句话已经很好地介绍了vue,“数据驱动的组件,为现代化的 Web 界面而生”, 其核心思想就是响应的数据绑定和组合的试图组件。

现在前端比较流行的MVVM框架有三个,Angular,React,Vue,我为什么要选择Vue来学习呢?其一,相对于其他两个来说,Vue体积小,比较轻量;其二就是Vue的学习曲线比较平缓,没有另外两个陡峭,学习Angular要对typeScript有所了解,而React就更不用说了,全家桶。。。所有我想都没有想,就是他了,Vue!!!刚好准备学习Vue的时候,看到了腾讯课堂的十天前端加薪Vue课程,我就立即报名了。

回归正题,现在我来谈一下这次的个人作业,根据这几天的课程老师的讲解,做一个todolist,来看一下最终运行效果图。。。

运行效果图

核心代码

这个页面的样式我是参考了todoMVC网站的样式。当然这个作业重点是Vue部分,所以代码HTML部分就不贴出来了,下面是这个作业的核心代码

var store = {
    save(key, value) {
        localStorage.setItem(key, JSON.stringify(value));
    },
    fetch(key) {
        return JSON.parse(localStorage.getItem(key)) || [];
    }
};
var list = store.fetch('newTodoClass');
var vm = new Vue({
    el: "#todoapp",
    data: {
        list: list,
        todo: '',
        edtorTodos: '',
        beforeTitle: '',
        visibility: 'all'
    },
    watch: {
        list: {
            handler() {
                store.save('newTodoClass', this.list);
            },
            deep: true
        }
    },
    methods: {
        addTodo() {
            this.list.push({
                title: this.todo,
                isChecked: false
            });
            this.todo = '';
        },
        deleteTodo(todo) {
            var index = this.list.indexOf(todo);
            this.list.splice(index, 1);
        },
        edtorTodo(todo) {
            this.edtorTodos = todo;
            this.beforeTitle = todo.title;
        },
        edtorTodoed(todo) {
            this.edtorTodos = '';
        },
        cancelTodo(todo) {
            todo.title = this.beforeTitle;
            this.edtorTodos = '';
        }
    },
    directives: {
        "focus": {
            update(el, binding) {
                if (binding.value) {
                    el.focus();
                }
            }
        }
    },
    computed: {
        completed() {
            return this.list.filter(function(item) {
                return !item.isChecked;
            }).length;
        },
        filteredList() {
            var filter = {
                all(list) {
                    return list
                },
                finished(list) {
                    return list.filter(function(item) {
                        return item.isChecked
                    })
                },
                unfinished(list) {
                    return list.filter(function(item) {
                        return !item.isChecked
                    })
                }
            }
            return filter[this.visibility] ? filter[this.visibility](list) : list
        }
    }
});
function watchHashChange() {
    var hash = window.location.hash.slice(1);
    vm.visibility = hash;
};
watchHashChange();
window.addEventListener('hashchange', watchHashChange);

功能实现思路

我来大致讲解一下这个功能的实现吧,html部分会通过vue的v-for指令渲染todos列表,这个列表相对应的内容已经在js代码中定义的list数组中存储了。

如何增加一条新的任务呢?

我们可以来理清一下思路:

  1. 首先我们需要通过在最上面的输入框里面输入文本,列表内容
    然后再按下回车键,或者这个输入框失去焦点时,就会在下面的todos列表中加入一行任务,状态默认是未完成的,这个状态是通过data数据里的isChecked来控制的。这部分的功能可以在Vue的实例中增加一个methods的属性,所以的方法都放在这里面。
  2. 然后我们在methods属性增加一个addTodo的方法,可以通过v-on来绑定时间。这个方法作用就是当函数触发时,我们会向list数组中插入一条数据,也就是一个对象,然后把输入框清空,注意这个push方法不是我们所熟知的js数组中的push方法,除了push,还有很多方法都是这样的,虽然名字和方法是类似的,但是vue的push方法是已经重写了的,希望大家不要搞混!
addTodo() {
            this.list.push({
                title: this.todo,
                isChecked: false
            });
            this.todo = '';
        }

title对应的值是通过v-model来绑定到输入框的,这就是双向数据绑定。

删除任务

删除一条任务也就是类似的道理了,直接定义一个delete方法,传入的参数是对应的那个任务item,找到这条任务在list对应的索引值,然后从数组中删除。

双击修改任务

另外一个功能就是双击任务,可以改变任务名称,也就是title的值,通过@dblclick绑定edtorTodo事件,定义了一个edtorTodos来记录修改的状态,在todo列表的父元素上绑定一个editing的class,通过这个class来改变任务列表和相对应的修改这个title的输入框的隐藏与显示,也是通过v-model绑定了item.title才能修改相对应任务的名称。

之后就是如果在修改的时候不想修改了,应该如何取消?
1. 定义一个beforeTitle,在修改之前把这个任务列表的title值赋给 beforeTitle;
2. 然后通过@keyup.esc绑定cancelTodo事件,把beforeTitle的值又传回给任务列表的title,并退出编辑;

而显示还有多少个任务未完成是通过Vue的计算属性completed来动态计算出list数组个每个项目里isChecked为false的项目个数,这个应该很简单,相信大家都能明白。

按钮控制不同状态任务列表的显示

然后我们怎么实现在点击对应的按钮后,显示对应状态的任务列表呢?比如点击未完成时,任务列表就只会渲染出isChecked为false的item,这个可以用到hash值

  1. 我们可以给window对象通过addEventListener绑定一个 hashchange事件,回调函数就是获得这个hash值,然后把这个hash值赋给Vue实例中的visibility属性,这个visibility默认是全部显示的。
  2. 通过一个计算属性filteredList来根据visibility的值动态返回不同的状态的list,然后html中v-for指令就不是直接渲染list了,而是通过这个filteredList筛选出来的list,如果在输错hash值的情况下,我们可以判断hash不存在的情况下,全都返回hash值为all的结果,这样就达到了我们想要的效果了。

实现上诉所说的功能之后,这个todos应该完成的差不多了,现在就差临门一脚,我们要怎么实现在刷新页面之后,这个todos的列表还在呢?换句话说,我们怎么把这个list存储下来呢?谈到存储,相信大家第一时间会想到locaStorage,下面我们就来实现这个功能

  1. 我们定义一个store的对象,里面有两个方法save和fetch,也就是通过 locaStorage.setItem设置存储和 locaStorage.getItem读取存储,这个大家应该都懂,就不多说了。
  2. 我们把list就不设置死了,把获取的本地存储的值赋给list,这样list就能在刷新页面后依然能取到之前的存储下来的list数组,那么我们应该在什么时候把list存储下来呢?如果在上面的各个有改动list的方法中,都去设置store的存储方法,未免比较繁杂,有没有一个属性可能让我们监听到list的变化呢?Vue中提供了一个watch的属性,用过浏览器开发者工具js断点调试的应该知道有个watch的东西吧,这个就是差不多的作用。
  3. 我们在Vue实例中定义一个watch的属性,监听list数据的变化,其中如果自定义一个监听函数,虽然可以监听到list表层的变化,但是对于list数组各个项里的数据变化就监听不到了,所以我们还需在watch中定义一个deep的属性,把它设置为true,这样就可以了。

最后的最后

这几天一直都比较上心,早上起不来的时候想起来还要签到,逼着自己爬起来。。。九点开始看课程的录播视频,然后跟着老师的思路自己敲一遍代码,目前来看,大致还是能听懂的,而这篇博文就是这几天的成果了,希望之后自己能更上一层楼,到时候毕业设计就可以用Vue实现了,想一想就有点小激动呢。。。加油,努力!!!梦想会实现的,技术会提升的,工作会找到的!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值