前端 101:给不了解前端的同学讲前端

10,456 阅读14分钟

简介

有时候需要向新同学科普前端,又不知道如何下手?先把这篇图文分享丢给他吧!

本文改编自魔法哥为 “百姓网暑期实习生训练营” 所作的前端入门讲座。此讲座面向在校大学生,内容比较初级,高手请飘过~

大家好,今天的分享主要分为以下三个部分。

由于目前计算机专业还没有为 Web 前端技术设立专门的课程,每位同学对前端的了解程度也不一样,今天的讲座会以最浅显的方式来为大家介绍 “前端”,帮助大家建立一个基本的概念。

前端是什么?

在回答这个问题之前,我想到了一道面试题:

当我们在浏览器中输入网址并按回车之后,接下来会发生什么?

我们来简单地看一看 “网页展现” 的整个过程。

比如这里有一个用户,它需要访问 abc.com 这个网址。一般来说,当用户输入一个域名时,是在请求一个 HTML 资源。当他完成域名解析之后,他的浏览器会向 abc.com 这个域名所指向的 Web 服务器发出请求。

有时候 Web 服务器直接就可以返回用户的请求了;有时候 Web 服务器还需要向数据库查询一些数据,然后才能把处理结果返回给用户。

当用户的浏览器拿到服务器返回的 HTML 资源之后,就开始解析并显示 HTML 的内容了。

一般来说,HTML 页面需要 CSS 资源来描述页面的样式。比如浏览器在解析 HTML 时发现了一个 CSS 外链 abc.com/a.css,它就会去请求这个资源。

HTML 页面往往还需要加载外部的 JS 资源,比如 abc.com/a.js,此时浏览器同样会向服务器请求这个资源。

当所需的资源都加载完成之后,这个页面就可以提供完整的外观和功能了。整个过程差不多就是这个样子了。

我们看一看这张流程图,可以在中间画一道竖线,把它分成左右两个部分。

我们会发现,这道线左侧的事情发生在浏览器端,我们称之为 “前端”;右侧的事情发生在服务器端,称为 “后端”。(“前端” 之所以叫 “前端”,是因为它离用户更近一些。)

大家都学过后端开发的相关课程,对后端这一块应该都比较熟悉了。那问题来了:在上面这个过程中,后端有哪些局限?

  • 服务器一旦把资源提供给浏览器之后,便失去对内容的影响。

  • 服务器无法得知用户在浏览器里做了什么,无法与用户交互。

这意味着,只有当用户下一次向服务器请求资源时,服务器才有机会再次决定用户看到的内容。那么,用户什么时候再向后端请求资源呢?

第一种情况是 “导航动作”。比如用户刷新页面、点击链接、点击浏览器的前进/后退等等。

第二种情况是用户提交表单。表单是最传统的页面交互方式之一,提交表单时浏览器会向服务器发出新请求——这意味着浏览器会跳转到一个新的地址,服务器会在新页面中显示表单的处理结果。

还有一种特殊情况,就是服务器在给浏览器返回 HTML 资源时,在页面中插入一个特殊的标记,浏览器看到这个标记就会在一定的时间后自动刷新当前页面或跳转到其它页面,相当于服务器强制用户再次发出请求。可想而知,这种非用户意愿驱动的页面跳转行为并不讨人喜欢,因此已经不常用了。

在传统网页中,上述几种用户与服务器之间的交互方式也算够用了。不过随着网页形态的不断演进,用户对网页体验提出了更高的要求,很多时候网页不仅仅是一篇静止的文档,而更像是一个应用程序,用户随时可能与之互动。这个时候,前端的价值就体现出来了。

  • 用户从停留在当前页面到发起新请求的这段时间内,前端可以控制页面内容。

  • 当用户停留在当前页面时,前端有能力与用户交互。由于前端的 JS 可以监听用户在浏览器中的各种行为(比如鼠标点击、键盘输入、滚动页面等等),前端就可以针对这些行为作出相应的反馈。

在前端与用户的交互过程中,有些事情光靠前端就可以做出响应。比如我们在网页上做了一个计算器的功能,当用户输入算式之后,JS 就可以直接计算出结果并显示给用户。整个过程不需要服务器的参与就可以完成。

但有些事情,光有前端是无法完成的。此时前端就需要交给后端来处理,拿到处理结果之后再交给用户。在这个过程中,前端可以让用户一直停留在当前页面,交互过程具有良好的连续性。

那么,前端如何把任务交给后端并拿到后端处理的结果呢?主要有两种方式:Ajax 和 Socket 连接。

