Astro 实现TodoList网页应用案例

Astro 是一个现代化的静态站点生成器和前端框架,它具有独特的设计理念:岛屿架构。它允许开发人员使用组件化的方式构建内容优先的网站,将各种技术栈(如React、Vue、Svelte等)的组件无缝集成到同一个项目中。

1、创建项目:

bash 复制代码
npm create astro@latest astro-todolist
bash 复制代码
cd astro-todolist
code .

创建组件

在 src/components/ 目录下创建 TodoList.astro

bash 复制代码
---
---

<div id="todo-app">
  <h1>TodoList</h1>
  <form id="todo-form">
    <input type="text" id="todo-input" placeholder="Add a new task">
    <button type="submit" id="add-button">Add</button>
  </form>
  <ul id="todo-list"></ul>
</div>

<script>
  const todoForm = document.getElementById('todo-form') as HTMLFormElement;
  const todoInput = document.getElementById('todo-input') as HTMLInputElement;
  const todoList = document.getElementById('todo-list') as HTMLUListElement;

  interface Todo {
    text: string;
    completed: boolean;
  }

  function loadTodos() {
    const todosJson = localStorage.getItem('todos');
    const todos: Todo[] = todosJson ? JSON.parse(todosJson) : [];
    todos.forEach(todo => {
      addTodoToDOM(todo.text, todo.completed);
    });
  }

  function saveTodos() {
    const todos: Todo[] = Array.from(todoList.children).map(li => ({
      text: li.querySelector('span')?.textContent || '',
      completed: li.classList.contains('completed')
    }));
    localStorage.setItem('todos', JSON.stringify(todos));
  }

  function addTodoToDOM(text: string, completed = false) {
    const li = document.createElement('li');
    li.className = 'todo-item' + (completed ? ' completed' : '');
    li.innerHTML = `
      <input type="checkbox" ${completed ? 'checked' : ''}>
      <span>${text}</span>
      <button class="delete-button">Delete</button>
    `;

    const checkbox = li.querySelector('input[type="checkbox"]');
    if (checkbox) {
      checkbox.addEventListener('change', function() {
        li.classList.toggle('completed');
        if (li.classList.contains('completed')) {
          todoList.appendChild(li);
        } else {
          todoList.insertBefore(li, todoList.firstChild);
        }
        saveTodos();
      });
    }

    const deleteButton = li.querySelector('.delete-button');
    if (deleteButton) {
      deleteButton.addEventListener('click', function() {
        li.remove();
        saveTodos();
      });
    }

    if (completed) {
      todoList.appendChild(li);
    } else {
      todoList.insertBefore(li, todoList.firstChild);
    }
  }

  todoForm.addEventListener('submit', function(e: Event) {
    e.preventDefault();
    if (todoInput.value.trim() === '') return;

    addTodoToDOM(todoInput.value);
    saveTodos();
    todoInput.value = '';
  });

  document.addEventListener('DOMContentLoaded', loadTodos);
</script>

<style>
 body {
      font-family: Arial, sans-serif;
    max-width: 500px;
    margin: 0 auto;
    padding: 20px;
  }
  h1 {
    text-align: center;
  }
  #todo-form {
    display: flex;
    margin-bottom: 20px;
  }
  #todo-input {
    flex-grow: 1;
    padding: 10px;
    font-size: 16px;
    border: 1px solid #ddd;
    border-radius: 4px 0 0 4px;
  }
  #add-button {
    padding: 10px 20px;
    font-size: 16px;
    background-color: #4CAF50;
    color: white;
    border: none;
    border-radius: 0 4px 4px 0;
    cursor: pointer;
  }
  #todo-list {
    list-style-type: none;
    padding: 0;
  }
  .todo-item {
    display: flex;
    align-items: center;
    padding: 10px;
    background-color: #f9f9f9;
    border: 1px solid #ddd;
    margin-bottom: 10px;
    border-radius: 4px;
  }
  .todo-item.completed {
    text-decoration: line-through;
    opacity: 0.6;
  }
  .todo-item input[type="checkbox"] {
    margin-right: 10px;
  }
  .delete-button {
    margin-left: auto;
    background-color: #f44336;
    color: white;
    border: none;
    padding: 5px 10px;
    border-radius: 4px;
    cursor: pointer;
  }
</style>

创建页面

在 src/pages/index.astro 中使用 TodoList 组件:

bash 复制代码
---
import TodoList from '../components/TodoList.astro';
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>Astro TodoList</title>
  </head>
  <body>
    <TodoList />
  </body>
</html>

2、运行

测试

bash 复制代码
npm run dev


构建部署

bash 复制代码
npm run build
npx netlify-cli deploy --prod


dist下打开网页:

双击静态页面打开

相关推荐
昵称画2 小时前
交接班记录电子化:三班之间的信息不漏
开发语言·数据库·人工智能·低代码·php
“AI国潮设计-小江”2 小时前
【AIGC实战】Python+SDXL批量生成“潮汕英歌舞不倒翁”IP | 角色一致性与多场景融合方案,附完整代码
开发语言·人工智能·python·prompt·aigc
沙蒿同学2 小时前
不引 Ghostscript:我用纯 Go 给 PDF 做了一场「压缩手术」
前端·后端·github
传奇开心果编程2 小时前
【Rust入门练中学】第6课:结构体与方法
开发语言·rust·结构体·编程语言理论·结构体方法·编程通用语言
Linux_cy2 小时前
服务器管理工具哪个好用?我用了七八个
运维·服务器·javascript·python·ssh·面板·gmssh
code tsunami3 小时前
【无标题】
开发语言·python
变与不变8063 小时前
jQuery细节以及使用应用场景
前端·javascript·jquery
CodeGL3 小时前
10、Python基础之进程和线程
开发语言·python
TechWayfarer4 小时前
PHP漏洞被利用,怎么揪出攻击IP?
开发语言·python·tcp/ip·网络安全·php
SailingCoder5 小时前
【封闭结束1】端到端交付:Agent 一次请求如何走完全链路
前端·安全·ai·面试·agent·harness