新手入门:从前端三件套到动态数据渲染

前言

作为前端学习者,掌握 HTML、CSS、JavaScript 是必经之路。本文将通过一个实际的"用户表格展示项目",带你从零开始理解前端开发的核心理念和知识点。

📚 本文项目源码:user-chat 项目仓库

项目效果

我们最终要实现的是一个动态加载用户数据的表格页面,数据来源于后端 API,最终渲染效果如下:

复制代码
┌─────────────────────────────────────────┐
│  ID  │  姓名  │  家乡  │  昵称         │
├─────────────────────────────────────────┤
│  1   │ 贤康 │ 南      │ 罗            │
│  2   │ 道轩 │ 南      │ 鸡蛋仙        │
│  3   │ 文瑾 │ 中国    │ 娃娃机        │
│  4   │ 佳明 │   安    │ 炸酱面        │
└─────────────────────────────────────────┘

一、项目结构

bash 复制代码
user-chat/
├── backend/              # 后端目录
│   ├── db.json          # JSON 数据库
│   └── package.json     # npm 配置
├── fe/                  # 前端目录
│   ├── index.html       # 主页面
│   ├── common.js        # JavaScript 逻辑
│   └── common.css       # 样式文件
└── readme.md           # 学习笔记

为什么要前后端分离?

  • 前端(fe):专注用户界面和交互
  • 后端(backend):专注数据处理和存储
  • 模块化:每个模块职责清晰,便于维护和扩展

二、HTML 基础

1. 语义化标签

HTML5 引入了语义化标签,让代码更具可读性:

html 复制代码
<!-- 语义化写法 -->
<header>顶部导航</header>
<main>主内容区域</main>
<aside>侧边栏</aside>
<footer>底部信息</footer>

<!-- 不推荐:全部用 div -->
<div>顶部导航</div>
<div>主内容区域</div>
<div>侧边栏</div>

语义化的好处

  • 代码可读性更高
  • 有利于 SEO 搜索引擎优化
  • 屏幕阅读器能更好地识别页面结构

2. 表格结构

表格是展示结构化数据的重要方式:

html 复制代码
<table class="table">
    <!-- 表头区域 -->
    <thead>
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>家乡</th>
            <th>昵称</th>
        </tr>
    </thead>
    
    <!-- 表体区域 -->
    <tbody>
        <tr>
            <td>1</td>
            <td>贤康</td>
            <td>南</td>
            <td>罗</td>
        </tr>
    </tbody>
</table>

标签说明

标签 全称 作用
<table> Table 表格容器
<thead> Table Head 表头区域
<tbody> Table Body 表体区域
<tr> Table Row
<th> Table Header 表头单元格(自动加粗居中)
<td> Table Data 数据单元格

💡 重要提示<thead><tbody> 不是可选的!它们对于 CSS 样式控制和无障碍访问至关重要。

三、CSS 基础

1. 盒子模型

每个 HTML 元素都可以看作一个"盒子":

css 复制代码
┌──────────────────────────────────┐
│           margin(外边距)         │
│  ┌────────────────────────────┐ │
│  │     border(边框)           │ │
│  │  ┌────────────────────────┐ │ │
│  │  │    padding(内边距)    │ │ │
│  │  │  ┌──────────────────┐  │ │ │
│  │  │  │    content       │  │ │ │
│  │  │  │   (内容区域)    │  │ │ │
│  │  │  └──────────────────┘  │ │ │
│  │  └────────────────────────┘ │ │
│  └────────────────────────────┘ │
└──────────────────────────────────┘

2. Bootstrap 栅格系统

Bootstrap 将页面分为 12 列,使用时只需添加相应的类名:

html 复制代码
<!-- Bootstrap CDN 引入 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css">

<!-- 占满整行 -->
<div class="col-md-12">100% 宽度</div>

<!-- 占一半宽度,可并排两个 -->
<div class="col-md-6">50%</div>
<div class="col-md-6">50%</div>

