JSFiddle - React, Tailwind, and code Playground

by ZooeyLai

HTML

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<div id="app">
<form action="">
  <div class="form-group">
    <input type="text" class="form-input" v-model="noteTitle" placeholder="請輸入筆記標題">
    <textarea class="form-input" v-model="noteContent" placeholder="請輸入筆記內容"></textarea>
    <select class="form-input" v-model="selectColor">
      <option value="" selected disabled>選擇顏色</option>
      <option value="red">紅</option>
      <option value="green">綠</option>
      <option value="blue">藍</option>
    </select>
    <button @click="sendNote" class="btn" type='button'>送出</button>

  </div>

</form>
  <div 
    v-for="(note, index) of notes" 
    class="note" 
    :style="{ 'background-color': note.color }"
    >
    <div class="info">
      <h3 class="title">{{note.title}}</h3>
      <p class="content">{{note.content}}</p>      
    </div>
    <button @click="delNote(note, index)" class="btn" type='button'>
    刪除
    </button>
    
  </div>
</div>

CSS

*,
*::after,
*::before {
 padding: 0px;
 margin: 0px;
 box-sizing: border-box;
 line-height: 1.5;
 font-size: 1rem;
}
body{
  background: #F5F5F6;
}
textarea {
  resize: none;
}
#app{
  margin: 1rem;
}
.note{
  padding: 1rem;
  border: 1px solid #D8DAE0;
  border-radius: 0.5rem;
  margin-bottom: 1rem;
  color: #fff;
  display: flex;
}
.info{
  flex: auto;
}

.content{
  font-size: 14px;
  opacity: 0.75;
}
.btn {
    font-size: 1rem;
    padding: 0.5rem 1rem;
    border: 2px solid transparent;
    border-radius: 0.25rem;
    background-color: #e2e8f0;
    color: #475569;
    cursor: pointer;
    display: block;
    text-align: center;
}
.form-group{
    padding: 2rem;
    background: #fff;
    margin-bottom: 1rem;
    display: flex;
    flex-flow: column;
    justify-content: space-between;
    border-radius: 0.5rem;
    gap: 0.5rem;
}
.form-input {
    border: 1px solid #94a3b8;
    padding: 0.5rem 1rem;
    border-radius: 0.25rem;
    flex: auto;
}
.form-input:focus {
    border-color: #4f46e5;
    box-shadow: 0px 0px 0px 3px rgba(79, 70, 229, 0.4);
    outline: none;
}

JavaScript

const { createApp } = Vue

createApp({
  data() {
    return {
      noteTitle: '',
      noteContent: '',
      selectColor: '',
      notes: [{
          title: "春節行程安排",
          content: "吃飽睡,睡飽吃",
          color: "red",
        },
        {
          title: "工作待辦事項",
          content: "詢問各家廠商報價",
          color: "green",
        },
        {
          title: "運動健身計畫",
          content: "每天早上六點去健身",
          color: "blue",
        },
      ]
    }
  },
  methods: {
  	sendNote(){
    	if ( this.noteTitle != '' && this.noteContent != '' && this.selectColor != ''){
        let newNote = {
          title: this.noteTitle,
          content: this.noteContent,
          color: this.selectColor,
        };
        //
        this.notes.push(newNote);
        //清空input資料
        this.noteTitle = '';
        this.noteContent = '';
        this.selectColor = '';
        console.log(newNote)
      }
    },
    
    delNote(note, index) {
    	this.notes.splice(index, 1);
    },  
  },
    mounted() {
        this.notes[0].content = "多出門、到處走走、也要多運動";
        const saveNotes = localStorage.getItem("saveNotes");
        if (saveNotes) {
          this.notes = JSON.parse(saveNotes);
        }
    },
    watch :{
        notes: {
            handler: function(newNotes) {
                localStorage.setItem('saveNotes', JSON.stringify(newNotes));
            }, // 監聽 notes 狀態變化
           deep: true, // 深度監聽,遞迴地監聽 notes 內部物件的變化
         },
    },
}).mount('#app')