徒手撸极简前后端分离Demo!吃透原生JS动态渲染底层
之前一直觉得前后端分离是个特别高大上的工程化概念总以为得学一堆框架、接口规范、部署流程才能上手。直到昨天我没用Vue、没用React纯靠原生JSHTMLCSSjson-server手写了一套最朴素的前后端分离小案例瞬间把底层逻辑彻底打通了。完整文章地址https://juejin.cn/post/7642981046925918208没有花里胡哨的封装所有流程都是最原始的写法反而让我搞懂了框架背后到底在帮我们做什么。今天把我踩坑、试错、顿悟的全过程分享出来。先说说我想解决的问题以前写前端页面所有数据都是写死在HTML里的。展示一个用户表格就得手动写一堆tr新增、修改、删除数据都要改页面代码特别笨拙完全不符合实际开发逻辑。我就想实现一个最基础的效果数据单独存、前端动态拉取、自动渲染页面真正做到数据和页面结构分离。不想搭复杂的 Java、Python 后端偶然发现json-server这个神器零代码就能搭本地API接口新手练手前后端分离再合适不过。5分钟搭建极简模拟后端说实话以前总觉得后端搭建很麻烦这次实操完才知道本地练手的后端居然这么简单。全程就三个文件分工超级清晰这也是我第一次真切体会到模块化拆分的意义。1. 初始化项目配置新建一个 backend 文件夹执行npm init -y初始化项目生成package.json。这个文件就是项目的“身份证”记录所有依赖和启动脚本。然后安装核心依赖npm i json-server最后配置启动命令完整配置如下{ 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 会自动把这个文件当成数据库对外提供接口。{ 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 栅格布局彻底改掉了烂习惯。语义化标签的真香之处这次页面我用了header、main、aside、footer表格也严格区分thead和tbody。以前觉得这些标签没用和 div 没区别后来才懂大厂为啥特别看重语义化结构一目了然哪个是头部、主体、侧边栏清晰分明搜索引擎抓取页面更友好利于SEO表格拆分表头和表体是规范开发的基础后续DOM操作更精准Bootstrap栅格布局快速适配页面手动写CSS居中、自适应布局太麻烦Bootstrap的栅格系统直接开箱即用。我用了container做页面居中留白row定义行col-md-6 col-md-offset-3实现表格居中展示几行类名搞定布局不用写一行自定义CSS。完整HTML页面代码!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title动态数据表格/title !-- 引入Bootstrap样式快速实现页面布局 -- link hrefhttps://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css relstylesheet /head body header111/header !-- 核心主体区域 -- main classcontainer aside333/aside !-- 栅格布局居中6列表格 -- div classrow col-md-6 col-md-offset-3 table classtable table-striped iduser-table thead classcontainer tr tdID/td td姓名/td td家乡/td td昵称/td /tr /thead tbody !-- JS动态渲染数据这里留白 -- /tbody /table /div aside444/aside /main footer222/footer !-- 引入自定义JS逻辑 -- script src./common.js/script /body /html踩坑半小时终于弄懂JS异步执行逻辑这是本次学习最大的卡点也是新手最容易犯的错我第一版代码写完控制台能打印出接口数据但页面空白、无任何渲染内容当时直接懵了。错误写法千万别这么写我当时把数据遍历渲染的代码写在了 fetch 请求的外面let users[]; // 异步请求数据 fetch(http://localhost:3000/users) .then(data data.json()) .then(data { console.log(data); // 控制台能正常打印数据 usersdata; }) // 同步遍历渲染坑死我了 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还是空数组。等接口请求成功、赋值完数据页面早就渲染结束了。执行步骤按时间顺序定义空数组users []发起fetch请求 →丢到异步队列不等待继续走后面代码立刻执行同步的 for 循环→users是空的页面啥也不渲染过了一会儿网络请求成功 → 执行.then→ 给users赋值但渲染代码早就跑完了页面永远不会更新结果控制台能打印数据赋值成功了页面无任何数据渲染时数据还没回来正确写法所有依赖接口数据的操作放进回调let users[]; const oBody document.querySelector(.table tbody); // 异步获取数据 动态渲染全部放在回调内部 fetch(http://localhost:3000/users) .then(data data.json()) .then(data { console.log(data); usersdata; // 数据回来后再执行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 } })执行步骤定义变量、获取 DOM发起fetch请求 → 丢到异步队列等待网络请求……期间不执行任何代码数据成功返回→ 执行.then给users赋值 →再执行 for 循环渲染页面正常显示数据结果控制台打印数据页面正常渲染所有用户信息一句话总结第一段不等数据回来直接渲染→ 白跑一趟没数据第二段等数据回来再渲染→ 逻辑正确页面生效这就是 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.前后端分离的本质超简单前端专注视图渲染后端专注提供数据接口数据和页面彻底解耦这就是所有前后端项目的核心逻辑。JS异步执行是重中之重同步先行、异步后置所有依赖接口返回值的逻辑绝对不能写在异步代码外部。基础远比框架重要Vue/React只是封装了DOM操作和异步逻辑吃透原生DOM、异步机制、语义化开发才算真正懂前端。最后提一句json-server 只适合新手练手、本地调试没有权限校验、数据持久化简陋千万别用到线上正式项目。其实前端很多看似难懂的概念亲手撸一遍demo就彻底通透了。你们初学前端的时候有没有踩过JS异步、DOM渲染的坑评论区聊聊