<!-- 占 1/3 宽度,可并排三个 -->
<div class="col-md-4">33.3%</div>
<div class="col-md-4">33.3%</div>
<div class="col-md-4">33.3%</div>

<!-- 居中显示:占 6 列,偏移 3 列 -->
<div class="col-md-6 col-md-offset-3">
    居中的内容
</div>

栅格布局图解

markdown 复制代码
12 列布局:
|___|___|___|___|___|___|___|___|___|___|___|___|
 1  2  3  4  5  6  7  8  9  10 11 12

col-md-6 col-md-offset-3:
|   |   |   |___|___|___|___|___|___|   |   |   |
 1  2  3  4  5  6  7  8  9  10 11 12
       ↑ 偏移 3 列 →  从这里开始占据 6 列

3. 布局容器

html 复制代码
<!-- container:左右留白,居中显示 -->
<div class="container">
    <div class="row">
        <!-- 内容 -->
    </div>
</div>

<!-- container-fluid:100% 宽度 -->
<div class="container-fluid">
    <!-- 全宽内容 -->
</div>

四、JavaScript 基础

1. DOM 编程

DOM(Document Object Model)是将 HTML 文档转换为对象的技术:

css 复制代码
HTML 文档:
<html>
  <body>
    <div class="container">
      <table>
        <tbody>...</tbody>
      </table>
    </div>
  </body>
</html>

DOM 树结构:
document
   └── html
       └── body
           └── div.container
               └── table
                   └── tbody

JavaScript 获取元素

javascript 复制代码
// 通过 ID 获取
const table = document.getElementById('user-table');

// 通过选择器获取(推荐)
const tbody = document.querySelector('.table tbody');
//              ↑ class 选择器  ↑ 标签选择器
//                    ↓ 空格表示"后代选择器",查找 .table 内部的 tbody

2. 动态修改页面内容

javascript 复制代码
// 获取元素
const oBody = document.querySelector('.table tbody');

// 修改内容
oBody.innerHTML = '<tr><td>新内容</td></tr>';

// 追加内容
oBody.innerHTML += '<tr><td>追加的内容</td></tr>';

⚠️ 注意 :在实际企业开发中,如果数据来自不可信的用户输入,直接使用 innerHTML 可能会导致安全问题(XSS 攻击)。本文为了演示方便采用此方法,后续可以了解 document.createElement 等更安全的做法:

javascript 复制代码
// 更安全的做法
const tr = document.createElement('tr');
const td = document.createElement('td');
td.textContent = '安全的内容';
tr.appendChild(td);
oBody.appendChild(tr);

3. 模板字符串

ES6 引入的模板字符串让字符串拼接更优雅:

javascript 复制代码
const user = { id: 1, name: '罗贤康', hometown: '南昌' };

// 传统方式(繁琐)
'<tr><td>' + user.id + '</td><td>' + user.name + '</td></tr>'

// 模板字符串(简洁)
`<tr>
    <td>${user.id}</td>
    <td>${user.name}</td>
    <td>${user.hometown}</td>
</tr>`

