從零打造個人博客靜態頁面與TodoList應用:前端開發實戰指南

前言

在當今數字時代,擁有個人博客和高效的任務管理工具已成為開發者展示自我和提升生產力的標配。本文將帶你從零開始,通過純前端技術實現一個兼具個人博客靜態頁面和TodoList任務管理功能的綜合應用。無論你是前端新手還是希望鞏固基礎的中級開發者,這個項目都將為你提供寶貴的實戰經驗。

一、項目概述與設計

1.1 為什么選擇這個組合項目?

博客頁面和TodoList看似是兩個獨立的功能,但它們的組合能帶來以下優勢:

  • 展示與實用結合:博客展示你的技術思考,TodoList管理你的創作任務

  • 技術覆蓋面廣:涵蓋HTML結構設計、CSS布局美化、JavaScript交互邏輯

  • 可擴展性強:為后續添加后端功能(如用戶認證、數據持久化)奠定基礎

1.2 技術選型

我們選擇純前端實現方案,確保項目輕量且易于部署:

  • 核心三件套:HTML5 + CSS3 + JavaScript (ES6+)

  • CSS框架:使用Tailwind CSS實現快速樣式開發(可選)

  • 圖標庫:Font Awesome或Remix Icon

  • 部署方案:GitHub Pages/Vercel/Netlify

二、博客靜態頁面開發

2.1 HTML結構設計

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>技術博客 | 開發者姓名</title><link rel="stylesheet" href="styles.css">
</head>
<body><header class="blog-header"><nav><div class="logo">我的技術博客</div><ul class="nav-links"><li><a href="#home">首頁</a></li><li><a href="#articles">文章</a></li><li><a href="#projects">項目</a></li><li><a href="#about">關于我</a></li><li><a href="#todo">TodoList</a></li></ul></nav></header><main class="blog-container"><section id="home" class="hero-section"><h1>歡迎來到我的技術博客</h1><p>分享前端開發、算法設計與技術思考</p></section><section id="articles" class="articles-section"><h2>最新文章</h2><div class="article-card"><h3>React Hooks深度解析</h3><p class="meta">發布于2023年5月15日 · 8分鐘閱讀</p><p>本文將深入探討React Hooks的工作原理和最佳實踐...</p><a href="#" class="read-more">閱讀全文</a></div><!-- 更多文章卡片 --></section><section id="projects" class="projects-section"><!-- 項目展示區 --></section></main><footer class="blog-footer"><p>? 2023 我的技術博客. 保留所有權利.</p></footer><script src="script.js"></script>
</body>
</html>

2.2 CSS樣式美化

/* 基礎樣式 */
:root {--primary-color: #3498db;--secondary-color: #2ecc71;--dark-color: #2c3e50;--light-color: #ecf0f1;--danger-color: #e74c3c;
}body {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;line-height: 1.6;color: #333;margin: 0;padding: 0;
}.blog-header {background-color: var(--dark-color);color: white;padding: 1rem 2rem;position: sticky;top: 0;z-index: 100;
}nav {display: flex;justify-content: space-between;align-items: center;
}.logo {font-size: 1.5rem;font-weight: bold;
}.nav-links {display: flex;list-style: none;gap: 2rem;
}.nav-links a {color: white;text-decoration: none;transition: color 0.3s;
}.nav-links a:hover {color: var(--primary-color);
}/* 響應式設計 */
@media (max-width: 768px) {nav {flex-direction: column;}.nav-links {margin-top: 1rem;gap: 1rem;}
}/* 文章卡片樣式 */
.article-card {background: white;border-radius: 8px;box-shadow: 0 2px 5px rgba(0,0,0,0.1);padding: 1.5rem;margin-bottom: 1.5rem;transition: transform 0.3s, box-shadow 0.3s;
}.article-card:hover {transform: translateY(-5px);box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}.meta {color: #7f8c8d;font-size: 0.9rem;
}.read-more {display: inline-block;color: var(--primary-color);text-decoration: none;font-weight: bold;margin-top: 0.5rem;
}.read-more:hover {text-decoration: underline;
}

三、TodoList應用實現

3.1 HTML結構

在博客頁面中添加TodoList部分:

