徒手撸极简前后端分离Demo!吃透原生JS动态渲染底层

之前一直觉得前后端分离是个特别高大上的工程化概念,总以为得学一堆框架、接口规范、部署流程才能上手。

直到昨天我没用Vue、没用React,纯靠原生JS+HTML+CSS+json-server,手写了一套最朴素的前后端分离小案例,瞬间把底层逻辑彻底打通了。

没有花里胡哨的封装,所有流程都是最原始的写法,反而让我搞懂了框架背后到底在帮我们做什么。今天把我踩坑、试错、顿悟的全过程分享出来。

先说说我想解决的问题

以前写前端页面,所有数据都是写死在HTML里的。

展示一个用户表格,就得手动写一堆<tr>,新增、修改、删除数据都要改页面代码,特别笨拙,完全不符合实际开发逻辑。

我就想实现一个最基础的效果:数据单独存、前端动态拉取、自动渲染页面,真正做到数据和页面结构分离。

不想搭复杂的 Java、Python 后端,偶然发现 json-server 这个神器,零代码就能搭本地API接口,新手练手前后端分离再合适不过。

5分钟搭建极简模拟后端

说实话,以前总觉得后端搭建很麻烦,这次实操完才知道,本地练手的后端居然这么简单。

全程就三个文件,分工超级清晰,这也是我第一次真切体会到模块化拆分的意义。

1. 初始化项目配置

新建一个 backend 文件夹,执行 npm init -y 初始化项目,生成 package.json。这个文件就是项目的"身份证",记录所有依赖和启动脚本。

然后安装核心依赖 npm i json-server,最后配置启动命令,完整配置如下:

json 复制代码
{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev":"json-server --watch db.json" // 启动本地模拟接口服务
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs",
  "dependencies": {
    "json-server": "^1.0.0-beta.15"
  }
}

2. 搭建模拟数据库

新建 db.json,直接写入模拟用户数据,json-server 会自动把这个文件当成数据库,对外提供接口。

json 复制代码
{
  "users":[
    {
      "id": 1,
      "name": "张三",
      "hometown": "杭州",
      "nikename": "小三"
    }, 
    {
      "id": 2,
      "name": "李四",
      "hometown": "南昌",
      "nikename": "小四"
    },
    {
      "id": 3,
      "name": "王五",
      "hometown": "上海",
      "nikename": "小五"
    }
  ]
}

终端执行 npm run dev,直接启动服务,访问 http://localhost:3000/users 就能拿到所有用户数据。一行后端代码没写,接口直接可用,太适合新手练手了。

用Bootstrap重构页面,改掉Div满天飞的坏习惯

之前写页面,我清一色全用 div,堆得乱七八糟,自己回头看都看不懂结构。这次刻意用了 HTML5 语义化标签 + Bootstrap 栅格布局,彻底改掉了烂习惯。

语义化标签的真香之处

这次页面我用了 headermainasidefooter,表格也严格区分 theadtbody

以前觉得这些标签没用,和 div 没区别,后来才懂大厂为啥特别看重语义化:

  • 结构一目了然,哪个是头部、主体、侧边栏清晰分明
  • 搜索引擎抓取页面更友好,利于SEO
  • 表格拆分表头和表体,是规范开发的基础,后续DOM操作更精准

Bootstrap栅格布局快速适配页面

手动写CSS居中、自适应布局太麻烦,Bootstrap的栅格系统直接开箱即用。

我用了 container 做页面居中留白,row 定义行,col-md-6 col-md-offset-3 实现表格居中展示,几行类名搞定布局,不用写一行自定义CSS。

完整HTML页面代码:

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动态数据表格</title>
    <!-- 引入Bootstrap样式,快速实现页面布局 -->
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <header>111</header>
    <!-- 核心主体区域 -->
    <main class="container">
        <aside>333</aside>
        <!-- 栅格布局:居中6列表格 -->
        <div class="row col-md-6 col-md-offset-3">
            <table class="table table-striped" id="user-table">
                <thead class="container">
                    <tr>
                        <td>ID</td>
                        <td>姓名</td>
                        <td>家乡</td>
                        <td>昵称</td>
                    </tr>
                </thead>
                <tbody>
                    <!-- JS动态渲染数据,这里留白 -->
                </tbody>
            </table>
        </div>
        <aside>444</aside>
    </main>
    <footer>222</footer>
    <!-- 引入自定义JS逻辑 -->
    <script src="./common.js"></script>
</body>
</html>

踩坑半小时!终于弄懂JS异步执行逻辑

这是本次学习最大的卡点,也是新手最容易犯的错!

我第一版代码写完,控制台能打印出接口数据,但页面空白、无任何渲染内容,当时直接懵了。

错误写法(千万别这么写)

我当时把数据遍历渲染的代码,写在了 fetch 请求的外面:

bash 复制代码
let users=[];

// 异步请求数据
fetch('http://localhost:3000/users')
    .then(data => data.json())
    .then(data => {
        console.log(data); // 控制台能正常打印数据
        users=data;
    })

