【IMWeb训练营作业】ToDoList

运行效果图

todolist主页面
localstorage

核心代码

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width,user-scalable=no, initial-scale=1">
    <title>index</title>
    <link rel="stylesheet" type="text/css" href="css/font-awesome.min.css">
    <link rel="stylesheet" type="text/css" href="css/style.css">
  </head>
  <body>
  <header>
    任务计划列表
  </header>
  <section class="main">
    <div class="infor">
      <h3>添加任务</h3>
      <input type="text" 
              v-model="todo"
              placeholder="例如:吃饭睡觉打豆豆;操作:按“enter”键添加任务" 
              v-on:keyup.enter="addTodo" />
      <ul class="">
        <li class="tip">{{ noCheckLength }}个任务未完成</li>
        <li class="action">
          <a href="#all">所有任务</a>
          <a href="#unfinished">未完成的任务</a>
          <a href="#finished">完成的任务</a>
        </li>
      </ul>
    </div>
    <div class="tasks">
      <h3>任务列表</h3>
      <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 ===editorTodos}" v-for="item in filterList">
          <div class="view">
            <input type="checkbox" class="toggle" v-model="item.isChecked" />
            <label v-on:dblclick="editTodo(item)">{{ item.title }}</label>
            <div class="destroy icon-remove-circle" v-on:click="deleteTodo(item)"></div>
          </div>
          <input v-focus="editorTodos === item" 
                  v-on:blur="editorTodoed(item)"
                  v-on:keyup.enter="editorTodoed(item)"
                  v-on:keyup.esc="cancelTodo(item)"
                  class="edit" 
                  type="text" 
                  v-model="item.title" />
        </li>
      </ul>
    </div>
  </section>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/main.js"></script>
  </body>
</html>
style.css
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
 ul,dl,ol{
    list-style: none;
} 

header{
    width: 100%;
    height: 50px;
    background: red;
    font-size: 25px;
    color: #fff;
    line-height: 2;
    text-align: center;
}
section.main{
    width: 800px;
    margin: 20px auto;
}
.infor{
    width: 100%;
}
.infor input[type="text"]{
    width: 100%;
    height: 28px;
    margin: 10px 0;
}
.infor ul{
    display: flex;
    flex-flow: row nowrap;
    justify-content: space-between;
}
.infor ul li.tip{
    color: red
}
.infor ul li.action a{
    text-decoration:none;
    color: #000 
}
.tasks{
    margin-top: 20px;
}
.todo-list li{
    display: flex;
    display: -webkit-flex;
    flex-wrap: nowrap;
    align-items: center;
    width: 100%;
    height: 40px;
    background: #fff;
}
.todo-list li:hover{
    background: #f7f6f6;
}
.todo-list li .edit{
    display: none;
}
.todo-list li.editing .view{
    display: none;
}
.todo-list li.editing .edit{
    display: block;
    width: 100%;
    height: 40px
}
.todo-list li .toggle{
    text-align: center;
    width: 25px;
    height: 25px
}
.completed{
    text-decoration: line-through;
    color: #ccc;
}
main.js
(function(win){

  // 存取localstorage中的数据 && 监控list存、删的功能
  var store = {
    save: function(key,value){
      localStorage.setItem(key,JSON.stringify(value));
    },
    fetch: function(key){
      return JSON.parse(localStorage.getItem(key)) || [];
    }
  };
  var filter = {
    all: function(list){
      return list;
    },
    finished: function(list){
      return list.filter(function(item){ return item.isChecked })
    },
    unfinished: function(list){
      return list.filter(function(item){ return !item.isChecked })
    }
  };


  /*var list = [
    {
      title: '吃饭打豆豆',
      isChecked: false
    }
  ];
*/
  var list = store.fetch("myTodoData")
  var vm =  new Vue({
    el: ".main",    
    data: { list: list, todo: "", editorTodos:"", // 记住正在编辑的数据 beforeTitle: "", // 记录正在编辑的数据的title visibility: "all" // 通过这个属性值对数据进行筛选 },
    watch: { list: { handler: function(){ store.save("myTodoData",this.list) }, deep: true } },
    methods: { addTodo : function(){ // 添加任务 this.list.push({ title: this.todo, // 当时push进来的时候忘了 isChecked属性,删除线的效果后知后觉, isChecked: false }); this.todo = ""; }, editTodo: function(todo){ // 编辑任务 this.editorTodos = todo; this.beforeTitle = todo.title; }, editorTodoed: function(todo){ // 编辑任务成功 this.editorTodos=''; }, cancelTodo: function(todo){ // 取消编辑任务 todo.title = this.beforeTitle; this.beforeTitle = ''; this.editorTodos = ''; }, deleteTodo: function(todo){ // 删除任务 var idx = this.list.indexOf(todo); this.list.splice(idx,1);  } },
    directives: { "focus" :{ update: function(el,binding){ if(binding.value){ el.focus() } } } },
    computed: { noCheckLength: function(){ return this.list.filter(function(item){ return !item.isChecked }).length }, filterList: function(){ // 过滤的时候有3种情况,按照3个a的# return filter[this.visibility] ? filter[this.visibility](list): list; } }
  });

  function watchHashChange(){
    var hash = window.location.hash.slice(1);  //去除#号
    vm.visibility = hash;
  }
  win.addEventListener("hashchange",watchHashChange)

}(window));

收获

  • 学到一种不同jquery的思维模式,不是直接通过dom来操作,而是先通过数据,操作虚拟dom,最后再渲染出来;
  • 组件化
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值