vue3实现一个todo-list

导读:本篇文章讲解 vue3实现一个todo-list,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

实现方式不是最优,主要是为了学习vue3的一些新语法以及属性,各位大佬勿喷~

功能介绍

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

项目的搭建可以参考这篇文章

vue3.x+vite+element-ui+vue-router+vuex+axios搭建项目

相关代码

index.vue

<template>
  <div class="todo-list">
    <el-card class="box-card">
      <template #header>
        <div class="card-header">
          <span>工作计划</span>
          <el-button
            class="button"
            type="primary"
            icon="el-icon-circle-plus"
            circle
            @click="handleClickTodo"
          ></el-button>
        </div>
      </template>

      <template v-if="list.length > 0">
        <todo-item
          v-for="(val, index) in list"
          :key="index"
          :info="val"
        ></todo-item>
      </template>

      <el-empty v-else description="还没有待办的事项~"></el-empty>
    </el-card>

    <add-action v-model:visible="visible"></add-action>
  </div>
</template>

<script>
import AddAction from "./AddTodo.vue";
import TodoItem from "./Item.vue";
import { reactive, toRefs, provide } from "vue";
export default {
  name: "todo-list",
  components: { AddAction, TodoItem },
  setup() {
    const state = reactive({
      visible: false,
      list: [
        {
          title: "1.学习vue3.0",
          time: "2021-08-20",
          desc: "1.ppppppppppppp",
          status: false,
        },
      ],
    });

    const addTodo = (data) => {
      state.list.push(data);
    };

    const delTodo = (title) => {
      state.list = state.list.filter((val) => val.title !== title);
    };

    const handleClickTodo = () => {
      state.visible = true;
    };

    provide("addTodo", addTodo);
    provide("delTodo", delTodo);

    return {
      handleClickTodo,
      ...toRefs(state),
    };
  },
};
</script>

<style>
.todo-list {
  padding: 100px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.text {
  font-size: 14px;
}

.item {
  margin-bottom: 18px;
}

.box-card {
  width: 480px;
}
</style>

AddTodo.vue

<template>
  <el-dialog
    title="新增待办计划"
    v-model="visible"
    width="600px"
    @close="handleClose"
  >
    <el-form
      style="width: 430px"
      :model="form"
      :rules="rules"
      label-width="120px"
      ref="formRef"
    >
      <el-form-item label="计划名称" prop="title">
        <el-input
          v-model="form.title"
          placeholder="请输入待办计划名称"
        ></el-input>
      </el-form-item>
      <el-form-item label="计划完成时间" prop="time">
        <el-date-picker value-format="YYYY/MM/DD" style="width: 100%" v-model="form.time" type="date" placeholder="请选择计划完成时间">
        </el-date-picker>
      </el-form-item>
      <el-form-item label="计划详细描述" prop="desc">
        <el-input
          type="textarea"
          :rows="6"
          v-model="form.desc"
          placeholder="请输入详细待办计划"
        ></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="visible = false">取 消</el-button>
        <el-button type="primary" @click="handleConfirm">确 定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script>
import { reactive, toRefs, ref, inject } from "vue";
export default {
  name: "add-todo",
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
  },
  setup(props, { emit }) {
    const formRef = ref(null)
    const addTodo = inject('addTodo')
    const state = reactive({
      form: {
        title: "",
        desc: "",
        time: "",
        status: false
      },
      rules: {
        title: [
          { required: true, message: '请输入待办计划名称', trigger: ['blur']}
        ],
        time: [
          { required: true, message: '请选择待办计划时间', trigger: ['change']}
        ],
        desc: [
          { required: true, message: '请输入详细待办计划', trigger: ['blur']}
        ]
      },
    });

    const handleClose = () => {
      emit("update:visible", false);
      formRef.value.clearValidate()
      formRef.value.resetFields()
    };

    const handleConfirm = () => {
      formRef.value.validate(valid => {
        if (valid) {
          addTodo(JSON.parse(JSON.stringify(state.form)))
          handleClose()
        }
      })
    }

    return {
      formRef,
      ...toRefs(state),
      handleClose,
      handleConfirm
    };
  },
};
</script>

Item.vue

<template>
  <div class="todo-item">
    <div class="titme-box">
      <el-checkbox v-model="info.status" @click="change"></el-checkbox>
      <h3 :class="info.status ? 'success' : ''">{{ info.title }}</h3>
    </div>

    <div class="del">
      <p class="time" :class="info.status ? 'success' : ''">{{ info.time }}</p>
      <el-button
        type="danger"
        icon="el-icon-delete"
        circle
        size="mini"
        @click="handleDelTodo"
      ></el-button>
    </div>
  </div>
</template>

<script>
import { inject } from "vue";
export default {
  name: "todo-item",
  props: {
    info: {
      type: Object,
      default: () => ({}),
    },
  },
  setup(props) {
    const delTodo = inject("delTodo");
    const handleDelTodo = () => {
      delTodo(props.info.title);
    };

    return {
      handleDelTodo,
    };
  },
};
</script>

<style lang="scss">
.todo-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid rgb(229, 226, 226);
  height: 45px;
  line-height: 45px;
  .success {
    text-decoration: line-through;
  }
  .titme-box {
    display: flex;
    align-items: center;
    h3 {
      padding-left: 12px;
      font-size: 16px;
    }
  }

  .del {
    display: flex;
    align-items: center;
    .time {
      width: 100px;
      font-size: 14px;
    }
  }
}
</style>

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/17176.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!