iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0
JavaScript

30天 JavaScript 提升計畫:從零到精通結合2024年的創新功能系列 第 29

第 29 天:實戰項目 - 基礎項目 To_do List 構建

  • 分享至 

  • xImage
  •  

評估需要用到的 JavaScript 功能


從頭構建一個簡單的項目 To_do List 當作整個知識點的收尾,其實購物車的想法也不錯其實都大同小異,因為裡面包含 CRUD,但是這裡就先用大家都熟悉的 To_do List 當練習,需要用到的技能如下:

需求評估


構建一個基本的待辦事項應用,主要包括以下功能:

  1. 添加待辦事項:user 可以添加新的待辦事項。
  2. 查看待辦事項列表:user 可以查看所有待辦事項。
  3. 標記為完成:user 可以將待辦事項標記為完成。
  4. 刪除待辦事項:user 可以刪除不再需要的待辦事項。

原生 JavaScript 開發


切版不在這次的範圍,如果真的需要,可以去參考 codepen 上的版型,或是找六角相關視頻應該也有!

🔔 參考視頻:Todo List Kata 練習 | 六角學院 | Vue 3 新手夏令營 | Vue 學習紀錄

Todo List Kata 練習 | 六角學院 | Vue 3 新手夏令營 | Vue 學習紀錄

<!DOCTYPE html>
<html lang="zh-Hant">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>待辦事項</title>
    <style>
        /* 添加一些簡單的樣式 */
        ul {
            list-style-type: none;
            padding: 0;
        }
        li {
            margin: 5px 0;
        }
    </style>
</head>
<body>
    <div>
        <h1>待辦事項</h1>
        <input id="newTodo" placeholder="添加新待辦事項" />
        <button id="addBtn">添加</button>
        <ul id="todoList"></ul>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="script.js"></script>
</body>
</html>
const todos = [];
const todoList = document.getElementById('todoList');
const newTodoInput = document.getElementById('newTodo');
const addBtn = document.getElementById('addBtn');

// 取得待辦事項
const fetchTodos = async () => {
    try {
        const response = await axios.get('http://localhost:8000/api/todos');
        response.data.forEach(todo => todos.push(todo));
        renderTodos();
    } catch (error) {
        console.error('Error fetching todos:', error);
    }
};

// 添加待辦事項
const addTodo = async () => {
    const newTodoTitle = newTodoInput.value.trim();
    if (!newTodoTitle) return;

    try {
        const response = await axios.post('http://localhost:8000/api/todos', { title: newTodoTitle });
        todos.push(response.data);
        newTodoInput.value = '';
        renderTodos();
    } catch (error) {
        console.error('Error adding todo:', error);
    }
};

// 更新待辦事項
const updateTodo = async (todo) => {
    try {
        await axios.put(`http://localhost:8000/api/todos/${todo.id}`, todo);
    } catch (error) {
        console.error('Error updating todo:', error);
    }
};

// 刪除待辦事項
const deleteTodo = async (todo) => {
    try {
        await axios.delete(`http://localhost:8000/api/todos/${todo.id}`);
        const index = todos.findIndex(item => item.id === todo.id);
        if (index > -1) {
            todos.splice(index, 1);
            renderTodos();
        }
    } catch (error) {
        console.error('Error deleting todo:', error);
    }
};

// 渲染待辦事項
const renderTodos = () => {
    todoList.innerHTML = '';
    todos.forEach(todo => {
        const li = document.createElement('li');
        li.innerHTML = `
            <input type="checkbox" ${todo.completed ? 'checked' : ''} onchange="updateTodoStatus(${todo.id}, this.checked)" />
            ${todo.title}
            <button onclick="deleteTodoItem(${todo.id})">刪除</button>
        `;
        todoList.appendChild(li);
    });
};

// 更新待辦事項狀態
const updateTodoStatus = (id, completed) => {
    const todo = todos.find(t => t.id === id);
    if (todo) {
        todo.completed = completed;
        updateTodo(todo);
    }
};

// 事件監聽
addBtn.addEventListener('click', addTodo);
newTodoInput.addEventListener('keyup', (event) => {
    if (event.key === 'Enter') {
        addTodo();
    }
});

// 初始化
fetchTodos();

轉成前端框架


前端環境:Vue3 Composition API、Axios、vite

<template>
  <div>
    <h1>待辦事項</h1>
    <input v-model="newTodo" @keyup.enter="addTodo" placeholder="添加新待辦事項" />
    <ul>
      <li v-for="todo in todos" :key="todo.id">
        <input type="checkbox" v-model="todo.completed" @change="updateTodo(todo)" />
        {{ todo.title }}
        <button @click="deleteTodo(todo)">刪除</button>
      </li>
    </ul>
  </div>
</template>
// <script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';

const todos = ref([]);
const newTodo = ref('');

onMounted(() => { fetchTodos });

const fetchTodos = async () => {
  try {
    const response = await axios.get('http://localhost:8000/api/todos');
    todos.value = response.data;
  } catch (error) {
    console.error('Error fetching todos:', error);
  }
};

const addTodo = async () => {
  if (!newTodo.value) return;
  try {
    const response = await axios.post('http://localhost:8000/api/todos', { title: newTodo.value });
    todos.value.push(response.data);
    newTodo.value = '';
  } catch (error) {
    console.error('Error adding todo:', error);
  }
};

const updateTodo = async (todo) => {
  try {
    await axios.put(`http://localhost:8000/api/todos/${todo.id}`, todo);
  } catch (error) {
    console.error('Error updating todo:', error);
  }
};

const deleteTodo = async (todo) => {
  try {
    await axios.delete(`http://localhost:8000/api/todos/${todo.id}`);
    todos.value = todos.value.filter(t => t.id !== todo.id);
  } catch (error) {
    console.error('Error deleting todo:', error);
  }
};

上一篇
第 28 天:JavaScript 設計模式
下一篇
第 30 天:JavaScript 面試題與學習資源
系列文
30天 JavaScript 提升計畫:從零到精通結合2024年的創新功能30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言