news 2026/9/9 2:59:54

3小时零基础入门前端三件套:HTML+CSS+JS实战待办事项

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
3小时零基础入门前端三件套:HTML+CSS+JS实战待办事项

写前端三件套(HTML+CSS+JS)的文章很多,但大多数要么太理论,读完还是写不出页面;要么太零散,今天学个标签明天学个选择器,学完就忘。这篇文章想换一种讲法:不做大而全的百科式罗列,而是用 3 小时带你走完一条“能动手、能验证、能看懂自己代码”的最小路径。

先说判断:零基础学前端,最忌讳的不是笨,而是顺序错了。很多人一上来就啃厚厚的参考书,或者直接扎进 Vue、React 框架里,结果 HTML 语义还没搞清,就被组件、状态管理砸晕,最后心态崩了。正确顺序应该是什么?先用 HTML 搭骨架,再用 CSS 做样式,最后用 JS 加交互——这也是为什么业界把这三种语言叫做“前端三件套”。

如果你正处在这些阶段,这篇文章非常适合你:

  • 完全零基础,想转行或自学前端,但不知道从哪里下手;
  • 学过一点 HTML 和 CSS,但 JS 一直没入门,写不出交互效果;
  • 想快速了解网页从“静态”到“动态”的完整过程,再决定要不要深入。

读完这篇文章,你会亲手做出一个可交互的待办事项页面,并理解背后每一行代码的作用。这个项目很小,但它把 HTML 结构、CSS 布局、JS 事件处理、DOM 操作全部串起来了。跑通它,你就等于掌握了一套“前端思考方式”。

下面是 3 小时的学习路线:

时间段学习内容产出
第 1 小时HTML 核心标签与页面结构一个语义清晰的页面骨架
第 2 小时CSS 选择器、盒模型、Flex 布局一个整洁、具备现代感的页面
第 3 小时JS 变量、事件、DOM 操作一个能增删数据的待办清单

1. 这篇文章真正要解决的问题

很多人问“前端难不难”,这个问题很难一句话回答。更准确的问法是:“你希望用前端解决什么问题?”

如果你只是想看懂网页、改改页面样式、给自己做个简单工具页,那么前端三件套的入门成本非常低。低到什么程度呢?你只需要一个浏览器,再加一个文本编辑器(比如 VS Code),不需要安装复杂的开发环境,不需要配置服务器,写完 HTML 文件直接用浏览器打开就能看到效果。这种“所见即所得”的反馈速度,是很多人愿意学前端的重要原因。

但如果你是想马上找一份前端开发的工作,那就需要清醒一点:3 小时只能帮你建立完整的概念框架和动手能力基础,距离企业用人要求还有不小的距离。本文的目标是把地基打牢,而不是给你造一栋精装房。

前端这个领域,表面上是三个技术,底层其实是两种思维:

  • 结构思维:用 HTML 把内容组织成树状结构,让浏览器和搜索引擎都能理解;
  • 变化思维:用 CSS 控制视觉表现,用 JS 响应用户行为,让页面从“死”的变成“活”的。

很多初学者写页面乱,本质是结构思维没建立起来;写交互总报错,本质是变化思维没建立起来。这两种思维,恰恰是这三小时里最值得你花精力体会的东西。

具体到本文,你会看到:

  • HTML 不是“背标签”,而是“设计内容层级”;
  • CSS 不是“背属性”,而是“理解布局规则”;
  • JS 不是“背语法”,而是“理解数据和事件”。

为了避免你学完就忘,整个项目的核心主线是**“做一个待办事项页面”**。你没有看错,就是很多人瞧不上眼的 Todo List。因为这个项目天然包含了前端最核心的几件事:用户输入、列表渲染、数据增删、界面状态变化。能把这个项目做明白,你已经超过了一半的“只看不练型选手”。

2. HTML:网页的结构骨架与核心标签

2.1 HTML 是什么,不是什么