<section id="todo" class="todo-section"><h2>任務管理</h2><div class="todo-container"><div class="todo-input"><input type="text" id="todoInput" placeholder="添加新任務..."><button id="addTodoBtn">添加</button></div><div class="todo-filters"><button class="filter-btn active" data-filter="all">全部</button><button class="filter-btn" data-filter="active">待完成</button><button class="filter-btn" data-filter="completed">已完成</button></div><ul id="todoList" class="todo-list"><!-- 任務將通過JavaScript動態添加 --></ul><div class="todo-stats"><span id="remainingCount">0</span> 個任務待完成<button id="clearCompleted" class="clear-btn">清除已完成</button></div></div>
</section>

3.2 JavaScript功能實現

document.addEventListener('DOMContentLoaded', function() {// DOM元素const todoInput = document.getElementById('todoInput');const addTodoBtn = document.getElementById('addTodoBtn');const todoList = document.getElementById('todoList');const filterBtns = document.querySelectorAll('.filter-btn');const remainingCount = document.getElementById('remainingCount');const clearCompletedBtn = document.getElementById('clearCompleted');// 狀態管理let todos = JSON.parse(localStorage.getItem('todos')) || [];let currentFilter = 'all';// 初始化renderTodoList();updateRemainingCount();// 事件監聽addTodoBtn.addEventListener('click', addTodo);todoInput.addEventListener('keypress', function(e) {if (e.key === 'Enter') addTodo();});clearCompletedBtn.addEventListener('click', clearCompleted);filterBtns.forEach(btn => {btn.addEventListener('click', function() {filterBtns.forEach(b => b.classList.remove('active'));this.classList.add('active');currentFilter = this.dataset.filter;renderTodoList();});});// 功能函數function addTodo() {const text = todoInput.value.trim();if (text) {const newTodo = {id: Date.now(),text,completed: false,createdAt: new Date().toISOString()};todos.unshift(newTodo);saveTodos();renderTodoList();updateRemainingCount();todoInput.value = '';}}function renderTodoList() {todoList.innerHTML = '';const filteredTodos = todos.filter(todo => {if (currentFilter === 'all') return true;if (currentFilter === 'active') return !todo.completed;if (currentFilter === 'completed') return todo.completed;return true;});if (filteredTodos.length === 0) {todoList.innerHTML = '<li class="empty-message">暫無任務</li>';return;}filteredTodos.forEach(todo => {const li = document.createElement('li');li.className = `todo-item ${todo.completed ? 'completed' : ''}`;li.dataset.id = todo.id;li.innerHTML = `<input type="checkbox" ${todo.completed ? 'checked' : ''}><span class="todo-text">${todo.text}</span><button class="delete-btn">×</button><small class="todo-date">${formatDate(todo.createdAt)}</small>`;const checkbox = li.querySelector('input[type="checkbox"]');const deleteBtn = li.querySelector('.delete-btn');checkbox.addEventListener('change', function() {toggleTodoComplete(todo.id);});deleteBtn.addEventListener('click', function() {deleteTodo(todo.id);});todoList.appendChild(li);});}function toggleTodoComplete(id) {todos = todos.map(todo => todo.id === id ? {...todo, completed: !todo.completed} : todo);saveTodos();renderTodoList();updateRemainingCount();}function deleteTodo(id) {todos = todos.filter(todo => todo.id !== id);saveTodos();renderTodoList();updateRemainingCount();}function clearCompleted() {todos = todos.filter(todo => !todo.completed);saveTodos();renderTodoList();}function updateRemainingCount() {const count = todos.filter(todo => !todo.completed).length;remainingCount.textContent = count;}function saveTodos() {localStorage.setItem('todos', JSON.stringify(todos));}function formatDate(dateString) {const options = { year: 'numeric', month: 'short', day: 'numeric' };return new Date(dateString).toLocaleDateString('zh-CN', options);}
});

3.3 TodoList樣式補充

