Node + React 实战:从0到1 实现记账本(八)


theme: channing-cyan

服务端总结&单页面开发概念

一.服务端语言

服务端语言是什么?它是运行在服务器上,可用于读写数据库、编写服务逻辑的语言。

我并不想把这件事情描述的太复杂,因为归根结底它就是做这两件事。

至于服务端语言的选择,完全是根据业务和自身能力相结合。比如我是一个前端开发,我更倾向于选择 Node 作为服务端开发语言,因为 js 可以去写后端。

这里强调一下,Node 它本身不是一门语言,而是一个开发环境,基于谷歌的 V8 引擎,能让 JavaScript 可以运行在服务器的一个环境。赋予 JavaScript 更多除了浏览器脚本意外的能力,如 IO 操作等。

二.数据库

数据库的作用,是用于数据的持久化存储。

本项目选择 MySQL 作为数据库,是因为它作为老牌数据库,网上解决方案比较多,若是在开发过程中遇到问题,可以在搜索引擎上轻松找到自己遇到的问题的解决方案,对于新手而言,项目开发的流畅度是关键,完成一整套项目的开发之后,当然可以尝试去选择其他更有意思的数据库,这里不展开描述。

image.png

本教程采用 egg-mysql 插件进行数据库的操作。官方推荐使用 Sequelize 来应对较为复杂的项目。初衷是希望大家能快速入门,不希望引入过多的复杂概念,这里如果在后续的学习过程中有需要应对更为复杂的项目时,可以考虑引入 Sequelize 。

三.项目分析

整个项目是基于 Egg.js 作为上层架构,通过 Egg.js 提供的一些预定好的开发形式,轻松地完成了下列十余个接口的开发:

image.png

项目不大,但是本项目包含了几个关键的知识点:

  • 多用户鉴权
  • 一套增删改查
  • 表数据的二次处理(图表)
  • 列表分页的制作
  • 文件数据上传

用“麻雀虽小、五脏俱全”来形容,哈哈哈。

如果想要在此基础上拓展一些新的功能,如朋友圈、笔记、博客等,都是可以基于该项目进行二次开发的,因为多用户鉴权的架子已经搭建好,后续要做的就是添加表,以及一些业务逻辑上的处理。

当然,如果想做更为复杂的项目,比如一个商城。那涉及到的内容可能就更多了,单论商品模块的后台编辑,前台展示,就涉及到 sku、购物车、库存的处理、多图上传、详情编辑、类型筛选等等。这就很考验知识储备和解决问题的能力了。

四.前端框架单页面概念

服务端的内容基本上已经结束,从这开始,带进入前端部分的实战环节。本项目前端部分使用 React 作为前端框架,所以先理解什么是单页面,它是怎样实现页面组件之间的切换,路由的原理等知识点。

  • 传统页面 DOM 直出
  • 单页面原理
  • 前端路由实现

1.单页面

前端自从进入三大框架时代以来,传统的多页面开发已渐渐淡出人们的视线。为了更好的了解现在,先要去知道它的过去。

2.传统页面

这里不纠结叫法,凡是整个项目都是 DOM 直出的页面,都称它为“传统页面”(SSR 属于首屏直出,这里我不认为是传统页面的范畴)。那么什么是 DOM 直出呢?简单说就是在浏览器输入网址后发起请求,返回来的 HTML 页面是最终呈现的效果,那就是 DOM 直出。并且每次点击页面跳转,都会重新请求 HTML 资源。耳听为虚,眼见为实。以这个地址为例,验证以下上述说法。

https://www.cnblogs.com/han-1034683568/p/14126727.html#4773138

image.png

腚眼一看,就能明白上图在描述什么。没错,博客园就是一个传统页面搭建而成的网站,每次加载页面,都会返回 HTML 资源以及里面的 CSS 等静态资源,组合成一个新的页面。打开后如下所示:

image.png

网页上能看到什么图片或文字,你能在上述图片中找到相应的 HTML 结构,那也属于传统页面,也就是 DOM 直出。

3.单页面

时代在进步,科技在发展,面对日益增长的网页需求,网页开始走向模块化、组件化的道路。随之而来的是代码的难以维护、不可控、迭代艰难等现象。面临这种情况,催生出不少优秀的现代前端框架,首当其冲的便是 React 、 Vue 、 Angular 等著名单页面应用框架。而这些框架有一个共同的特点,便是“通过 JS 渲染页面”。 举个例子,以前直出 DOM ,而现在运用这些单页面框架之后, HTML 页面基本上只有一个 DOM 入口,大致如下所示:

image.png

所有的页面组件,都是通过运行上图底部的 app.js 脚本,挂载到 <div id="root"></div> 这个节点下面。用一个极其简单的 JS 展示挂载这一个步骤: ```js

```

所有的节点都通过 createElement 方法创建,最终通过 appendChild 的形式插入到 root 根节点。

那么问题来了,如果有十几个页面需要这样的操作咋整?

这时候「前端路由」应运而生,它的出现就是为了解决单页面网站多个页面组件切换。通过切换浏览器地址路径,来匹配相对应的页面组件。通过一张丑陋的图片来理解这个过程:

image.png

「前端路由」会根据浏览器地址栏 pathname 的变化,去匹配相应的页面组件。然后将其通过创建 DOM 节点的形式,塞入根节点

 。这就达到了无刷新页面切换的效果,从侧面也能说明正因为无刷新,所以 React 、 Vue 、 Angular 等现代框架在创建页面组件的时候,每个组件都有自己的「生命周期」。

4.路由实现原理

「前端路由」插件比较火的俩框架对应的就是 Vue-Router 和 React-Router ,但是它们的逻辑,归根结底还是一样的,用殊途同归四个字,再合适不过。

通过分析「哈希模式」和「历史模式」的实现原理,对前端路由的原理有一个更深刻的理解。

哈希模式(hash)

a 标签锚点大家应该不陌生,而浏览器地址上 # 后面的变化,是可以被监听的,浏览器提供了原生监听事件 hashchange,它可以监听到如下的变化:

  • 点击 a 标签,改变了浏览器地址。
  • 浏览器的前进后退行为。
  • 通过 window.location 方法,改变浏览器地址。

接下来利用这些特点,去实现一个 hash 模式的简易路由: 在线运行

```html

Hash 模式

```

当然,这是很简单的实现,真正的 hash 模式,还要考虑到很多复杂的情况,大家有兴趣就去看看源码。

image.png

历史模式(history)

history 模式会比 hash 模式稍麻烦一些,因为 history 模式依赖的是原生事件 popstate,下面是来自 MDN 的解释:

image.png

小知识:pushState 和 replaceState 都是 HTML5 的新 API,他们的作用很强大,可以做到改变浏览器地址却不刷新页面。这是实现改变地址栏却不刷新页面的重要方法。

包括 a 标签的点击事件也是不会被 popstate 监听。需要想个办法解决这个问题,才能实现 history 模式。

解决思路:可以通过遍历页面上的所有 a 标签,阻止 a 标签的默认事件的同时,加上点击事件的回调函数,在回调函数内获取 a 标签的 href 属性值,再通过 pushState 去改变浏览器的 location.pathname 属性值。然后手动执行 popstate 事件的回调函数,去匹配相应的路由。逻辑上可能有些饶,用代码来解释一下:在线地址

```html

History 模式

```

这里注意,不能在浏览器直接打开静态文件,需要通过 web 服务,启动端口去浏览网址。默认打开的协议是 file 协议,它是不会被 popstate 监听的。

五.总结

上述内容,基本上对前端单页面的实现原理有了一个大概的雏形,更深入的学习还是需要再对框架的源码进行分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值