💡 模板字符串使用反引号 ````` 包裹,${} 用于插入变量。

4. fetch API 与网络请求

什么是 fetch?

fetch 是现代浏览器提供的 API,用于发送网络请求获取数据:

javascript 复制代码
// 基本语法
fetch('请求地址')
    .then(响应处理函数)
    .then(数据处理函数)
    .catch(错误处理函数);

处理响应数据

javascript 复制代码
fetch('http://localhost:3000/users')
    .then(response => response.json())  // 解析 JSON
    .then(data => {                     // 处理数据
        console.log(data);
    })

流程解析

步骤 数据类型 说明
fetch() 返回 Response 对象 HTTP 响应原始对象
response.json() Promise<JSON> 解析为 JSON 的 Promise
第二个 .then() Array/Object 真正的数据,可直接使用

为什么需要 .then()?

fetch 是异步操作,必须等待服务器返回数据后才能处理:

scss 复制代码
同步执行(阻塞):
代码1 → 代码2 → 代码3

异步执行(非阻塞):
fetch() 开始请求 ──────────────────►
    ↓ 等待...
Promise.then() 处理结果 ✓

⏱️ fetch 发出请求后,不会等待结果,继续执行后面的代码

⚠️ 注意 :fetch 的错误处理有个特别之处------它只在网络故障时 才会进入 .catch()。如果后端返回 404(找不到资源)或 500(服务器错误)等状态码,fetch 依然会进入 .then()。因此,建议在解析 JSON 之前检查 response.ok

javascript 复制代码
fetch('http://localhost:3000/users')
    .then(response => {
        if (!response.ok) {
            throw new Error('请求失败: ' + response.status);
        }
        return response.json();
    })
    .then(data => console.log(data))
    .catch(err => console.error(err));

5. 通俗理解:前后端连接就像去餐厅吃饭

很多新手不理解前后端是怎么连接的,下面用一个通俗的餐厅例子来解释:

🍽️ 餐厅类比

scss 复制代码
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   🍽️ 餐厅例子                                               │
│                                                             │
│   ┌──────────┐              ┌──────────┐                   │
│   │  前台    │  ← 传菜单 →  │  厨房    │                   │
│   │ (前端)   │              │ (后端)   │                   │
│   └──────────┘  ← 端菜 →    └──────────┘                   │
│                                                             │
│   你坐的位置          服务员传话          厨师做菜           │
│   (浏览器)            (网络请求)           (服务器处理)      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1. 你去餐厅吃饭(打开网页)

markdown 复制代码
👤 你(浏览器)
    ↓ 走进餐厅
┌──────────────────┐
│  前台(网页界面)   │
│  桌号、菜单、座位   │
└──────────────────┘

2. 你点菜(前端发送请求)

sql 复制代码
👤 你对服务员说:"我要一份宫保鸡丁!"
    ↓ 传递菜单
┌──────────────────┐
│  服务员(fetch)  │  拿着菜单去厨房
└──────────────────┘

对应代码:

javascript 复制代码
fetch('http://localhost:3000/users')
//   ↑
// 就像服务员去找厨师

3. 厨房做菜(后端处理)

ini 复制代码
                    ┌──────────────────┐
                    │  厨房(后端)     │
                    │                   │
                    │  db.json = 菜谱   │
                    │  厨师按照菜谱做菜   │
                    └──────────────────┘

4. 端菜上桌(返回数据)

arduino 复制代码
                    ┌──────────────────┐
                    │  厨房(后端)     │
                    └────────┬─────────┘
                             ↓
┌────────────────────────────────────────────┐
│  你点的菜做好了!                           │
│  "宫保鸡丁一份,请慢用!"                   │
└────────────────────────────────────────────┘

对应代码:

javascript 复制代码
fetch('...')
    .then(data => data.json())  // 厨师把菜装盘
    .then(data => {
        // 菜端到你面前了,可以吃了!
        console.log(data);
    })

完整流程图

javascript 复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                                                                      │
│   后端(backend)                      前端(fe)                    │
│                                                                      │
│   ┌─────────────┐                      ┌─────────────────────┐      │
│   │  db.json    │                      │  index.html         │      │
│   │             │                      │  (页面界面)        │      │
│   │  存放数据    │                      │                     │      │
│   └──────┬──────┘                      └──────────┬──────────┘      │
│          │                                        │                 │
│          │  json-server 在 3000 端口监听           │                 │
│          │                                        │                 │
│   ┌──────┴──────┐                                │                 │
│   │  厨师        │                                │                 │
│   │  随时待命    │◄──────────────────────────────┤                 │
│   │             │    fetch('localhost:3000/users')                │
│   └─────────────┘    "我要 users 数据!"                           │
│          │                                                           │
│          │ 返回 JSON 数据                                            │
│          │ "[{id:1, name:'罗贤康'...}, ...]"                         │
│          │                                                           │
│          └──────────────────────────────────────────────────────────►│
│                           common.js                                   │
│                           ┌───────────────┐                           │
│                           │ 处理数据       │                           │
│                           │ 渲染到表格     │                           │
│                           └───────────────┘                           │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

关键点总结

概念 餐厅类比 代码
后端 厨房+厨师 db.json + json-server
前端 餐厅前台+座位 index.html + common.js
请求 你点菜 fetch('http://localhost:3000/users')
响应 菜端上来 .then(data => ...)
端口 3000 厨房的窗口 服务器监听的"门牌号"

💡 最重要的理解

  • fetch = 打电话给后端要数据
  • localhost:3000 = 后端家的地址
  • /users = 要的具体菜品
  • .then() = 收到数据后的处理

6. 循环遍历

for...of 循环(ES6)

javascript 复制代码
const users = [
    { name: '罗贤康', hometown: '南昌' },
    { name: '金道轩', hometown: '南昌' },
    { name: '王文瑾', hometown: '中国' }
];

// for...of:直接遍历元素,更简洁
for (let user of users) {
    console.log(user.name);  // 罗贤康、金道轩、王文瑾
}

// 传统 for 循环:需要索引
for (let i = 0; i < users.length; i++) {
    console.log(users[i].name);
}

forEach 方法

javascript 复制代码
users.forEach(user => {
    console.log(user.name);
});

7. 变量声明:const vs let

声明方式 特点 使用场景
const 常量,不能重新赋值 声明后不再改变的变量
let 变量,可以重新赋值 需要改变值的变量
var 函数作用域(不推荐) 避免使用
javascript 复制代码
const PI = 3.14159;     // 常量,不应改变
let count = 0;          // 变量,可能改变
count = count + 1;       // ✓ let 可以

PI = 3.14;               // ❌ TypeError: Assignment to constant variable

五、综合示例:动态渲染用户表格

javascript 复制代码
// 1. 定义空数组
let users = [];

// 2. 从 API 获取数据
fetch('http://localhost:3000/users')
    // 3. 解析 JSON 响应
    .then(data => data.json())
    // 4. 处理数据
    .then(data => {
        console.log('获取到的数据:', data);
        
        // 赋值给变量
        users = data;
        
        // 获取表格 tbody 元素
        const oBody = document.querySelector('.table tbody');
        
        // 遍历用户数据,生成 HTML
        for (let user of users) {
            oBody.innerHTML += `
            <tr>
                <td>${user.id}</td>
                <td>${user.name}</td>
                <td>${user.hometown}</td>
                <td>${user.nickname}</td>
            </tr>
            `;
        }
    })
    // 5. 错误处理
    .catch(err => console.error('请求失败:', err));

执行流程

css 复制代码
1. 定义 users = []
        ↓
2. fetch 发起请求(异步)
        ↓ 等待...
3. 服务器返回 JSON 数据
        ↓
4. response.json() 解析数据
        ↓
5. 遍历数组,拼接 HTML
        ↓
6. 插入到 tbody 中
        ↓
7. 页面显示完整表格 ✓

六、后端模拟:json-server

什么是 json-server?

json-server 是一个工具,可以快速搭建一个完整的 RESTful API 服务,只需一个 JSON 文件。

db.json 数据文件

json 复制代码
{
    "users": [
        {
            "id": 1,
            "name": "罗贤康",
            "hometown": "南昌",
            "nickname": "罗"
        },
        {
            "id": 2,
            "name": "金道轩",
            "hometown": "南昌",
            "nickname": "鸡蛋仙"
        }
    ]
}

启动服务

bash 复制代码
cd backend
npm install
npm run dev

自动生成的 API

方法 地址 说明
GET /users 获取所有用户
GET /users/1 获取 ID 为 1 的用户
POST /users 添加新用户
PUT /users/1 更新 ID 为 1 的用户
DELETE /users/1 删除 ID 为 1 的用户

七、端口的概念

端口 = 服务的"门牌号"

yaml 复制代码
计算机(IP 地址)
    ├── 端口 80    → HTTP 网页服务
    ├── 端口 443   → HTTPS 加密网页
    ├── 端口 3000  → json-server(我们的项目)
    ├── 端口 3306  → MySQL 数据库
    └── 端口 22    → SSH 远程登录

访问方式

arduino 复制代码
http://localhost:3000
       ↑      ↑
   IP 地址   端口号
  • localhost = 本机 IP 地址(127.0.0.1)
  • 3000 = json-server 监听的端口

八、大厂关注的底层能力

通过这个项目,我们学习了大厂特别注重的底层能力:

1. HTML 语义化

html 复制代码
<!-- 不推荐 -->
<div class="header">导航</div>
<div class="main">内容</div>

<!-- 推荐 -->
<header>导航</header>
<main>内容</main>

2. DOM 编程

javascript 复制代码
// 选择器查找
document.querySelector()

// 操作 DOM
element.innerHTML
element.appendChild()
element.remove()

3. 模块化思想

markdown 复制代码
├── backend/     → 后端模块
│   └── db.json
└── fe/          → 前端模块
    ├── index.html
    ├── common.js
    └── common.css

4. 树状数据结构

理解 document 对象的树状结构,是 DOM 编程的基础:

css 复制代码
document
  ├── html
  │   ├── head
  │   └── body
  │       └── div.container
  │           └── table
  │               └── tbody

九、常见错误及解决方案

1. favicon.ico 404 错误

问题:浏览器自动请求网站图标失败

解决:在 HTML 中添加内联图标

html 复制代码
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>💬</text></svg>" />

2. Bootstrap 类名不生效

问题:使用了 Bootstrap 的类名但没有引入 Bootstrap CSS

解决 :确保在 <head> 中引入 Bootstrap CDN

html 复制代码
<head>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css">
</head>

3. fetch 数据为 undefined

问题 :没有调用 .json() 方法

错误写法

javascript 复制代码
fetch('url').then(data => {
    console.log(data);  // ❌ Response 对象,不是数据
})

正确写法

javascript 复制代码
fetch('url')
    .then(res => res.json())  // ✓ 解析 JSON
    .then(data => {
        console.log(data);     // ✓ 真正的数据
    })

十、总结

通过这个简单的项目,我们学习了:

知识点 掌握程度
HTML 语义化标签
表格结构(thead/tbody/tr/th/td)
CSS 盒子模型
Bootstrap 栅格系统
DOM 树状结构
JavaScript 选择器
模板字符串
fetch API 异步请求
for...of 循环
前后端分离概念

🎯 学习建议:不要只看不练,亲手敲代码才能真正掌握!

十一、下一步学习

  1. 添加用户功能:使用 POST 请求添加新用户
  2. 删除用户功能:使用 DELETE 请求删除用户
  3. 搜索功能:在前端筛选数据
  4. 表单验证:验证用户输入
  5. 错误处理:更好的错误提示

📬 如果有任何问题,欢迎在评论区留言!

💻 项目源码:gitee.com/dongmeng-yi...

标签:前端入门 / HTML / CSS / JavaScript / 新手教程

相关推荐
XovH11 小时前
Django 从 0 到 1 打造完整电商平台:商品详情页与图片展示
后端
胡萝卜术11 小时前
从“用户管理”全栈项目深挖模块化、RESTful 与语义化之道
前端·后端
JiaWen技术圈11 小时前
React 中的 Server Components 和 Server Components
前端·javascript·react.js
用户2986985301411 小时前
告别手动复制:Java 拆分 Word 文档的两种实用方案
java·后端
光影少年11 小时前
react的 useReducer 使用场景、替代 useState 的情况
前端·react.js·掘金·金石计划
YAwu1111 小时前
原型与原型链:面试中的关键问题深入剖析
前端·javascript
To_OC11 小时前
徒手撸极简前后端分离Demo!吃透原生JS动态渲染底层
前端·javascript
HYCS11 小时前
用pixi.js实现fabric.js(四):StaticCanvas
前端·javascript·canvas
烬羽11 小时前
《读<JavaScript语言精粹>第3章,我整理了6个必须掌握的对象核心知识点》
前端