HTML 全称是 HyperText Markup Language(超文本标记语言)。注意,它叫“标记语言”,不是“编程语言”。它没有变量、没有逻辑判断、没有循环,它的工作只有一件事:用标签描述内容的结构。

标签的书写形式非常简单:由尖括号包裹的标签名组成,通常有开始标签和结束标签。

<p>这是一段文本</p>

也有少数自闭合标签,比如换行标签:

<br>

你要把 HTML 理解成一份“文档大纲”,它告诉浏览器:这里有标题,这里是段落,这里是一个链接,那里是一张图片。至于标题用什么颜色、段落显示多大字号、图片显示多宽,这些都不归 HTML 管,而是 CSS 的工作。

很多初学者刚学 HTML,特别喜欢背标签,什么articlesectionasidefooter,背得头大。这里给个建议:先记住使用频率最高的 20 个标签,其余的等用到再查。前端是一个极其依赖查文档的领域,这不是丢人的事,反而是从业常态。

2.2 一份 HTML 文档的标准结构

任何 HTML 文件,打开后都是下面这个模板。它不需要你记,VS Code 里输入!再按 Tab 键就能自动生成。

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>我的第一个页面</title> </head> <body> <h1>你好,前端</h1> <p>这是我的第一个页面。</p> </body> </html>

几个关键点解释一下:

  • <!DOCTYPE html>:告诉浏览器当前文档使用的是 HTML5 标准。不要省略,否则浏览器会进入“怪异模式”,导致样式解析异常。
  • <html lang="zh-CN">:声明页面语言为中文,这对无障碍访问和 SEO 都有影响。
  • <head>:存放页面的元信息,比如字符集、视口配置、标题、外部样式表和脚本的引入。这里的 content 不会直接显示在页面上。
  • <meta charset="UTF-8">:指定字符编码为 UTF-8。如果不写,页面上中文很可能变成乱码。
  • <meta name="viewport" ...>:移动端适配必备,控制页面在手机上的显示宽度。不写的话,手机浏览器会把桌面端页面整体缩小显示,体验很差。
  • <body>:所有用户能看到的页面内容,都必须放进这里。

记住一个习惯:先写结构,再填内容。不要一上来就急着打字,先在脑子里想清楚,这个页面由哪些模块组成,每个模块是什么关系。

2.3 常用的 HTML 标签与语义化

下面这张表覆盖了日常开发中最常用的一批标签,建议你先按这个范围学,不要贪多。

标签作用典型使用场景
h1~h6标题,一级到六级页面主标题、章节标题
p段落正文文本
a超链接跳转其他页面或锚点
img图片展示图片素材
ul/ol/li无序列表 / 有序列表 / 列表项导航菜单、商品列表
div无语义的分块容器页面布局分区
span无语义的行内容器对一段文本的部分内容做样式
input输入框表单、搜索框
button按钮提交、触发交互
form表单容器收集用户输入
nav导航区域顶部菜单栏
header页头页面顶部区域
main页面主要内容区主体内容容器
footer页脚版权信息、底部链接

那么“语义化”是什么意思?现在很多表格布局时代的老前端喜欢全用div一把梭,但语义化标签的初衷是让“代码自己说明自己”。你可以想象自己是一名阅读你代码的同事,如果他打开文件第一眼就看到headernavmainfooter,会比看到一堆div class="top"div class="mid"div id="bottom"轻松得多。更重要的是,搜索引擎爬虫和屏幕阅读器都会根据语义标签来理解页面结构,这对 SEO 和无障碍体验都有实实在在的好处。

2.4 实战:搭建待办页面的 HTML 骨架

现在开始动手。创建一个新文件夹,命名为todo-app,在里面新建一个文件index.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="style.css"> </head> <body> <div class="app"> <h1>📝 我的待办清单</h1> <div class="input-area"> <input type="text" id="todoInput" placeholder="输入新的待办事项..."> <button id="addBtn">添加</button> </div> <ul id="todoList"> <li class="todo-item"> <input type="checkbox" class="todo-checkbox"> <span>学习 HTML 标签</span> <button class="delete-btn">删除</button> </li> <li class="todo-item"> <input type="checkbox" class="todo-checkbox"> <span>学习 CSS 布局</span> <button class="delete-btn">删除</button> </li> </ul> </div> <script src="script.js"></script> </body> </html>

注意几个细节:

  • <link rel="stylesheet" href="style.css">放在head中,表示引入外部 CSS 文件;
  • <script src="script.js">放在body的末尾。因为 JS 要操作 DOM,而 DOM 必须等页面加载完才能操作。放在末尾可以避免“还没渲染完就开始找节点”的问题。
  • 我用了两个input,一个是文本框,一个是复选框,它们都是普通的输入控件,不要混淆。

现在就差 CSS 和 JS 文件了。别急着关编辑器,我们继续。

3. CSS:从“白底黑字”到“现代界面”

3.1 CSS 到底是干什么的

CSS 全称是 Cascading Style Sheets(层叠样式表)。它的核心价值在于:把“内容”和“表现”分离。同样一份 HTML,引用不同的 CSS,可以呈现出完全不同的视觉风格。这就像同一件白 T 恤,搭休闲裤是日常风,搭半身裙是通勤风,搭牛仔裤是街头风——衣服是 HTML,搭配方案是 CSS。

初学者最容易在 CSS 里遇到的困惑是:为什么我设的颜色不生效?为什么这个元素不居中?要解决这些问题,不能只背属性,必须理解 CSS 的两个底层机制:

  • 选择器:决定“样式作用于哪个元素”;
  • 盒模型:决定“元素在页面中占多大空间、怎么排列”。

3.2 选择器:精准定位要修饰的元素

CSS 选择器种类很多,但入门阶段掌握下面五类就够用。

选择器写法示例作用
标签选择器标签名p { color: red; }选择所有p标签
类选择器.类名.app { width: 500px; }选择所有class="app"的元素
ID 选择器#id名#addBtn { padding: 8px; }选择id="addBtn"的元素
后代选择器父 子.input-area input { }选择父元素内部的所有匹配子元素
伪类选择器元素:hoverbutton:hover { }元素处于某个状态时应用样式

这里特别提醒两个高频误区:

第一,ID 在同一个页面里只能出现一次。它是元素的“身份证号”,不能重复使用。如果需要为多个元素设置相同样式,应该使用类选择器。

第二,后代选择器并不要求必须是父子关系,只要是祖先和后代即可。比如.app input会选择.app内部所有层级的input,即使中间还包裹了div

关于伪类选择器,很多初学者被“伪”字吓到,其实它不过是指“元素在某一种特殊状态下的样式”。最常见的:hover是鼠标悬停。此外你还会经常见到:first-child:last-child:nth-child()这类用于选位置的伪类,它们在做列表样式时非常有用。

3.3 盒模型:理解空间的底层逻辑

在 CSS 中,每一个元素都可以看作一个盒子。从内到外分别是:

  • Content(内容区):文本或图片显示的区域;
  • Padding(内边距):内容与边框之间的距离;
  • Border(边框):盒子的边框;
  • Margin(外边距):盒子与其他元素之间的间距。

一个盒子的实际宽度公式,是面试题也爱考的经典问题:

实际宽度 = width + padding-left + padding-right + border-left + border-right

这意味着,如果你给一个元素设置了width: 200pxpadding: 20px,它最终的视觉宽度不是 200px,而是 240px。这个问题困扰过无数新手,因为它直接导致“明明设置了宽度,却还是溢出”的现象。

解决办法有两个:

一是记住公式,计算时手动扣除。

二是使用box-sizing属性,把宽度计算方式从content-box改成border-box

* { box-sizing: border-box; }

