vue待辦事項

by superyngo

HTML

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/autosize.js/6.0.1/autosize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/autosize.js/6.0.1/autosize.min.js"></script>
  <body>
    <div id="app">
      <h1>待辦事項</h1>
      <form class="inputArea">
        <input
          type="text"
          class="titleInput"
          v-model="inputData.titleInput"
          placeholder="標題"
        />
        <textarea
          class="contentInput"
          v-model="inputData.contentInput"
          placeholder="內容"
          ref="inputData"
        ></textarea>
        <input type="color" class="colorInput" v-model="inputData.colorInput" />
        <input type="button" value="送出" @click="submit()" />
      </form>

      <div
        v-for="(note,index) in notes"
        class="note"
        :style="{'background-color':note.color}"
      >
        <h3 class="title">{{note.title}}</h3>
        <p class="content">{{note.content}}</p>
        <button class="btn_close" @click="del(index)">X</button>
      </div>
    </div>
  </body>

CSS

*,
*::before,
*::after {
  box-sizing: border-box;
}

img,
picture,
svg,
video {
  display: block;
}

* {
  margin: 0;
  padding: 0;
  font: inherited;
}

html {
  color-scheme: dark light;
}

body {
  min-height: 100svh;
  width: 100svw;
  overflow: auto;
  /* border: 2px solid pink; */
  /* display: grid; */
}

div.note {
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 4rem;
  border: 0.1rem solid black;
  margin: 1rem 1rem;
  padding: 0 1rem;
  color: white;
}

H1 {
  margin: 1rem 1rem;
}

form {
  margin: 1rem 1rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
div.note {
  position: relative;
}

button.btn_close {
  background-color: inherit;
  border: none;
  top: 0.2rem;
  right: 0.2rem;
  position: absolute;
  color: white;
}

button.btn_close:hover {
  cursor: pointer;
}

JavaScript

const { createApp } = Vue;

createApp({
  data() {
    return {
      inputData: {
        titleInput: "",
        contentInput: "",
        colorInput: "#40c4bb",
      },
      notes: [
        {
          title: "春節行程安排",
          content: "多出門、到處走走、也要多運動",
          color: "red",
        },
        {
          title: "工作待辦事項",
          content: "詢問各家廠商報價",
          color: "green",
        },
        {
          title: "運動健身計畫",
          content: "每天早上六點去健身",
          color: "blue",
        },
      ],
    };
  },
  watch: {
    notes: {
      handler(newNotes) {
        localStorage.setItem("saveNotes", JSON.stringify(newNotes));
      },
      deep: true,
    },
  },
  mounted() {
    const saveNotes = localStorage.getItem("saveNotes");
    this.notes = JSON.parse(saveNotes) ?? this.notes;
    autosize(this.$refs.inputData);
  },
  methods: {
    submit() {
      this.notes.push({
        title: this.inputData.titleInput,
        content: this.inputData.contentInput,
        color: this.inputData.colorInput,
      });
      this.inputData = {
        titleInput: "",
        contentInput: "",
        colorInput: "#40c4bb",
      };
    },
    del(index) {
      this.notes.splice(index, 1);
    },
  },
}).mount("#app");