vue、less、element写todolist

效果图


一、运用element写html


        划分区域,头部的添加以及下面的完成和未完成板块,可以运用<el-card>来获得卡片

        1.头部

                input输入框组件

    <!-- 头部板块,el-header顶栏容器 -->
    <el-header style="text-align: left">
      <div class="title">
        <span style="font-size:20px">TodoList</span>
        <!-- input输入框组件 -->
        <el-input
          v-model="input"
          placeholder="Please input"
          clearable 
          //v-on指令,.enter指回车确认修饰符
          @keyup.enter="submit"
        />
      </div>
    </el-header>

        2.主体板块

<!-- 主体板块,主要区域容器 -->
    <el-main style="text-align: left;margin-top:15px;">
      <!-- space间距组件,direction="vertical"定义子元素垂直排序,也可以用wrap实现不换行 -->
      <el-space direction="vertical">

        <!-- card用来将已完成和未完成添加到不同的是card中,使得其以两个卡片的形式出现 -->

        <!--未完成板块-->
        <el-card style="width: 450px" class="todoList">

          <p style="font-size:18px">todo</p>

          <!--任务列表-->
          <div class="todo">
            <span>{{ input }}</span>
            <span>{{ times }}</span>
            <el-checkbox v-model="checked" @change="handleChange()" />
            <el-button text size="small" @click="deleteMessage()">
              <el-icon style="vertical-align: middle" size="15">
                <Delete />
              </el-icon>
            </el-button>
          </div>

        </el-card>

        <!--已完成板块-->
        <el-card style="width: 450px" class="finishList">

          <sp style="font-size:18px">finish</p>

          <!--任务列表-->
          <div class="finish">
            <span>{{ input }}</span>
            <span>{{ times }}</span>
            <el-checkbox v-model="checked" @change="handleChange()" />
            <el-button text size="small" @click="deleteMessage()">
              <el-icon style="vertical-align: middle" size="15">
                <Delete />
              </el-icon>
            </el-button>
          </div>

        </el-card>

      </el-space>
    </el-main>

知识点:

          <div class="todo" >
            <span>{{ item.input }}</span>
            <span>{{ item.times }}</span>
            <el-checkbox v-model="item.checked" @change="handleChange()" />
            <el-button text size="small" @click="deleteMessage()">
              <el-icon style="vertical-align: middle" size="15">
                <Delete />
              </el-icon>
            </el-button>
          </div>

1.icon图标:

       (1) 使用el-icon为SVG图标提供属性

        <el-icon>

                <Delete/>

        </el-icon>

        (2)Delete组件需要先引入注册才能使用

                引入:import { Delete } from "@element-plus/icons-vue";

                注册:components: { Delete },


二、运用less写style