个人强烈建议你在所有新项目里都加上这一行。border-box的意思是,你设置的width就是元素最终占据的宽度,padding 和 border 都在这 200px 内部消化。这样一来,心智负担会小很多。

3.4 布局方式:别急着学 Grid,先把 Flex 用熟

CSS 发展到今天,主流的布局方式已经不再是float,更不是position一点点拼凑。你要学的下一个重点就是Flexbox(弹性布局)

Flex 最核心的一句话是:让容器里的子元素按照主轴方向排列,并自动处理空间分配与对齐。使用方式很简单,给父容器写上display: flex,它的直接子元素就会变成“弹性项”,沿水平方向排成一行。

.input-area { display: flex; gap: 8px; }

这是 Flex 布局中最高频、最容易见效的写法之一。gap用于控制子元素之间的间距。再用justify-content控制水平方向的对齐,比如center居中、space-between两端对齐;用align-items控制垂直方向的对齐,比如center居中对齐。

初学者常犯的错是把 Flex 属性写在子元素上。记住,display: flexjustify-contentalign-items都是写在父容器上的。子元素只需要通过flex: 1这类属性告诉浏览器“我要占据剩余空间”。

3.5 完整 CSS:让待办页面“活”起来

现在在todo-app文件夹下新建一个style.css,写入下面的代码:

/* 文件路径:todo-app/style.css */ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; } .app { width: 480px; max-width: 90%; background: #ffffff; border-radius: 16px; padding: 24px; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2); } .app h1 { text-align: center; font-size: 24px; color: #333; margin-bottom: 16px; } .input-area { display: flex; gap: 8px; margin-bottom: 16px; } #todoInput { flex: 1; padding: 10px 14px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; outline: none; transition: border-color 0.2s; } #todoInput:focus { border-color: #667eea; } #addBtn { padding: 10px 18px; background-color: #667eea; color: #fff; border: none; border-radius: 8px; font-size: 14px; cursor: pointer; transition: background-color 0.2s; } #addBtn:hover { background-color: #5a6fd6; } #todoList { list-style: none; } .todo-item { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px solid #f0f0f0; } .todo-item:last-child { border-bottom: none; } .todo-item span { flex: 1; font-size: 15px; color: #444; } .todo-item input[type="checkbox"] { width: 18px; height: 18px; cursor: pointer; } .delete-btn { padding: 4px 10px; background-color: #ff6b6b; color: #fff; border: none; border-radius: 6px; font-size: 12px; cursor: pointer; } .delete-btn:hover { background-color: #e05555; } .todo-item.completed span { text-decoration: line-through; color: #aaa; }

这段 CSS 并不是随便写的,每个块都在解决一个具体问题:

  • body上的display: flex+align-items: center+justify-content: center,实现整屏水平垂直居中。这个技巧是“页面居中”话题的标配答案;
  • .input-area上的display: flex,让输入框和按钮排在同一行,输入框用flex: 1自动填满剩余宽度;
  • .todo-itemdisplay: flex排列复选框、文本和删除按钮;
  • .todo-item.completed spantext-decoration: line-through实现删除线效果,这是后面 JS 联动的基础。

此时你在浏览器里打开index.html,页面已经不再是白底黑字,而是一个带渐变色背景、居中卡片、态度鲜明的现代化小应用了。

4. JavaScript:让页面拥有“生命”

4.1 为什么需要 JS

HTML 负责内容,CSS 负责样式,但它们都改变不了页面的行为。你不能在纯 HTML 里实现“点击按钮新增一行”,也不能在纯 CSS 里实现“输入内容后按下回车自动提交”。而 JS 的存在,就是为网页提供动态行为。

所谓“动态”,其实就两件事:响应用户操作、更新页面内容。

不过,JS 和传统编程语言不太一样的地方在于,它从诞生起就绑定在浏览器环境里。在浏览器里,JS 通过document对象来操作 DOM(Document Object Model,文档对象模型)。

理解 DOM 是理解前端交互的关键。浏览器在加载 HTML 后,会把标签解析成一棵倒挂的树,我们称它为“DOM 树”。每一个标签都变成了这棵树上的一只“节点对象”。JS 能通过操作这些节点,来改变网页上用户看到的任何一个元素——改文字、加样式、增节点、删节点。

简单说:HTML 是静态的买房合同,DOM 是那套能随时重新装修的房子,JS 就是你的装修队。没有 JS,房子再好也就那样;有了 JS,你才能按需改造。

4.2 变量、数据类型与常用语法

JavaScript 的语法面非常广,但一个“能写交互”的入门者,真正需要掌握的语法其实很少。

变量声明:可以使用letconstconst用于不会被重新赋值的变量,let用于会被重新赋值的变量。var是老写法,现在推荐尽量避免。

const appTitle = '我的待办清单'; let count = 0;

数据类型:入门阶段你最需要关注的是字符串(string)、数字(number)、布尔值(boolean)、对象(object)、数组(array)。

函数:把一段逻辑封装起来。

function addTodo() { // 具体逻辑 }

事件监听:JS 最核心的交互方式。

const btn = document.getElementById('addBtn'); btn.addEventListener('click', addTodo);

模板字符串:字符串拼接的现代化写法。

const text = `当前有 ${count} 条待办`;

4.3 获取 DOM 元素与操作属性

JS 操作 DOM,第一步永远是“找到要操作的元素”。最常用的三种 API 是:

API返回值使用场景
document.getElementById('id')单个元素操作唯一元素
document.querySelector('选择器')第一个匹配元素任意选择器
document.querySelectorAll('选择器')NodeList(类似数组)操作一组元素

找到元素后,你能做什么?最常用的有三个维度:

  • 改文本element.textContent = '新内容'
  • 改样式element.style.color = 'red'
  • 改类名element.classList.add('completed')

4.4 常用的 DOM 操作:创建、追加、删除

动态列表的基础操作,就是这三板斧:

// 创建元素 const li = document.createElement('li'); // 给元素添加类名和内容 li.classList.add('todo-item'); li.innerHTML = `<input type="checkbox" class="todo-checkbox"><span>${text}</span><button class="delete-btn">删除</button>`; // 追加到父元素中 document.getElementById('todoList').appendChild(li);

这里有一个经验之谈:尽量使用textContent去设置用户输入的内容,不要直接拼 HTML。因为如果用户输入的是<img src=x onerror=alert(1)>这类字符串,直接拼到 HTML 里就触发 XSS 攻击。虽然我们这是个学习项目,但从第一天开始养成安全的习惯很重要。

4.5 完整的 JS 逻辑实现

现在在todo-app文件夹下新建script.js,写入下面的完整逻辑:

// 文件路径:todo-app/script.js const todoInput = document.getElementById('todoInput'); const addBtn = document.getElementById('addBtn'); const todoList = document.getElementById('todoList'); // 新增待办事项 function addTodo() { const text = todoInput.value.trim(); if (text === '') { alert('请输入待办内容'); return; } const li = document.createElement('li'); li.classList.add('todo-item'); const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.classList.add('todo-checkbox'); const span = document.createElement('span'); span.textContent = text; const deleteBtn = document.createElement('button'); deleteBtn.textContent = '删除'; deleteBtn.classList.add('delete-btn'); li.appendChild(checkbox); li.appendChild(span); li.appendChild(deleteBtn); // 复选:切换完成状态 checkbox.addEventListener('change', function () { li.classList.toggle('completed'); }); // 删除:从列表中移除 deleteBtn.addEventListener('click', function () { todoList.removeChild(li); }); todoList.appendChild(li); todoInput.value = ''; todoInput.focus(); } // 回车提交:绑定 input 上的 keydown 事件 todoInput.addEventListener('keydown', function (event) { if (event.key === 'Enter') { addTodo(); } }); addBtn.addEventListener('click', addTodo);

这段代码里有几个细节需要你品一下:

第一,trim()的作用。用户输入可能带前后空格,如果不处理,会出现“看起来没内容但确实添加了”的 bug。trim()会去掉字符串首尾的空白符。如果去掉后是空字符串,直接提示并返回,不创建任何节点。

第二,为什么用createElement而不是innerHTML前面提到过安全问题。更重要的,createElement生成的是 DOM 对象,我们需要给它的子元素单独绑定事件。如果用整段字符串插入,后续绑定删除事件会比较绕。

第三,事件的绑定位置。注意,删除按钮和复选框的事件是在li被创建之后就立即绑定的。这也是很多教程里容易忽略的细节:如果你在 HTML 里写死了一个删除按钮,你只需要在全局绑定一次;但这里是动态创建的节点,所以每个新节点都需要自己的事件监听器。

第四,toggle方法。如果类名completed存在则移除,不存在则添加。这样复选框反复勾选时,删除线效果能正常切换,而不会被叠加出来。

5. 完整示例与代码实现:把三件套串起来

现在,三个文件已经全部就绪。整个项目的目录结构如下:

todo-app/ ├── index.html ├── style.css └── script.js

各文件作用的对应关系可以用一张图表达:

  • index.html定义页面结构和初始内容;
  • style.css负责视觉表现,包括居中、卡片、按钮样式、删除线等;
  • script.js负责交互逻辑,包括输入、添加、勾选完成、删除。

这三个文件互相配合,构成了一个最简单也最完整的前端项目。这个“HTML 结构 + CSS 样式 + JS 交互”的协作模式,会一直沿用到你接触任何复杂前端项目。

5.1 如何运行与验证

在浏览器中运行有两种方式:

方式一:直接双击打开 index.html。这是最快的验证方式。双击后浏览器直接渲染页面,不需要任何服务器。适合学习阶段使用。

方式二:使用 VS Code 的 Live Server 插件。如果你用 VS Code,建议安装 Live Server 插件。安装后在index.html上右键选择 “Open with Live Server”,浏览器会自动打开http://127.0.0.1:5500并实时刷新。这个方式更接近真实开发体验,也方便调试。

建议直接用方式二,因为它能让你体会到“改代码、保存、浏览器立即更新”的开发节奏。

5.2 预期效果

完成之后,你应该能看到:

  • 一个居中显示的白色卡片,卡片上方是标题“我的待办清单”;
  • 输入框 + 按钮在同一行,输入框有圆角边框,按钮是蓝紫色;
  • 列表里默认有两条待办;
  • 在输入框里输入文字,点击“添加”或按下回车,新条目会以列表形式插入到最后;
  • 勾选复选框后,对应文字出现删除线并变为灰色;
  • 点击“删除”按钮,对应条目被移除。

如果你看到以上所有效果,说明你的 HTML、CSS、JS 已经形成了一个完整的闭环。

5.3 如果失败,怎么排查

最可能出问题的地方是文件路径。请仔细检查:

  • index.html<link rel="stylesheet" href="style.css">的路径是否与style.css在同一个目录下;
  • <script src="script.js">的路径是否正确;
  • 文件名的大小写是否一致,比如style.css不要写成Style.css

如果点击“添加”没反应,优先打开浏览器开发者工具(F12),切到 Console 标签页,查看是否有红色报错。最常见的报错是Cannot read properties of null,这种提示十有八九是getElementById的 id 名写错了,或者脚本执行时该元素还不存在于 DOM 中。

6. 常见问题与排查思路

问题现象可能原因排查方式解决方案
页面打开后中文显示乱码HTML 文件缺少<meta charset="UTF-8">查看<head>中是否声明字符编码<head>中添加<meta charset="UTF-8">
CSS 样式完全没有生效link标签的路径错误或文件名不匹配检查link标签的href与目录结构修正路径并统一文件名大小写
输入框为空时点击添加也能添加没有做空值校验审查addTodo函数的trim()判断使用text.trim()判断,为空时alertreturn
点击删除无效动态生成的元素没有绑定删除事件查看控制台报错和事件绑定代码每个动态节点的删除按钮都要单独绑定事件,或用事件委托
页面在手机上显示过宽缺少 viewport 配置检查<head>中 meta 标签添加<meta name="viewport" content="width=device-width, initial-scale=1.0">
勾选复选框后删除线不出现completed类名与 CSS 不匹配检查 JS 中classList.toggle和 CSS 中.completed span选择器统一类名拼写,确保 CSS 写在style.css
找不到元素报错JS 执行时机早于 DOM 渲染打开 F12 查看 Console 报错位置<script>放在body底部,或使用DOMContentLoaded事件

7. 最佳实践与工程建议

项目虽然小,但一些“工程习惯”可以尽早建立起来。很多人觉得这些习惯是“以后进公司再说”的事,但实际上它们决定了一个人的代码能走多远。

7.1 命名规范

  • HTML id 和 class 使用小驼峰或短横线命名。推荐短横线风格,如:todo-inputtodo-list。关键词之间用-分隔,可读性好。
  • JS 变量和函数使用小驼峰命名。如:todoInputaddTodo。常量大写,如:MAX_COUNT
  • CSS 类名做到“见名知义”.todo-item一眼就知道是待办事项条目,.red-bg这种描述样式而不是描述语义的类名尽量少用。

7.2 把逻辑拆成独立函数

建议把“添加事件”和“添加逻辑”拆开,而不是把所有代码都塞进一个click回调里。例如把addTodo定义成独立函数,而addBtn.addEventListener('click', addTodo)只负责事件绑定。这样后续如果要加表单校验、数据持久化,不会把同一个函数改得越来越长。

7.3 防止脚本加载顺序的坑

最简单也最稳妥的做法是把<script>标签放在<body>的末尾。因为浏览器解析 HTML 是按顺序从上往下执行的,脚本放在底部时可以确保它执行时,所有 DOM 元素都已经解析完成。如果你非要放在<head>里,也不是不行,但必须把操作 DOM 的代码包在DOMContentLoaded事件里:

document.addEventListener('DOMContentLoaded', function () { // 在这里执行 DOM 操作 });

7.4 建议尽早尝试的扩展

只用script.js里的逻辑还不够,学到一个阶段后可以尝试:

  • 把待办事项存入localStorage,刷新页面后数据不丢失。这会顺便让你理解 JSON 的stringifyparse
  • 支持“双击编辑”,把静态文本变成可编辑的输入框;
  • 增加筛选功能,全部分类、已完成、未完成三个 Tab;
  • 增加统计功能,在页面底部显示“剩余 X 项未完成”。

这些扩展并不难,但每一个都会逼着你回头复习三件套,尤其是 DOM 和事件。

7.5 关于学习路径的提醒

到这里,3 小时的内容基本就学完了。但想提醒一句:本文的学习重点是“建立整体认知”,不是“背语法大全”。学完后你应该具备的能力是:

  • 看到一个设计稿,能大致画出它由哪些 HTML 块组成;
  • 看懂网上 Demo 里的 CSS 在做什么,并能微调样式;
  • 能独立给页面添加一个简单的交互功能;
  • 遇到问题知道先看控制台、再查 MDN 文档。

这些能力一旦建立,后续无论学 Vue 还是 React,都会顺畅很多。因为它们本质上是在帮你更高效地操作 DOM、管理数据和维护状态,而底层依然是 HTML、CSS 和 JavaScript 这三件套。

8. 总结与下一步

这篇文章用了约 3 小时的阅读和动手时间,带你完成了从零到一的第一个完整前端小项目。此时你手里应该已经有了三个文件:index.htmlstyle.cssscript.js,以及一个能输入、能添加、能勾选、能删除的待办页面。

接下来你需要做一件事:不要急着进入新知识,先把这个项目反复“折腾”几遍。改改颜色,调整一下布局,给列表增加一个“全部清空”按钮,把输入框的 placeholder 换成自己的语言。折腾的过程中,你一定会踩到新的坑,而踩坑、查错、修复,才是真正的学习过程。

如果再往后走,推荐按这个顺序继续:

  1. 把待办数据存入localStorage,理解前端持久化;
  2. 学习更系统的 CSS 知识,重点掌握 Grid 布局、伪元素、过渡动画;
  3. 学习 ES6+ 常用语法(解构、模板字符串、箭头函数、模块化);
  4. 接触 Vue 或 React,用框架重构这个 Todo 项目。

前端入门并没有想象中那么困难,真正困难的是持续练习、在报错中积累经验,并始终保持“把页面做出来”的动力。希望这个 3 小时的小项目,能成为你前端路上第一个真正跑起来的起点。如果文章里有哪个环节还没看懂,建议回到对应章节,把代码再敲一遍——前端最怕“眼睛会了、手不会”,一定要让手先动起来。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 2:59:12

2026年最值得装的9款Claude Code插件:只留生产力,告别鸡肋

你说 Claude Code 装插件这事&#xff0c;难吗&#xff1f;真不难&#xff0c;GitHub 上翻一圈&#xff0c;星星多的项目能列出几十个。难的是装完之后你发现&#xff0c;真正每天会用的其实就两三个&#xff0c;剩下的全躺在配置里&#xff0c;偶尔还冒出来一个报错打断你。我…

作者头像 李华
网站建设 2026/9/9 2:57:10

NeuMus:打通脑机接口从论文算法到产品原型的最后一公里

做脑机接口这些年&#xff0c;我最深的感受是&#xff1a;圈子里从来不缺漂亮的论文&#xff0c;缺的是能把论文里的算法变成能戴在头上、能亮灯、能动起来的东西的人。NeuMus这个平台&#xff0c;我一开始以为它只是又一个信号处理工具箱&#xff0c;后来发现它更像是一条从“…

作者头像 李华
网站建设 2026/9/9 2:54:02

数据技术驱动精准营销:从用户画像到AB实验的完整链路

前一段时间有个做电商运营的朋友跟我聊&#xff0c;说这两年广告投放好像突然变得"看不懂"了&#xff1a;以前投个详情页就能卖货&#xff0c;现在必须分人群、分时段、分渠道做不同素材&#xff1b;以前一个爆款能吃半年&#xff0c;现在上线两周数据就得重新观察。…

作者头像 李华
网站建设 2026/9/9 2:53:27

Mac本地大模型内存优化:分层缓存与SSD实战

1. 先说结论&#xff1a;Mac跑本地大模型&#xff0c;瓶颈从来不是算力过去两年我一直在跟本地AI推理打交道&#xff0c;从最早在MacBook Pro上折腾Llama 2&#xff0c;到后来换M系列芯片跑各种量化模型&#xff0c;最直观的感受是&#xff1a;M系列芯片的NPU和GPU其实没那么弱…

作者头像 李华
网站建设 2026/9/9 2:53:19

傅里叶变换轮廓术仿真实验:从光栅条纹到三维重建全流程解析

简介&#xff1a;面向三维形貌测量与数字全息入门者的傅里叶变换轮廓术&#xff08;FTP&#xff09;Matlab仿真资源包&#xff0c;完整演示了条纹投影、图像捕获、傅里叶变换、相位恢复与三维重建的典型处理链路。压缩包仅274KB&#xff0c;包含2个.m主程序&#xff08;条纹图生…

作者头像 李华
网站建设 2026/9/9 2:53:01

睡眠监测仪技术路线之争:UWB为何比毫米波雷达更适合测呼吸

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华