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下打开网页:

双击静态页面打开

相关推荐
程序喵大人5 小时前
【C++入门】编译链接模型 - 01 一个 C++ 程序是怎样变成可执行文件的
开发语言·c++·编译链接模型
陈随易5 小时前
bm2,Node.js 与 Bun 项目部署新选择
前端·后端·程序员
可乐鸡翅yeah_7 小时前
FFmpeg 生成 HLS 独立分片 independent‑segments 参数到底有什么用
javascript·ffmpeg·音视频·safari·m3u8
sunshine22 girl7 小时前
Java学习七 Java 项目实战1-项目创建和主页面搭建
java·开发语言·学习
福兮说7 小时前
canvas 旋转图片的六个坑:四角被裁、Math.ceil 多出 1px 黑边、JPG 角发黑、翻转方向反了
前端·javascript·图像处理·canvas
菜鸟~noob2337 小时前
【电子战】第三季预告—波武器与电子系统强力毁伤
开发语言·数据库·matlab·电子战
Ai-_Man8 小时前
您您这可以把Grok的多个会话比如说。左侧的多个会话一次性导出吗?不是单条会话里面的多次会对话。AI导出鸭
javascript·人工智能·ai·小程序·电脑
惊讶的猫8 小时前
工具选对之后还不够:商城 Agent 的参数与权限治理
开发语言·python
传人once8 小时前
多图片上传预览功能如何写
前端·css·html·jquery·html5
cmpxr_8 小时前
【MicroPython】如何刷新ESP8266的固件
开发语言·micropython