<style lang="less">
p{
  margin-bottom: 10px;
}
.todo {
  border: 1px solid var(--el-border-color);
  padding: 0px 5px;
  margin-bottom: 5px;
  // margin-top: 5px;
  border-radius: 5px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.finish {
  .todo();
  color: gray;
  text-decoration: line-through;
}
</style>

知识点:混合,将一组属性从一组规则集包含(或混入)另一个规则集

        .todo{}

        .finish{.todo()}


三、运用vue写js部分


        1.思路


1.在data()里面初始化所需变量以及属性

data(){
    input:"",
    times:"",
    checked:"",
    list:[]
},

2.在method中撰写方法

        (1)回车获取input数据并添加到list中

submit(){
    //判空
    if(!this.input.trim()){
        alert("请输入数据");
        return;
    }
    //push添加数据
    this.list.push({
        input:this.input,
        times:this.times,
        checked:false
    });
}

        (2)获取当前时间

    getNowTime() {
      var date = new Date();
      var year = date.getFullYear();
      var month = date.getMonth() + 1;
      var dates = date.getDate();
      var hours = date.getHours()<10?"0"+date.getHours():date.getHours();
      var minute = date.getMinutes()<10?"0"+date.getMinutes():date.getMinutes();
      var second = date.getSeconds()<10?"0"+date.getSeconds():date.getSeconds();
      return (
        year +
        "-" +
        month +
        "-" +
        dates +
        " " +
        hours +
        ":" +
        minute +
        ":" +
        second
      );
    },

                将push中的this.times替换成this.getNowTime(),并删除掉data()里面对times的初始化

        (3)获取checkbox状态并存储到本地,实现点击删除该列

//获取checkbox状态并存储到本地
handleChange(item){
    item.checked=!item.checked;
    localStorage.serItem("todolist",JSON.stringify(this.list)
}
//点击实现删除该列
deleteMessage(index){
    this.list.splice(index,1);
}

        (4)将push后的新数组存储到本地,并清空input的内容

submit(){
    this.input = "";
    localStorage.setItem("todolist", JSON.stringify(this.list));
}

        (5)将list的内容渲染到页面

<div class="todo" v-for="(item,index) in list">
    <span>{{item.input}}</span>
    <span>{{item.times}}</span>
    <el-checkbox v-model="item.checked" @change="handleChange(item)" />
    <el-button text size="small" @click="deleteMessage(index)">
        <el-icon style="vertical-align:middle" size="15>
            <Delete />
        </el-icol>
    </el-button>
</div>

        2.会发现上面的代码繁琐又存在很多问题,于是可以进行优化

       


1.对data的优化:

                可以直接通过将属性都放在一个对象里面实现优化

  data() {
    return {
      input: "",
      list: [
        { id: 1, input: "ss", times: "2022-11-22 16:6:4", checked: true },
        { id: 2, input: "ss", times: "2022-11-22 16:6:4", checked: true },
        { id: 3, input: "ss", times: "2022-11-22 16:6:4", checked: false },
      ],
    };
  },

     


  2.对submit的优化

    submit() {
      if (!this.input.trim()) {
        alert("请输入数据");
      } else {
        this.list.push({
          input: this.input,
          times: this.getNowTime(),
          checked: false,
        })
        this.input = ""
      }
    },

     


  2.对checkbox的优化。

                因为v-model可以绑定property并侦听相关事件,所以当我点击checkbox时,checked会自动发生变化,所以可以直接删除对应的点击事件

<el-checkbox v-model="item.checked"/>
<el-button text size="small" @click="deleteMessage(index)>
    <el-icon style="vertical-align: middle" size="15">
        <Delete />
    </el-icon>
</el-button>

       


  3.区分已完成和未完成

                通过计算属性来区分完成和未完成

computed:{
    //已完成
    checkedList(){
        return this.list.filter(item =>item.checked);
    }
    //未完成
    uncheckedList(){
        return this.list.filter(item =>!item.checked);
    }
}
//未完成
<div class="todo" v-for="(item,index) in uncheckedList">
    <span>{{item.input}}</span>
    <span>{{item.times}}</span>
    <el-checkbox v-model="item.checked" />
    <el-button text size="small" @click="deleteMessage(index)">
        <el-icon style="vertical-align:middle" size="15>
            <Delete />
        </el-icol>
    </el-button>
</div>

//已完成
<div class="todo" v-for="(item,index) in checkedList">
    <span>{{item.input}}</span>
    <span>{{item.times}}</span>
    <el-checkbox v-model="item.checked" />
    <el-button text size="small" @click="deleteMessage(index)">
        <el-icon style="vertical-align:middle" size="15>
            <Delete />
        </el-icol>
    </el-button>
</div>

                 知识点:

                        this.list.filter(item => item.checked)

                        ① filter过滤元素,item.checked为true的情况下完成过滤

                        ② 箭头函数的简写:

                                (item)=>{return true}

                                1.当参数只有一个的时候可以省略()      

                                        (item)=>{return true}       item=>return true

                                        (item,index)=>{return true}     //不能简写

                                2.当{}里面可以直接返回函数体的时候可以省略{}

                                        item=>true

                                3.通过三元运算符简化if..else

                                        item=>{ if(Math.random()=>0.5{

                                                                return true

                                                        }else{

                                                                return false

                                                        }

                                        }

                                        //item=>Math.random()=>0.5?true:false


        4.存储到本地的优化

                运用watch监听器来监听list的改变并存储到本地

watch:{
    list:{
        deep:true,
        handler(val){
            localStorage.setItem("todolist",JSON.stringify(this.list))
            //localStorage.setItem("todolist",JSON.stringify(val))
        }
    },
},

                 知识点:

                        watch:{

                                input(val,oldVal){

                                        consloe.log('this.input 发生了变化","改变后的值为:",val,"改变前的值为:",oldVal)

                                }

                        }

                        因为list为引用数据类型,不能直接判等,所以无法监听判断数据是否发生变化,但是用deep深度监听可以实现

   


    5.将本地数据渲染到页面上优化

                直接将本地的列表赋给list,然后通过渲染list渲染到页面上

data(){
    return {
        input:'',
        list:localStorage.getItem("todlist")?JSON.parse(localStorage.getItem("todolist")):[],
    };
},

     


  6.对删除操作的优化

                因为checkedList和uncheckedList只读,所以需要给list中的数据添加唯一性(id)

  data() {
    return {
      input: "",
      list: [
        { id: 1, input: "ss", times: "2022-11-22 16:6:4", checked: true },
        { id: 2, input: "ss", times: "2022-11-22 16:6:4", checked: true },
        { id: 3, input: "ss", times: "2022-11-22 16:6:4", checked: false },
      ],
    };
  },
//点击实现删除该列
deleteMessage(id){
    consol.log("删除列的id":id)
}
           <el-button text size="small" @click="deleteMessage(id)">
              <el-icon style="vertical-align: middle" size="15">
                <Delete />
              </el-icon>
            </el-button>

        但由于已完成和未完成和id没有关系,所以直接选择删除点击的该条数据

            <el-button size="small" text @click="deleteList(item)">
              <el-icon size="18">
                <Delete />
              </el-icon>
            </el-button>
    deleteList(item){
      this.list.splice(this.list.indexOf(item),1)
    }


四、整体代码


<template>
  <el-container style="width: 500px">
    <el-header style="text-align: left">
      <div class="title">
        <p style="font-size:20px">TodoList</p>
        <el-input
          v-model="input"
          placeholder="Please input"
          clearable 
          @keyup.enter="submit"
        />
      </div>
    </el-header>

    <!-- 主体板块,主要区域容器 -->
    <el-main style="text-align: left;margin-top: 15px;">
      <el-space direction="vertical">
        <el-card style="width: 450px" class="todoList">
          <p style="font-size:18px">todo</p>
          <div class="todo" v-for="(item, index) in uncheckedList" >
            <span>{{ item.input }}</span>
            <span>{{ item.times }}</span>
            <el-checkbox v-model="item.checked" />
            <el-button text size="small" @click="deleteMessage(item)">
              <el-icon style="vertical-align: middle" size="15">
                <Delete />
              </el-icon>
            </el-button>
          </div>
        </el-card>

        <el-card style="width: 450px" class="finishList">
          <p style="font-size:18px">finish</p>
          <div class="finish" v-for="(item, index) in checkedList">
            <span>{{ item.input }}</span>
            <span>{{ item.times }}</span>
            <el-checkbox v-model="item.checked" />
            <el-button text size="small" @click="deleteMessage(item)">
              <el-icon style="vertical-align: middle" size="15">
                <Delete />
              </el-icon>
            </el-button>
          </div>
        </el-card>
      </el-space>
    </el-main>
  </el-container>
</template>

<script>
import { Delete } from "@element-plus/icons-vue";

export default {
  components: {
    Delete,
  },
  data() {
    return {
      input: "",
      list: localStorage.getItem("todolist")
        ? JSON.parse(localStorage.getItem("todolist"))
        : [],
    };
  },
  computed:{
    checkedList(){
      return this.list.filter(item=>item.checked);
    },
    uncheckedList(){
      return this.list.filter(item=>!item.checked);
    }
  },
  watch: {
    list: {
      deep: true,
      handler(val) {
        console.log('this.list 发生了改变');
        localStorage.setItem("todolist", JSON.stringify(val))
      }
    }
  },
  methods: {
    submit() {
      if (!this.input.trim()) {
        alert("请输入数据");
      } else {
        this.list.push({
          input: this.input,
          times: this.getNowTime(),
          checked: false,
        })
        this.input = ""
      }
    },
    getNowTime() {
      var date = new Date();
      var year = date.getFullYear();
      var month = date.getMonth() + 1;
      var dates = date.getDate();
      var hours = date.getHours()<10?"0"+date.getHours():date.getHours();
      var minute = date.getMinutes()<10?"0"+date.getMinutes():date.getMinutes();
      var second = date.getSeconds()<10?"0"+date.getSeconds():date.getSeconds();
      return (
        year +
        "-" +
        month +
        "-" +
        dates +
        " " +
        hours +
        ":" +
        minute +
        ":" +
        second
      );
    },

    deleteMessage(item) {
      this.list.splice(this.list.indexOf(item),1);
    },
  },
};
</script>

<style lang="less">
p{
  margin-bottom: 10px;
}
.todo {
  border: 1px solid var(--el-border-color);
  padding: 0px 5px;
  margin-bottom: 5px;
  // margin-top: 5px;
  border-radius: 5px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.finish {
  .todo();
  color: gray;
  text-decoration: line-through;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值