IMWeb训练营作业--todolist

来源:互联网 发布:巨人网络数据分析 编辑:程序博客网 时间:2024/05/22 13:12

运行效果图:


核心代码:

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Backlog</title>
    <link rel="stylesheet" href="style.css">
    <script type="text/javascript" src="vue.js"></script>
    <link rel="stylesheet" href="index.css">
    <script src="index.js"></script>
  </head>
  <body>
    <div class="title">
      任务计划列表
    </div>
    <div class="container">
      <div class="content">
        <div class="main">
          <div class="main-title">添加任务:</div>
          <input type="text" class="input-task"
            placeholder="例如:吃饭,提示:回车即可完成添加任务。"
            @keyup.enter="addTodo"
            v-model="todo"
          />
          <div class="panel">
            <div class="tips">{{unfinished}}个任务未完成</div>
            <div class="tab">
              <a href="#all" :class="{active: visibility === 'all'}">所有任务</a>
              <a href="#unfinished" :class="{active: visibility === 'unfinished'}">未完成的任务</a>
              <a href="#finished" :class="{active: visibility === 'finished'}">完成的任务</a>
            </div>
          </div>
          <div class="list-title">任务列表:</div>
          <div class="tasks">
            <span class="no-task-tip" v-show="!list.length">还没有添加任何任务</span>
            <ul class="list">
              <li v-for="item in filterList" :class="{editing: item === editTodos}">
                <div class="view">
                  <el-checkbox class="btn-check" :checked="item.isChecked" v-model="item.isChecked"></el-checkbox>
                  <!-- <input type="checkbox" class="btn-check" /> -->
                  <label class="item" @dblclick="editTodo(item)" :class="{completed: item.isChecked}">{{item.title}}</label>
                  <el-button icon="close"
                    class="btn-del"
                    @click="delTask(item)">
                  </el-button>
                  <!-- <input type="button" class="btn-del" /> -->
                </div>
                <input type="text" class="edit"
                  v-focus="item === editTodos"
                  @keyup.esc="canclEdit(item)"
                  v-model="item.title"
                  @keyup.enter="editDone(item)"
                  @blur="editDone(item)"
                />
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>


    <script type="text/javascript" src="app.js"></script>
  </body>
</html>

app.js

var store = {
  save (k,v) {
    localStorage.setItem(k, JSON.stringify(v));
  },
  fetch (k) {
    return JSON.parse(localStorage.getItem(k)) || [];
  }
};


var list = store.fetch('backlog');


// var list = [{
//   title: '吃饭睡觉',
//   isChecked: true
// },{
//   title: '打豆豆',
//   isChecked: false
// }];


var filter = {
  'all': (list) => {
    return list;
  },
  'unfinished': (list) => {
    return list.filter((item)=>{
      return !item.isChecked;
    })
  },
  'finished': (list) => {
    return list.filter((item)=>{
      return item.isChecked;
    })
  }
};


var vm = new Vue({
  el: '.container',
  data: {
    list: list,
    todo: '',
    editTodos: '',
    beforeTitle: '',
    visibility: 'all'
  },
  computed: {
    unfinished: function() {
      return this.list.filter(function(v) {
        return !v.isChecked;
      }).length;
    },
    filterList: function() {
      if(filter[this.visibility]) {
        return filter[this.visibility](this.list);
      }else {
        this.visibility = 'all';
        return this.list;
      }
    }
  },
  watch: {
    list: {
      handler: function(val) {
        store.save('backlog', val)
      },
      deep: true
    }
  },
  directives:{
    'focus': {
      update (el, binding) {
        if(binding.value) {
          el.focus();
        }
      }
    }
  },
  methods: {
    addTodo () {
      // console.log(event);
      this.list.push({
        title: this.todo,
        isChecked: false
      });


      this.todo = '';
    },
    editTodo (todo) {
      this.beforeTitle = todo.title;
      this.editTodos = todo;
    },
    canclEdit (todo) {
      todo.title = this.beforeTitle;
      this.editTodos = '';
    },
    editDone (todo) {
      this.editTodos = '';
    },
    delTask (todo) {
      let i = this.list.indexOf(todo);
      this.list.splice(i,1);
    }
  }
});


function watchHashChange() {
  let hash = window.location.hash.slice(1);
  vm.visibility = hash;
}


watchHashChange();


window.addEventListener('hashchange', watchHashChange);


style.css

body {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-items: stretch;
}


.container {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 50%;
  align-self: center;
}


.title {
  font-size: 20px;
  color: white;
  height: 40px;
  text-indent: 25%;
  line-height: 40px;
  background-color: rgb(217, 58, 8);
}


.main-title {
  font-size: 18px;
  padding: 10px 0;
  font-weight: bold;
}


.panel {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  margin: 10px 0;
}


.tips {
  font-size: 14px;
  color: #cf530f;
  font-weight: bold;
}


.list-title {
  font-size: 18px;
  font-weight: bold;
  margin: 10px 0;
}


.tab {
  font-size: 10px;
}


.tab > a {
  padding: 5px 5px;
  text-decoration: none;
}


.tab > .active {
  border: 1px solid #dbe6e9;
}


.input-task, .edit {
  width: 100%;
  height: 30px;
}


ul {
  list-style: none;
  padding: 0 0;
}


li {
  width: 100%;
  position: relative;
}


.edit {
  margin-left: 40px;
  line-height: 40px;
  width: 90%;
  display: none;
}


.btn-check, .btn-del {
  position: absolute;
  width: 20px;
  height: 20px;
}


.view > .btn-check {
  left: 5px;
  top: 8px;
}


.view > .btn-del {
  top: 5px;
  right: 5px;
  border: none;
  color: grey;
  background: transparent;
}


.list .view > .btn-del:hover {
  color: red;
}


.view {
  background-color: white;
  box-shadow: 5px 5px 10px #e8f4f9;
  height: 40px;
  border: 0.5px solid #f4f4f4;
  font-size: 15px;
  color: grey;
}


.view:hover {
  background-color: rgb(228, 244, 235);
}


.view > .item {
  position: absolute;
  left: 40px;
  line-height: 40px;
  width: 90%;
}


.view > .completed {
  text-decoration-line: line-through;
  color: #dbe6e4;
}


li.editing > .view {
  display: none;
}


li.editing > input {
  display: block;
}


vue的向下兼容很不错,直接可以在html中实现,而不用搭建web服务器,这方面比react要好用。

0 0
原创粉丝点击