Ajax 是最常见的前后端交互方式。它以 “请求→响应” 的方式来完成前后端的信息传递。传统的表单交互需求几乎都可以由 Ajax 改造为 “原地提交并获取反馈” 的交互方式,不需要跳转页面,从而有效提升用户体验。

而对于实时性比较高的场景,Socket 连接就是一个更好的选择。它的工作方式是前后端建立一个持续的连接,信息可以随时由前端发向后端,或由后端推送到前端。如果我们要建立一个实时对话的应用,通常就会用到 Socket 连接了。

前端需要用到哪些技术?

说到前端技术,我们通常都会说到 “三大块”:

  • HTML
  • CSS
  • JS

这是前端最核心的三项技术。

接下来,我们就会说到 “前端的分层架构”。这个架构的原则就是 “让合适的技术去做合适的事情”。一个网页从逻辑上可以视为这三层的有机结合体:

  • 结构层:这一层的作用是表述一个页面中有哪些信息,以及这些信息之间的关系是什么。这一层在技术上是由 HTML 来实现的。

  • 表现层:这一层决定了页面中的信息会以什么样的外观呈现出来。这一层由 CSS 来实现。

  • 行为层:这一层控制了页面如何与用户进行交互。在传统的展示型网页中,可能只需要 “结构层” 和 “表现层” 就足以提供完整的功能;而现代网页承载了越来越多的交互,这就推动 “行为层” 的能力不断增强。这一层由 JS 来实现。

我们通过一个实例来理解这个分层架构。

比如我是一个百姓网的用户,我打开了 “用户中心” 中的 “我发布的信息” 这个页面。

这个页面的 HTML 描述了信息以及信息的结构。即使没有 CSS 和 JS 的辅助,这个页面仍然可以呈现出可理解的内容(参见上图)。页面顶部是一些导航元素,接下来的 “显示中的信息” 是一个标题,它又引出了一个列表。这个列表自然就是我在百姓网发布的所有信息了。(除了 “显示中的信息” 以外,页面后半段还有 “已删除的信息”,这里不再赘述。)

接下来,我们会在表现层下功夫,通过 CSS 来为页面中的各个元素设定外观。经过这一层的修饰之后,页面中的内容更加美观了;更重要的是,各元素的功能职责也更加直观易懂了(参见上图)。

这已经是一个挺不错的网页了,但接下来,我们还会通过 JS 来丰富它的功能,提升用户的使用效率。

作为信息的发布者,我可能需要修改某条信息的内容,或对它进行 “刷新” 之类的操作。在传统的交互中,我需要在这个列表中点击需要操作的信息,然后在信息的详情页选择合适的操作。

我们可以把这个流程简化一下:我们在这个列表中为每条信息添加一个操作按钮,当用户点击某条信息的操作按钮时,我们就在页面中弹出一个操作面板,用户可以直接选择想要的操作,减少了中间环节(参见上图)。

由此可见,结构层、表现层、行为层这三者各有所长,共同构造了一个功能完备、体验良好的网页出来。

除了基本的 “三大块” 之外,作为前端工程师,我们还需要掌握以下知识和技能:

  • HTTP 相关:由于前端资源都是浏览器通过网络下载的,因此我们有必要了解相关的网络协议。

  • 浏览器相关:前端代码运行在浏览器中,我们需要了解浏览器的各种特性,以及浏览器向我们提供的各种接口。

  • 前端性能优化:让网页更快,减少用户的等待,这也是前端工程师面临的重要课题。优化网页的前端性能,需要我们具备上面两项知识,并且掌握性能优化相关的工具和方法。

  • 图形图像:网页信息不仅包含文字,还包含图片、视频等多媒体信息。图片作为最常用媒体资源,需要我们掌握与其相关的技能。比如了解各种图片格式适用的场景、基本的图片处理方法等等。

(在讲座中设立了一个 demo 环节,我会现场演示如何从零开始创建一个简单的网页,并实践 “前端的分层架构” 这一指导思想。)

前端的开发方式是怎样的?

前面我们已经介绍了前端技术 “三大块”,然而在如今,当我们在编写这三块的代码时,已经不再 “裸写” 了。这意味着我们在开发阶段编写的代码与实际在浏览器环境中运行的代码已经不一样了,详细来说:

  • 我们通过模板语言来生成 HTML。
  • 通过 CSS 预处理器来生成 CSS 代码。
  • 通过 ES6+ 的语法和特性来编写 JS 代码。

举例来看吧,以下三个例子展示了代码书写方式的演化。

百姓网采用了 Jade 和 Jedi 这两种模板语言。在上图的代码中,我们仅仅使用了模板语言最基本的标记语法,还没有插入使用模板语言的任何逻辑能力。仅此一步,就可以看出模板语言带来的好处。

原先我们在写 HTML 代码时,会花费大量的精力在 </> 这样的语法噪音上;同时,识别标签的嵌套关系也很费眼。幸运的是,Jade 和 Jedi 这样的现代模板语言把前端工程师解放了出来。它们通过缩进来表达嵌套关系,层级关系一目了然;语法更精练,表现力更强。

在 CSS 方面,预处理器一方面通过更简洁的语法减轻开发者的书写负担,另一方面通过内置的逻辑能力增强了代码的表现力。举个例子,在使用原生 CSS 来写代码时,不同元素采用的相同颜色只能分散在代码各处;而采用了 CSS 预处理器之后,我们可以把相同意义的颜色通过变量的形式抽象出来,然后在代码各处调用即可。这样不仅便于后期维护,在平时读代码时也更容易理解代码意图。

在 JS 方面,我们开始享受 ES6+ 带来的新特征福利。ES(ECMAScript)是定义 JS 这门语言的标准规范,从第六版开始,ES 以每年一版的节奏持续快速地扩展着 JS 语言的能力。

在以往,如果我们要实现 “在数组中找出符合特定条件的成员” 的需求,往往需要借助 Underscore 这样的工具库,调用它的 _.find() 方法。而在 ES6 中,语言本身就扩展了数组的能力,我们只需要直接调用 Array#find() 接口即可。另外,像箭头函数这样的新语法也可以令代码进一步简化。

在 HTML、CSS、JS 这三大块,我们放弃 “裸写”,采用 “更高级” 语言的目的在于:

  • 利用高级语言提供的 “逻辑能力” 来增强代码的表现力。

  • 利用高级语言的 “语法糖” 和 “新特性” 来提升开发效率和舒适度。

当然,采用这些更高级的语言也不是完全没有成本的。我们在开发阶段所用的语言已经不是纯粹的 HTML、CSS、JS 了,浏览器无法直接识别和运行。因此,当我们放弃 “裸写”,也就意味着:

  • 在部署流程中需要设立构建环节,把源码编译到浏览器环境可以运行的目标代码。

  • 在开发阶段,需要有工具来实时监视并编译有变动的源码,以确保页面上呈现的是我们修改过的最新效果。

在百姓网,前端架构组已经搭建好了必要的开发环境,开发者们只需要关注开发本身就可以了。

在企业级的前端开发中,我们还需要了解如下知识点:

  • 模块化:模块化是最常见的编程实践之一,令我们的代码组织更加清晰、易维护。ES6 为 JS 增加了完善的模块化方案,我们的日常开发也已经迁移到了 ES6 模块规范之下。

  • 包管理:如何将开源社区中的优秀组件为我所用?这就不能不提 “npm” 这个最主流的 JS 包管理器。前端界优秀的开源项目几乎都发布到了 npm 的包仓库,我们日常开发中用到的第三方库也都是由 npm 来管理的。

    打包工具可以把我们写的模块化的源码和第三方包整合到一起,形成页面所需的完整 JS 资源。“包管理器”、“模块化”、“打包工具” 的相互结合,基本上就是日常的 JS 代码组织方式。

  • 组件化:在传统的前端开发中,HTML、CSS、JS 这三块的代码有各自独立的文件,这些文件往往也分散在不同的目录结构中。

    如果页面功能区块的划分足够清晰,开发者就可以用 “组件” 的概念来把页面拆分,整个页面会被视为多个组件的嵌套和组合;同时,开发者也倾向于把每个组件相关的 HTML、CSS、JS 代码整合到同一个目录(或同一个文件)中,便于管理和维护。

    这就是 “组件化” 的开发模式。要实现这样的开发模式,通常需要前端框架和构建工具的配合。

  • 单页应用:HTML5 的 History API 为前端提供了控制浏览器导航行为的能力,配合 Ajax 无刷新更新页面内容的特性,我们可以在一个页面内实现应用的多视图切换,避免页面的频繁跳转,提供类似桌面应用的体验。比如 Gmail 等产品就是典型的单页应用模式,百姓网的大多数后台系统也都是单页应用。

  • 其它实用的知识点,就留待大家在工作中慢慢发掘吧。

今天想跟大家分享的主要内容就是这些了,感谢阅读,再见!


作者:CSS魔法@前端架构
简介:百姓网前端架构 TL,《CSS 揭秘》译者,CSS Conf 讲师,自称 “披着工程师外衣的设计师”。

本文仅为作者个人观点,不代表百姓网立场。
题图作者:lakexyde @ Pixabay


本文在 “百姓网技术团队” 微信公众号首发,扫码立即订阅: