vue3實現一個todo-list

實現方式不是最優,主要是為瞭學習vue3的一些新語法以及屬性

功能介紹

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

相關代碼

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>

在這裡插入圖片描述

總結

本篇文章就到這裡瞭,希望能給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: