建站代码怎么写:从 HTML、CSS 到 JavaScript 搭建一个简单网页

资讯2天前发布 jdkjadmin
0 00
建站代码怎么写:从 HTML、CSS 到 JavaScript 搭建一个简单网页

建站代码怎么写:从 HTML、CSS 到 JavaScript 搭建一个简单网页

想自己做一个网页,通常不必先安装复杂的开发环境,也不必一开始就学习大型框架。一个普通网页可以先由三种基础技术组成:HTML 描述内容和结构,CSS 负责外观与布局,JavaScript 处理交互。把它们放进几个文件,用浏览器打开,就能得到一个可运行的小项目。

本文会从零搭建一个简单的任务清单:用户可以输入任务、添加任务、删除任务,刷新页面后仍能看到已保存的内容。示例不依赖第三方库,适合学习静态网页的基本组成、熟悉浏览器调试,以及制作个人介绍页、产品说明页或轻量交互原型。它不是账号系统、多人协作工具,也不适合保存敏感信息;这些边界会在后文说明。

一、先理解三个部分各自做什么

  • HTML:组织标题、段落、表单、按钮和列表等内容。它决定页面有哪些元素,以及这些元素之间的语义关系。
  • CSS:控制颜色、字体、间距、宽度和响应式布局。CSS 可以改变视觉呈现,但不会自动实现数据保存或表单业务逻辑。
  • JavaScript:响应点击和输入,修改页面内容,并调用浏览器提供的功能。本文用它新增、删除任务,并把数据保存在浏览器本地。

三者之间有明确的边界:HTML 提供基础结构,CSS 美化结构,JavaScript 在结构上增加行为。浏览器会把这几部分一起解析和运行,但把代码拆成文件,通常更方便阅读、修改和排错。

二、准备目录和运行方式

先创建一个文件夹,例如 my-first-site,并在其中新建三个文件:

my-first-site/
├── index.html
├── styles.css
└── app.js

可以使用任意文本编辑器编写这些文件。保存后,直接用浏览器打开 index.html,就能运行这个示例。开发时也可以使用编辑器提供的本地预览功能,或启动本地静态服务器。对于本文用到的普通 HTML、CSS 和本地存储,直接打开文件通常也能工作;但涉及模块导入、请求接口、浏览器权限等功能时,使用本地服务器往往更接近真实网站运行环境。

注意:这里的“本地运行”指页面在你自己的设备上打开,不等于网站已经发布到互联网上。想让其他人访问,需要把文件部署到静态托管服务或自己的服务器,并配置域名等相关内容。

三、编写 HTML:先搭好结构

把下面内容保存为 index.html。它提供一个页面标题、一段说明、一个输入表单和一个任务列表。label 与输入框通过 for 和 id 关联,便于屏幕阅读器识别,也能让用户点击标签时聚焦输入框。defer 会让浏览器先解析 HTML,再执行外部 JavaScript 文件。

<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>我的任务清单</title>
  <link rel="stylesheet" href="styles.css">
  <script src="app.js" defer></script>
</head>
<body>
  <main class="page">
    <header class="intro">
      <p class="eyebrow">一个简单的网页示例</p>
      <h1>我的任务清单</h1>
      <p>写下接下来要做的事,完成后可以删除。</p>
    </header>

    <section class="panel" aria-labelledby="form-title">
      <h2 id="form-title">添加任务</h2>
      <form id="task-form">
        <label for="task-input">任务内容</label>
        <div class="form-row">
          <input
            id="task-input"
            name="task"
            type="text"
            maxlength="80"
            placeholder="例如:整理本周的学习计划"
            autocomplete="off"
            required
          >
          <button type="submit">添加</button>
        </div>
        <p class="hint">最多输入 80 个字符。</p>
      </form>
    </section>

    <section class="panel" aria-labelledby="list-title">
      <div class="list-heading">
        <h2 id="list-title">待办事项</h2>
        <span id="task-count" class="count">0 项</span>
      </div>
      <p id="empty-message" class="empty-message">还没有任务,添加一项试试。</p>
      <ul id="task-list" class="task-list"></ul>
    </section>

    <footer class="footer">
      <p>示例数据保存在当前浏览器中。</p>
    </footer>
  </main>
</body>
</html>

HTML 属性不是业务逻辑的替代品。这里的 required 和 maxlength 会启用浏览器原生表单校验,方便用户发现明显错误;但真实应用仍应在 JavaScript 中检查输入。若数据会发送到服务器,服务器也必须重新验证,因为客户端校验可以被绕过。

四、编写 CSS:让页面清楚易读

把下面代码保存为 styles.css。这里使用居中的内容区、卡片式面板和简单的窄屏布局。CSS 中的类名与 HTML 中的 class 对应;如果改了类名,记得同步修改相关样式。

* {
  box-sizing: border-box;
}

:root {
  color-scheme: light;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
    sans-serif;
  color: #20252c;
  background: #f3f5f8;
}

body {
  margin: 0;
  min-width: 320px;
}

button,
input {
  font: inherit;
}

.page {
  width: min(100% - 32px, 720px);
  margin: 0 auto;
  padding: 56px 0 32px;
}

.intro {
  margin-bottom: 28px;
}

.eyebrow {
  margin: 0 0 8px;
  color: #52647d;
  font-size: 0.9rem;
}

h1 {
  margin: 0 0 12px;
  font-size: clamp(2rem, 7vw, 3rem);
  line-height: 1.15;
}

.intro > p:last-child {
  margin: 0;
  color: #56606c;
  line-height: 1.7;
}

.panel {
  margin: 16px 0;
  padding: 24px;
  border: 1px solid #e0e5ec;
  border-radius: 14px;
  background: #fff;
  box-shadow: 0 5px 18px rgb(30 45 65 / 5%);
}

h2 {
  margin: 0 0 18px;
  font-size: 1.2rem;
}

label {
  display: block;
  margin-bottom: 8px;
  font-weight: 600;
}

.form-row {
  display: flex;
  gap: 10px;
}

input {
  min-width: 0;
  flex: 1;
  padding: 11px 12px;
  border: 1px solid #aeb8c5;
  border-radius: 8px;
}

input:focus-visible,
button:focus-visible {
  outline: 3px solid #8bb8ff;
  outline-offset: 2px;
}

button {
  padding: 10px 16px;
  border: 0;
  border-radius: 8px;
  color: #fff;
  background: #2459b3;
  cursor: pointer;
}

button:hover {
  background: #19458f;
}

.hint {
  margin: 8px 0 0;
  color: #657181;
  font-size: 0.9rem;
}

.list-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.list-heading h2 {
  margin-bottom: 8px;
}

.count {
  color: #657181;
  font-size: 0.9rem;
}

.empty-message {
  margin: 12px 0 0;
  color: #657181;
}

.task-list {
  display: grid;
  gap: 10px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.task-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px;
  border: 1px solid #e4e8ee;
  border-radius: 8px;
  overflow-wrap: anywhere;
}

.task-text {
  white-space: pre-wrap;
}

.delete-button {
  flex: 0 0 auto;
  padding: 7px 10px;
  color: #8b2635;
  background: #fff0f1;
}

.delete-button:hover {
  background: #ffe1e4;
}

.footer {
  padding-top: 8px;
  color: #657181;
  font-size: 0.9rem;
}

@media (max-width: 480px) {
  .page {
    padding-top: 32px;
  }

  .panel {
    padding: 18px;
  }

  .form-row {
    align-items: stretch;
    flex-direction: column;
  }
}

box-sizing: border-box 让宽度计算更直观;min() 和 clamp() 是现代 CSS 函数,用来限制内容宽度和标题字号。若需要兼容较旧的浏览器,可以先用普通属性写出基础样式,再按项目目标检查是否需要降级方案。不要假设所有浏览器、设备和用户偏好都完全相同,发布前应在目标环境中实际测试。

五、编写 JavaScript:处理添加、删除和保存

把下面代码保存为 app.js。程序先读取页面上的元素,再尝试从 localStorage 恢复数据。每次添加或删除后会重新绘制列表并保存。示例通过创建文本节点来显示用户输入,不把输入拼接成 HTML。

"use strict";

const STORAGE_KEY = "simple-task-list-v1";
const MAX_TASK_LENGTH = 80;

const form = document.querySelector("#task-form");
const input = document.querySelector("#task-input");
const list = document.querySelector("#task-list");
const count = document.querySelector("#task-count");
const emptyMessage = document.querySelector("#empty-message");

let tasks = loadTasks();

function loadTasks() {
  try {
    const saved = localStorage.getItem(STORAGE_KEY);

    if (saved === null) {
      return [];
    }

    const parsed = JSON.parse(saved);

    if (!Array.isArray(parsed)) {
      return [];
    }

    return parsed
      .filter((item) => typeof item === "string")
      .map((item) => item.trim())
      .filter((item) => item.length > 0 && item.length <= MAX_TASK_LENGTH);
  } catch (error) {
    // 存储不可用或内容无法解析时,先以空列表继续运行。
    return [];
  }
}

function saveTasks() {
  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(tasks));
  } catch (error) {
    // 浏览器可能禁用或限制存储;页面仍可在当前内存中使用。
    console.warn("任务未能保存到本地存储。");
  }
}

function renderTasks() {
  list.replaceChildren();

  tasks.forEach((task, index) => {
    const item = document.createElement("li");
    item.className = "task-item";

    const text = document.createElement("span");
    text.className = "task-text";
    text.textContent = task;

    const deleteButton = document.createElement("button");
    deleteButton.className = "delete-button";
    deleteButton.type = "button";
    deleteButton.textContent = "删除";
    deleteButton.setAttribute("aria-label", `删除任务:${task}`);

    deleteButton.addEventListener("click", () => {
      tasks.splice(index, 1);
      saveTasks();
      renderTasks();
    });

    item.append(text, deleteButton);
    list.append(item);
  });

  count.textContent = `${tasks.length} 项`;
  emptyMessage.hidden = tasks.length > 0;
}

form.addEventListener("submit", (event) => {
  event.preventDefault();

  const task = input.value.trim();

  if (task.length === 0) {
    input.focus();
    return;
  }

  if (task.length > MAX_TASK_LENGTH) {
    input.setCustomValidity(`任务内容不能超过 ${MAX_TASK_LENGTH} 个字符。`);
    input.reportValidity();
    input.setCustomValidity("");
    return;
  }

  tasks.push(task);
  saveTasks();
  renderTasks();

  form.reset();
  input.focus();
});

renderTasks();

代码中的箭头、比较符号和逻辑运算符在网页源码中需要正确转义,因此在上面的代码展示中,诸如 =>、&& 和 <= 是 HTML 实体;从代码块复制时,若编辑器复制的是页面显示文本,它们会对应 JavaScript 中的 =>、&& 和 <= 符号。实际 app.js 文件应使用 JavaScript 原字符。完整写法如下:代码文件中把比较和箭头运算符写作 >、<、=>,逻辑运算符写作 &&;它们在 HTML 代码片段中显示为实体,是为了避免被网页解析成标签。

如果将示例直接复制到纯文本的 app.js,可将上面的 HTML 实体还原为对应字符。更稳妥的做法是根据这条规则核对:HTML 代码块里的 &gt;、&lt;、=&gt;、&amp;&amp; 分别对应 JavaScript 的 >、<、=>、&&。这样才能保证 JavaScript 文件本身不含 HTML 转义实体。

六、输入限制、存储能力与安全边界

maxlength="80" 会限制输入框可输入的长度,JavaScript 中的 MAX_TASK_LENGTH 则在提交时再次检查。两者是对用户输入的便利限制,不是可靠的安全机制:浏览器端代码可以被修改,页面脚本也可以绕过。若应用把输入发给服务器,应由服务器按业务规则重新校验,并根据数据库和接口设计设置合理的长度、格式和速率限制。

JavaScript 字符串的 length 计算的是 UTF-16 代码单元数量,并不总等于用户感知的“字符数”。部分表情符号或组合字符可能占多个代码单元,因此这里的 80 更准确地说是代码单元上限。对普通短任务通常够用;如果产品要求精确限制可见字符数,需要采用符合该需求的 Unicode 字符分段方案,并明确前后端采用一致规则。

localStorage 属于当前浏览器环境中的客户端存储。它适合保存非敏感的偏好或小型示例数据,但不等于数据库:数据可能被用户清除,也不会自动同步到另一台设备;不同浏览器、配置文件或站点来源之间通常也不能直接共享。可用空间和行为受浏览器实现、用户设置及运行环境影响,不应把某个固定容量当作所有设备都保证支持的上限。写入失败时,示例会在控制台提示,当前页面仍可通过内存中的数组操作,但刷新后未保存的数据可能消失。

不要把密码、访问令牌、支付信息或其他敏感数据放进 localStorage。同一来源下运行的 JavaScript 通常可以读取其中的数据;如果页面出现跨站脚本漏洞,攻击代码也可能访问这些内容。浏览器本地存储不是加密保险箱,也不是身份验证或授权机制。需要账号、云端同步、权限控制、审计或可靠备份时,应设计服务端接口、认证授权与数据存储方案,而不是单靠静态页面和本地存储。

示例使用 textContent 写入用户输入,这是一个重要的安全习惯。不要把用户输入直接拼进 innerHTML,例如把输入当作 HTML 字符串插入页面;恶意内容可能被浏览器解释并执行。若确实需要展示富文本,应采用经过审查的消毒方案,并明确允许的标签和属性。仅仅做字符串替换通常不足以构成可靠的 HTML 消毒。

七、常见问题与排查顺序

  • 页面没有样式:检查 styles.css 是否与 index.html 位于同一目录,文件名和大小写是否完全一致。浏览器开发者工具的网络面板可以查看 CSS 是否加载成功。
  • 按钮点击没有反应:检查 app.js 路径、浏览器控制台错误,以及 HTML 中的 id 是否与 JavaScript 查询的选择器一致。一个拼错的 task-form 就会让事件绑定失效。
  • 脚本报语法错误:确认 JavaScript 文件中使用的是原始运算符,而不是展示用的 HTML 实体;例如代码文件里应写 && 字符本身,而不是文本 &amp;&amp;。
  • 刷新后数据不见:确认浏览器允许该页面使用本地存储。也要注意,不同浏览器配置、浏览器隐私设置和页面来源可能对应不同的存储空间。清除浏览数据会移除本地保存的任务。
  • 窄屏上内容溢出:检查输入框、按钮和长文本的宽度,避免给弹性布局中的子元素设置不合理的固定宽度。示例的 min-width: 0 与 overflow-wrap: anywhere 用来缓解常见溢出情况,但仍应在目标设备上测试。
  • 改了 HTML 后样式或功能消失:检查元素的类名、ID、标签嵌套是否仍与 CSS 和 JavaScript 相匹配。开发者工具的元素面板可以查看浏览器最终生成的 DOM。

遇到问题时,建议依次检查文件路径、浏览器控制台、元素 ID 和选择器,而不是一次改动很多地方。开发者工具通常能直接指出脚本文件加载失败、语法错误或未找到对应元素的位置。

八、可以怎样继续扩展

在这个基础上,可以尝试增加完成状态、任务筛选、清空列表或日期字段。每增加一个功能,都先明确数据结构,再决定 HTML 需要哪些控件、CSS 需要哪些状态、JavaScript 如何更新数据。若任务不再只是字符串,而是还要保存完成状态和创建时间,数据可以改为对象数组,例如每项包含 text、done 和 createdAt;同时要考虑旧版本地数据如何兼容或清理。

也可以进一步学习语义化 HTML、CSS Grid 与 Flexbox、事件处理、表单可访问性、HTTP 请求和服务端开发。框架并不是基础网页的必要条件;当页面复杂到需要组件复用、路由、团队协作或自动化构建时,再选择合适的工具更容易判断其价值。

总结

一个简单网页可以从三个文件开始:HTML 负责结构,CSS 负责呈现,JavaScript 负责交互。本文的任务清单示例能在浏览器中直接运行,也展示了表单校验、本地存储和安全输出的基本做法。需要牢记的是,客户端限制可被绕过,本地存储不适合敏感数据,用户输入也不应未经处理地作为 HTML 插入。理解这些边界,比单纯把页面“跑起来”更重要。

© 版权声明

相关文章