// 同步遍历渲染(坑死我了!)
const oBody = document.querySelector('.table tbody'); 
for(let user of users){
    oBody.innerHTML += `
        <tr>
            <td>${user.id}</td>
            <td>${user.name}</td>
            <td>${user.nikename}</td>
            <td>${user.hometown}</td>
        </tr>
    ` 
}

我百思不得其解:数据明明拿到了,为啥渲染不出来?

后来翻了执行逻辑才恍然大悟:JS是单线程,同步代码优先执行,异步代码后置执行

页面加载后,会先执行外面的 for 循环,这时候 fetch 接口还在请求中,users 还是空数组。等接口请求成功、赋值完数据,页面早就渲染结束了。

执行步骤(按时间顺序)

  1. 定义空数组 users = []
  2. 发起 fetch 请求 → 丢到异步队列,不等待,继续走后面代码
  3. 立刻执行同步的 for 循环users 是空的,页面啥也不渲染
  4. 过了一会儿,网络请求成功 → 执行 .then → 给 users 赋值
  5. 但渲染代码早就跑完了! 页面永远不会更新

结果

  • 控制台能打印数据(赋值成功了)
  • 页面无任何数据(渲染时数据还没回来)

正确写法(所有依赖接口数据的操作,放进回调)

bash 复制代码
let users=[];
const oBody = document.querySelector('.table tbody'); 

// 异步获取数据 + 动态渲染,全部放在回调内部
fetch('http://localhost:3000/users')
    .then(data => data.json())
    .then(data => {
        console.log(data);
        users=data;
        // 数据回来后,再执行DOM渲染
        for(let user of users){
            oBody.innerHTML += `
            <tr>
                <td>${user.id}</td>
                <td>${user.name}</td>
                <td>${user.nikename}</td>
                <td>${user.hometown}</td>
            </tr>
        ` 
        }
})

执行步骤

  1. 定义变量、获取 DOM
  2. 发起 fetch 请求 → 丢到异步队列
  3. 等待网络请求......(期间不执行任何代码)
  4. 数据成功返回 → 执行 .then
  5. users 赋值 → 再执行 for 循环渲染
  6. 页面正常显示数据

结果

  • 控制台打印数据
  • 页面正常渲染所有用户信息

一句话总结

  • 第一段:不等数据回来,直接渲染 → 白跑一趟,没数据
  • 第二段:等数据回来,再渲染 → 逻辑正确,页面生效

这就是 JavaScript 异步编程最基础、最容易踩的坑!所有依赖异步数据的操作 (渲染 DOM、计算、判断等),必须写在异步回调(then/async-await)里面

新手核心避坑点:只要是接口请求、定时器这类异步操作,后续所有依赖返回结果的逻辑,必须写在异步回调里面!

原生DOM编程,吃透框架底层原理

现在的框架都帮我们封装好了DOM渲染,很多人只会用框架,根本不懂底层怎么实现的。这次纯原生手写,我彻底搞懂了动态渲染的本质。

简单说下我的通俗理解:

DOM 就是浏览器把所有HTML标签,转换成JS内存里的一棵树状对象 。我们通过 querySelector 精准选中页面节点,再用 innerHTML动态拼接HTML结构,把接口数据批量插入页面。

对比老式的索引for循环,ES6的 for...of 真的太香了,不用管下标、不用赋值,直接遍历数组元素,代码简洁可读性拉满,这也是现在主流的遍历写法。

最后聊聊模块化开发的感悟

以前写代码,所有结构、样式、逻辑全堆在一个文件里,看着简洁,实则一坨乱麻,后续根本没法维护扩展。

这次我严格做了拆分:

  • HTML:只负责页面结构,只管长什么样
  • CSS/外部Bootstrap:只负责页面样式,只管好不好看
  • 独立JS文件:只负责逻辑、数据请求、DOM渲染
  • json文件:只负责存储数据

这就是最基础的模块化思想:每个文件只做一件事,各司其职,解耦分离。所有大厂的工程化项目,底层都是这个逻辑。

收尾:本次学习3个核心收获

折腾完这个小demo,比我看十篇理论文章收获都大,总结三个最实用的知识点:

1.前后端分离的本质超简单:前端专注视图渲染,后端专注提供数据接口,数据和页面彻底解耦,这就是所有前后端项目的核心逻辑。

  1. JS异步执行是重中之重:同步先行、异步后置,所有依赖接口返回值的逻辑,绝对不能写在异步代码外部。

  2. 基础远比框架重要:Vue/React只是封装了DOM操作和异步逻辑,吃透原生DOM、异步机制、语义化开发,才算真正懂前端。

最后提一句:json-server 只适合新手练手 、本地调试,没有权限校验、数据持久化简陋,千万别用到线上正式项目

其实前端很多看似难懂的概念,亲手撸一遍demo就彻底通透了。你们初学前端的时候,有没有踩过JS异步、DOM渲染的坑?评论区聊聊~

相关推荐
weixin_382395233 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__3 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.4 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~5 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华6 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子8 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅8 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni8 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学10 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端