/* TodoList 樣式 */
.todo-section {background-color: #f8f9fa;padding: 2rem;border-radius: 8px;margin-top: 2rem;
}.todo-container {max-width: 600px;margin: 0 auto;background: white;padding: 1.5rem;border-radius: 8px;box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}.todo-input {display: flex;margin-bottom: 1rem;gap: 0.5rem;
}.todo-input input {flex: 1;padding: 0.75rem;border: 1px solid #ddd;border-radius: 4px;font-size: 1rem;
}.todo-input button {padding: 0.75rem 1.5rem;background-color: var(--primary-color);color: white;border: none;border-radius: 4px;cursor: pointer;transition: background-color 0.3s;
}.todo-input button:hover {background-color: #2980b9;
}.todo-filters {display: flex;gap: 0.5rem;margin-bottom: 1rem;
}.filter-btn {padding: 0.5rem 1rem;background: none;border: 1px solid #ddd;border-radius: 4px;cursor: pointer;transition: all 0.3s;
}.filter-btn.active {background-color: var(--primary-color);color: white;border-color: var(--primary-color);
}.todo-list {list-style: none;padding: 0;margin: 0;
}.todo-item {display: flex;align-items: center;padding: 0.75rem;border-bottom: 1px solid #eee;gap: 0.75rem;
}.todo-item.completed .todo-text {text-decoration: line-through;color: #95a5a6;
}.todo-item input[type="checkbox"] {cursor: pointer;
}.todo-text {flex: 1;
}.delete-btn {background: none;border: none;color: var(--danger-color);font-size: 1.25rem;cursor: pointer;opacity: 0.7;transition: opacity 0.3s;
}.delete-btn:hover {opacity: 1;
}.todo-date {color: #95a5a6;font-size: 0.8rem;
}.empty-message {text-align: center;color: #95a5a6;padding: 1rem;
}.todo-stats {display: flex;justify-content: space-between;align-items: center;margin-top: 1rem;color: #7f8c8d;font-size: 0.9rem;
}.clear-btn {background: none;border: none;color: var(--danger-color);cursor: pointer;font-size: 0.9rem;
}.clear-btn:hover {text-decoration: underline;
}

四、項目優化與高級功能

4.1 性能優化建議

  1. 圖片懶加載:對博客中的圖片實現懶加載

<img src="placeholder.jpg" data-src="actual-image.jpg" class="lazy-load">

// 實現懶加載
const lazyImages = document.querySelectorAll('.lazy-load');const imageObserver = new IntersectionObserver((entries, observer) => {entries.forEach(entry => {if (entry.isIntersecting) {const img = entry.target;img.src = img.dataset.src;img.classList.remove('lazy-load');observer.unobserve(img);}});
});lazyImages.forEach(img => imageObserver.observe(img));

? ? 2. 防抖處理:對搜索功能或頻繁觸發的事件添加防抖

function debounce(func, delay) {let timeoutId;return function(...args) {clearTimeout(timeoutId);timeoutId = setTimeout(() => {func.apply(this, args);}, delay);};
}// 使用示例
searchInput.addEventListener('input', debounce(function() {// 搜索邏輯
}, 300));

4.2 可添加的高級功能

  1. Markdown支持:讓博客支持Markdown格式

// 使用marked.js庫
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>// 轉換Markdown為HTML
document.getElementById('markdown-content').innerHTML = marked.parse(markdownText);

? ?2. 主題切換:實現暗黑/明亮模式切換

/* 在:root中添加CSS變量 */
:root {--bg-color: #ffffff;--text-color: #333333;/* 其他變量 */
}/* 暗黑模式 */
[data-theme="dark"] {--bg-color: #1a1a1a;--text-color: #f0f0f0;/* 其他變量 */
}
// 切換主題
function toggleTheme() {const currentTheme = document.documentElement.getAttribute('data-theme');const newTheme = currentTheme === 'dark' ? 'light' : 'dark';document.documentElement.setAttribute('data-theme', newTheme);localStorage.setItem('theme', newTheme);
}// 初始化主題
const savedTheme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-theme', savedTheme);

? 3. PWA支持:讓應用可離線使用

  • 創建manifest.json文件

  • 注冊Service Worker

五、項目部署指南

5.1 GitHub Pages部署

  1. 在GitHub創建新倉庫

  2. 將項目代碼推送到倉庫

  3. 進入倉庫Settings > Pages

  4. 選擇部署分支(通常是main或master)

  5. 等待幾分鐘,訪問提供的URL

5.2 Vercel部署(更推薦)

  1. 注冊Vercel賬號(可使用GitHub賬號登錄)

  2. 點擊"New Project"

  3. 導入你的GitHub倉庫

  4. 配置項目(保持默認即可)

  5. 點擊"Deploy"

  6. 部署完成后會自動獲得一個vercel.app的域名

六、總結與擴展方向

通過本項目,你已經掌握了:

  • 響應式博客頁面的設計與實現

  • 功能完整的TodoList應用開發

  • 本地存儲(localStorage)的使用

  • 前端狀態管理的基本概念

  • 項目部署的基本流程

擴展方向建議

  1. 添加后端支持:使用Node.js + Express或Python Flask為項目添加后端API

  2. 數據庫集成:使用MongoDB或Firebase存儲博客文章和任務數據

  3. 用戶認證:實現登錄注冊功能,讓TodoList可以多用戶使用

  4. 博客管理系統:開發一個簡易的CMS用于管理博客內容

  5. 評論系統:為博客添加

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/80300.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80300.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/80300.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

工作流與n8n:自動化技術的演進與開源工具的核心地位

第一章 工作流的基礎理論介紹 1.1 工作流的定義與核心要素 工作流&#xff08;Workflow&#xff09;是指一系列相互銜接、自動化的業務活動或任務&#xff0c;其核心在于通過規則驅動的流程設計&#xff0c;實現跨系統、跨角色的協同作業。根據國際工作流管理聯盟&#xff08…

WordPress插件:WPJAM Basic優化設置

WPJAM Basic 插件的「優化設置」是我愛水煮魚博客多年使用 WordPress 的經驗而整理的各類優化設置。 一、功能屏蔽 功能屏蔽就是屏蔽一些WordPress中用不上、難用的功能&#xff0c;目前的支持屏蔽以下功能&#xff1a; &#xff08;1&#xff09;屏蔽文章修訂功能 文章修…

Spring AI 入門(持續更新)

介紹 Spring AI 是 Spring 項目中一個面向 AI 應用的模塊&#xff0c;旨在通過集成開源框架、提供標準化的工具和便捷的開發體驗&#xff0c;加速 AI 應用程序的構建和部署。 依賴 <!-- 基于 WebFlux 的響應式 SSE 傳輸 --> <dependency><groupId>org.spr…

c/c++日志庫初識

C/C日志庫&#xff1a;從入門到實踐的深度指南 在軟件開發的世界里&#xff0c;日志&#xff08;Logging&#xff09;扮演著一個沉默卻至關重要的角色。它像是飛行記錄儀的“黑匣子”&#xff0c;記錄著應用程序運行時的關鍵信息&#xff0c;幫助開發者在問題發生時追溯根源&a…

C 語言圖形編程 | 界面 / 動畫 / 字符特效

注&#xff1a;本文為 “C 語言圖形編程” 相關文章合輯。 略作重排&#xff0c;如有內容異常&#xff0c;請看原文。 C 語言圖形化界面——含圖形、按鈕、鼠標、進度條等部件制作&#xff08;帶詳細代碼、講解及注釋&#xff09; 非線性光學元件于 2020-02-15 09:42:37 發布…

開發狂飆VS穩定剎車:Utility Tree如何讓架構決策“快而不失控”

大家好&#xff0c;我是沛哥兒。 在軟件技術架構的世界里&#xff0c;架構師們常常面臨靈魂拷問&#xff1a;高并發和低成本哪個優先級更高&#xff1f; 功能迭代速度和系統穩定性該如何平衡&#xff1f; 當多個質量屬性相互沖突時&#xff0c;該如何做出科學決策&#xff1f; …

SCI論文圖數據提取軟件——GetData Graph Digitizer

在寫綜述或者畢業論文的時候一般會引用前人的文獻數據圖&#xff0c;但是直接截圖獲取來的數據圖通常質量都不太高。因此我們需要從新畫一張圖&#xff0c;可以通過origin繪圖來實現&#xff0c;今天介紹一個新的軟件GetData Graph Digitizer 感謝下面博主分享的破解安裝教程 …

深入探索 Apache Spark:從初識到集群運行原理

深入探索 Apache Spark&#xff1a;從初識到集群運行原理 在當今大數據時代&#xff0c;數據如同奔涌的河流&#xff0c;蘊藏著巨大的價值。如何高效地處理和分析這些海量數據&#xff0c;成為各行各業關注的焦點。Apache Spark 正是為此而生的強大引擎&#xff0c;它以其卓越…

場景可視化與數據編輯器:構建數據應用情境?

場景可視化是將數據與特定的應用場景相結合&#xff0c;借助數據編輯器對數據進行靈活處理和調整&#xff0c;通過模擬和展示真實場景&#xff0c;使企業能夠更直觀地理解數據在實際業務中的應用和影響&#xff0c;為企業的決策和運營提供有力支持。它能夠將抽象的數據轉化為具…

攻防世界-php偽協議和文件包含

fileinclude 可以看到正常回顯里面顯示lan參數有cookie值表示為language 然后進行一個判斷&#xff0c;如果參數不是等于英語&#xff0c;就加上.php&#xff0c;那我們就可以在前面進行注入一個參數&#xff0c;即flag&#xff0c; payload&#xff1a;COOKIE:languageflag …

手撕LFU

博主介紹&#xff1a;程序喵大人 35- 資深C/C/Rust/Android/iOS客戶端開發10年大廠工作經驗嵌入式/人工智能/自動駕駛/音視頻/游戲開發入門級選手《C20高級編程》《C23高級編程》等多本書籍著譯者更多原創精品文章&#xff0c;首發gzh&#xff0c;見文末&#x1f447;&#x1f…

火影bug,未保證短時間數據一致性,拿這個例子講一下Redis

本文只拿這個游戲的bug來舉例Redis&#xff0c;如果有不妥的地方&#xff0c;聯系我進行刪除 描述&#xff1a;今天在高速上打火影&#xff08;有隧道&#xff0c;有時候會卡&#xff09;&#xff0c;發現了個bug&#xff0c;我點了兩次-1000的忍玉&#xff08;大概用了1千七百…

KRaft (Kafka 4.0) 集群配置指南(超簡單,脫離 ZooKeeper 集群)還包含了簡化測試指令的腳本!!!

docker-compose方式部署kafka集群 Kafka 4.0 引入了 KRaft 模式&#xff08;Kafka Raft Metadata Mode&#xff09;&#xff0c;它使 Kafka 集群不再依賴 ZooKeeper 進行元數據管理。KRaft 模式簡化了 Kafka 部署和管理&#xff0c;不需要額外配置 ZooKeeper 服務&#xff0c;…

Admyral - 可擴展的GRC工程自動化平臺

文章目錄 一、關于 Admyral相關鏈接資源關鍵特性 二、安裝系統要求 三、快速開始1、啟動服務 四、核心功能1、自動化即代碼2、AI增強工作流3、雙向同步編輯器4、工作流監控5、企業級基礎設施 五、示例應用六、其他信息許可證遙測說明 一、關于 Admyral Admyral 是一個基于 Pyt…

DDR在PCB布局布線時的注意事項及設計要點

一、布局注意事項 控制器與DDR顆粒的布局 靠近原則&#xff1a;控制器與DDR顆粒應盡量靠近&#xff0c;縮短時鐘&#xff08;CLK&#xff09;、地址/控制線&#xff08;CA&#xff09;、數據線&#xff08;DQ/DQS&#xff09;的走線長度&#xff0c;減少信號延遲差異。 分組隔…

計算機網絡-LDP工作過程詳解

前面我們已經學習了LDP的基礎概念&#xff0c;了解了LDP會話的建立、LDP的標簽控制等知識&#xff0c;今天來整體過一遍LDP的一個工作過程&#xff0c;后面我們再通過實驗深入學習。 一、LDP標簽分發 標簽分發需要基于基礎的路由協議建立LDP會話&#xff0c;激活MPLS和LDP。以…

解構與重構:自動化測試框架的進階認知之旅

目錄 一、自動化測試的介紹 &#xff08;一&#xff09;自動化測試的起源與發展 &#xff08;二&#xff09;自動化測試的定義與目標 &#xff08;三&#xff09;自動化測試的適用場景 二、什么是自動化測試框架 &#xff08;一&#xff09;自動化測試框架的定義 &#x…

跑不出的循環 | LoveySelf 系列定位

最近開始陷入一輪一輪的循環狀態&#xff0c;無奈&#xff0c;只能自我整理一下。23年暑假&#xff0c;在計算機系折騰了一年后&#xff0c;重新打開博客&#xff0c;回想在數學系摸索博客寫作的日子&#xff0c;思緒涌上心頭&#xff0c;我們決定拾起這份力量。當時覺得 hexo …

Redis最新入門教程

文章目錄 Redis最新入門教程1.安裝Redis2.連接Redis3.Redis環境變量配置4.入門Redis4.1 Redis的數據結構4.2 Redis的Key4.3 Redis-String4.4 Redis-Hash4.5 Redis-List4.6 Redis-Set4.7 Redis-Zset 5.在Java中使用Redis6.緩存雪崩、擊穿、穿透6.1 緩存雪崩6.2 緩沖擊穿6.3 緩沖…

一文讀懂Python之requests模塊(36)

一、requests模塊簡介 requests模塊是python中原生的一款基于網絡請求的模塊&#xff0c;功能強大&#xff0c;簡單便捷且高效 &#xff0c;該模塊可以模擬瀏覽器發送請求&#xff0c;主要包括指定url、發起請求、獲取響應數據和持久化存儲&#xff0c;包括 GET、POST、PUT、…