vue 小目标列表 todolist

最终效果:

功能:

添加、删除、判断已完成、未完成

todolist.vue所有代码:

<template>
    <div>
      <div id="app" class="main">
        <h2>小目标列表</h2>
        <div class="list">
          <h3>添加小目标</h3>
          <input type="text" class="text-keyword" placeholder="按回车确认" @keyup.13='addList' v-model="addText"/>
          <!--如果noend等于0,就是全部完成了就显示‘全部完成了’,如果没有就是显示已完成多少条(prolist.length-noend)和未完成多少条(noend)-->
          <p>共有{{prolist.length}}个目标,{{noend==0?"全部完成了":'已完成'+(prolist.length-noend)+',还有'+noend+'条未完成'}}</p>
          <p>
            <input type="radio" name="chooseType" checked="true" @click='chooseList(1)'/><label>所有目标</label>
            <input type="radio" name="chooseType" @click='chooseList(2)'/><label>已完成目标</label>
            <input type="radio" name="chooseType" @click='chooseList(3)'/><label>未完成目标</label>
          </p>
        </div>
        <ul>
          <li class="li1" v-for="(list,index) in newList" :class="{'eidting':curIndex===index}">
            <div>
              <span class="status-span" @click="changeType(index)" :class="{'status-end':list.status}"></span>
              <span @dblclick="curIndex=index">{{list.name}}</span>
              <span class="close" @click='delectList(list)'>X</span>
            </div>
            <input type="text" class="text2" v-model='list.name' @keyup.esc='cancelEdit(list)' @blur='edited' @focus='editBefore(list.name)' @keyup.enter='edited' v-focus/>
          </li>
        </ul>
      </div>
    </div>
</template>

<script>
    export default {
        name: "todolist",
        data(){
          return{
            addText:'',
            //name-名称,status-完成状态
            prolist:[
              {name:"HTML5",status:false},
              {name:"CSS3",status:false},
              {name:"vue",status:false},
              {name:"react",status:false}
            ],
            newList:[],
            curIndex:'',
            beforeEditText:"",
            curType:0
          }
        },

      computed:{
        //计算属性,返回未完成目标的条数,就是数组里面status=false的条数
        noend:function(){
          return this.prolist.filter(function(item){
            return !item.status
          }).length;
        }
      },
      methods:{
        addList(){
          //添加进来默认status=false,就是未完成状态
          this.prolist.push({
            name:this.addText,
            status:false
          });
          //添加后,清空addText
          this.addText="";
        },
        chooseList(type){
          //type=1时,选择所有目标
          //type=2时,选择所有已完成目标
          //type=3时,选择所有未完成目标
          this.curType=type;
          switch(type){
            case 1:this.newList=this.prolist;break;
            case 2:this.newList=this.prolist.filter(function(item){return item.status});break;
            case 3:this.newList=this.prolist.filter(function(item){return !item.status});break;
          }
        },
        /*改变单条数据的完成状态*/
        changeType(index){
          this.newList[index].status=!this.newList[index].status;
          //更新数据
          this.chooseList(this.curType);
        },
        delectList(list){
          var index=this.prolist.indexOf(list);
          //根据索引,删除数组某一项
          this.prolist.splice(index,1);
          //更新newList  newList可能经过this.prolist.filter()赋值,这样的话,删除了prolist不会影响到newList  那么就要手动更新newList
          //this.newList=this.prolist;
          this.chooseList(this.curType);
        },
        //修改前
        editBefore(name){
          //先记录当前项(比如这一项,{name:"HTML5",status:false})
          //beforeEditText="HTML5"
          this.beforeEditText=name;
        },
        //修改完成后
        edited(){
          //修改完了,设置curIndex="",这样输入框就隐藏,其它元素就会显示。因为在li元素 写了::class="{'eidting':curIndex===index}"  当curIndex不等于index时,eidting类名就清除了!
          //输入框利用v-model绑定了当前项(比如这一项,{name:"HTML5",status:false})的name,当在输入框编辑的时候,比如改成‘HTML’,实际上当前项的name已经变成了‘HTML’,所以,这一步只是清除eidting类名,隐藏输入框而已
          //还有一个要注意的就是虽然li遍历的是newList,比如改了newList的这一项({name:"HTML5",status:false}),比如改成这样({name:"HTML",status:true})。实际上prolist的这一项({name:"HTML5",status:false}),也会被改成({name:"HTML",status:true})。因为这里是一个对象,而且公用一个堆栈!修改其中一个,另一个会被影响到
          this.curIndex="";
        },
        //取消修改
        cancelEdit(val){
          //上面说了输入框利用v-model绑定了当前项(比如这一项,{name:"HTML5",status:false})的name,当在输入框编辑的时候,比如改成‘HTML’,实际上当前项的name已经变成了‘HTML’,所以,这一步就是把之前保存的beforeEditText赋值给当前项的name属性,起到一个恢复原来值得作用!
          val.name=this.beforeEditText;
          this.curIndex="";
        }
      },

      mounted(){
        //初始化,把prolist赋值给newList。默认显示所有目标
        this.newList=this.prolist;
      },
      directives:{
        "focus":{
          update(el){
            el.focus();
          }
        }
      }
    }
</script>

<style scoped>
  body{font-family: "微软雅黑";font-size: 14px;}
  input{font-size: 14px;}
  body,ul,div,html{padding: 0;margin: 0;}
  .hidden{display: none;}
  .main{width: 800px;margin: 0 auto;}
  li{list-style-type: none;line-height: 40px;position: relative;border: 1px solid transparent;padding: 0 20px;}
  li .status-span{display: block;width: 10px;height: 10px;background: #ccc;margin: 14px 10px 0 0 ;float: left;}
  li .status-span.status-end{
    background: black;
  }
  li .close{position: absolute;color: yellowgreen;font-size: 20px;line-height: 40px;height: 40px;right: 20px;cursor: pointer;display: none;top: 0;}
  li:hover{border: 1px solid black;}
  li:hover .close{display: block;}
  li div{display: block;}
  li.eidting div{display: none;}
  li .text2{height: 40px;padding-left: 10px;box-sizing: border-box;margin-left: 10px;width: 80%;display: none;}
  li.eidting .text2{display: block;}
  li .text-keyword{height: 40px;padding-left: 10px;box-sizing: border-box;margin-left: 10px;width: 80%;display: none;}
  .text-keyword{box-sizing: border-box;width: 300px;height: 40px;padding-left: 10px;outline: none;}
</style>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值