前端知识梳理

13 分钟读完

web-notes

记录一个本科生的前端开发学习之路,记录我对前端学习的思考,以及我对某些技术和问题的理解。
这个README文档,按照不同知识点由前到后,同类知识点由浅入深的顺序来组织内容。


开始之前

本文档的目的:
  • 知识梳理
  • 探究技术细节
  • 为其他学习者提供参考
文档写作的原则:
  • 以大学生的视角去看待学习中遇到的问题
  • 内容由浅入深
  • 不简单抄袭拷贝,会根据参考文章谈论自己的理解
  • 每篇文章都会讨论一个完整的知识点,避免碎片知识点
  • 虽然会梳理知识,但只涉及体系结构,内容只包括比较学习中遇到的重要的问题,而不是面面俱到

技术脉络

  1. 网页本质
  2. 基础
  3. 进阶
  4. 工具
  5. 总结
  6. 学习思考

1.网页本质

网页的本质是信息的交流(其实互联网的本质也是如此)

而网页前端开发所做的事情,简单来说,就是将信息展示给用户。注意,关键词是 “展示” 。 而“展示”其实包含很多方面,不妨简单思考一下:

  • 要展示的具体内容
  • 以怎样的模样展示
  • 不可能一次展现出所有信息,所以要考虑信息如何管理,以及信息切换的逻辑
  • 信息的获取方式,如何获取新信息,如何从已经存储的信息中筛选应该展示的信息
  • 信息的存储和管理,包括效率,安全等问题
  • ……

要全部说完几乎是不可能的,甚至会演变为哲学问题…
但是对于web开发者来说,重要的是这种看待信息的方式——要想当个艺术家,就要像艺术家一样思考问题。web开发也一样。

2.基础

注意!基础不等于简单,也不等于可以快速掌握,这也是很多初学者和自学者容易走错的地方。

这一部分对于web前端开发者的重要性,就像素描对于画家的重要性——每个人学习都要从这一阶段开始,并且要学的足够扎实,不然在进阶道路上将会一脸茫然。
此外,即便开始学习更高阶的技术,也经常需要回过头来补足薄弱之处。


2.1 HTML(Hyper Text Markup Language:超文本标记语言)

名称解释:

强大的组织文本/信息的语言。

功能:

前文提到过网页的本质是信息的交流,而HTML在网页中扮演的角色就是,将网页的信息的具体内容通过之间的关系(层级关系,逻辑关系)组织起来。
换言之,HTML负责组织网页的内容。

HTML基础:
  1. 通过分类来理解HTML标签
HTML5特性:
  1. HTML5带来的功能提升
  2. HTML5带来了哪些语义化提升

2.2 CSS (Cascading Style Sheets:层叠样式表)

名称解释:

(层叠式的)控制样式的表单

功能:

过去网页刚出现的时候,作为文献传播工具,其中的信息几乎是以纯文本展示的,没有样式可言。但是现在网页已经用于展示各类信息,我们的需求不再只是信息本身,更是如何提高可读性,如何让网页更加吸引人。
CSS就负责控制网页中的信息的以怎样的样式展示。

CSS基础:
  1. CSS选择器
  2. 通过分类来理解CSS属性
CSS进阶:
  1. CSS布局
  2. CSS动画

2.3 JavaScript

JavaScript最重要的功能,就是控制网页的一切。

那么是通过怎样的方式来控制的呢?

  1. JavaScript肯定要有自己的语法和基本数据结构(即对ECMAScript标准的实现)。
  2. DOM(Document Object Model:文档对象模型): 对于HTML来说,DOM将HTML文档看作一个树形结构模型,树中的每个节点都是一个对象,与HTML文档中的内容一一对应。通过这个树形结构中的各个对象的接口(由W3C组织指定的标准接口),从而对文档进行操作。
  3. BOM(Browser Object Model:浏览器对象模型):控制浏览器显示的页面内容之外的部分,但是现在还未形成标准,不同的浏览器有不同的实现。

所以,JavaScript是通过控制DOM来控制网页的。

JavaScript基本语法:

前文说了,JavaScript通过控制DOM来控制网页的方方面面,那么JavaScript又是如何控制DOM的呢?

  • 改变DOM总不能随机的改变,需要有一个“契机”,或者说有一个条件,只有当满足这个条件的时候,网页才做出相应的改变。(就好比枪膛里的子弹不会无缘无故的发射,只有当扣下扳机的时候,才会义无反顾的发射出去。)这个“契机”就叫做——事件
  • 事件又有很多类型,比如子弹不会在你上膛的时候发射。而在网页中,事件有可能是鼠标单击了一下,或者在键盘上敲击了某个键,甚至可能是页面加载到某一个阶段,因此,事件都有一个具体的类型,即——事件类型
  • 而每个事件,都应该是在网页中的某个部分触发的,可能是整个网页,也可能是网页中的某个按钮或者表单等等,也就是说,事件都需要有一个——事件源
  • 而要在事件源触发事件的那一刻立即响应,我们就需要时刻关注着事件源的变化,这种行为就叫做——事件监听
  • 当事件发生变化之后,我们就要开始正式改变DOM了,而这时我们要做的其实就是——事件处理程序

所以JavaScript控制DOM的流程可以分为两步:

  1. 监听事件源的某种类型的事件,并绑定对应的事件处理程序。
  2. 当事件发生的时候,执行事件处理程序,完成对DOM的改变。(这才是真正的操作DOM的部分)


所以我们需要考虑的也就是这两个问题:

  1. 如何合理的绑定事件
  2. 如何改变DOM
JavaScript的浏览器兼容性问题处理:

前面提到过,JavaScript主要包括两部分:对ECMAScript的实现,以及DOM。

然而一方面,因为ECMAScript和DOM的标准都会持续更新变化,所以迄今已经历经了很多版本。而在版本变化时,浏览器肯定要实现最新的版本,所以浏览器也会有版本升级(比如IE6,IE7,IE8这样),在新版本的浏览器中实现新的标准(旧的版本还是仅支持旧的标准)。
另一方面,不同浏览器对于W3C制定的同一DOM标准可能会有不同的实现(这其中最大的xx就是微软的IE浏览器!)。也就是说,有时候,想做同一件事,在不同的浏览器中却有不同的方式。
这两个方面,就是导致浏览器兼容性问题的根本原因。因为我们不可能奢望所有的用户都用最新版的浏览器。更不可能要求所有的用户都用同一种浏览器,因此,为了我们的网站可以跨浏览器兼容,我们应该处理这些问题。而因为浏览器对ECMAScript的实现倒是没有什么有差异的地方(当然较新的ES6除外),所以我们在这主要关心DOM的浏览器兼容性。

在这里不得不推荐一本书:

《JavaScript高级程序设计》(Nicholas C.Zakas)

推荐理由:权威,详细,实用性强,知识点全面

3.进阶

Ajax

Node.js

HTTP

ES6

网页优化

浏览器兼容性问题一览

其他

4.工具

SASS

SASS是一个CSS预处理器

原生的CSS在使用上会有很多不方便地方,当然,原生CSS的设计是没有问题的,我估计之所以保持简单,是为了渲染速度的考量。
然而在开发过程中,没有渲染的需求,所以提出了这样一种解决方案:

  1. 在开发的时候,我用一种功能更强大的语言(如SASS)编写样式表
  2. 开发结束后,再将SASS这样的语言编译成CSS,就可以正常使用了。

所以说,CSS预处理器解决的是开发时的需求。SASS的语法是基于CSS拓展的,所以只需要了解拓展了哪些语法规则,就可以开始使用了。使用之后才能孰能生巧(毕竟刚开始写CSS也不是一下子就熟悉的。)

Bootstrap

meteor

meteor是一个web应用的开发框架。

meteor是一种全栈js的框架,集成了服务器和客户端,客户端和服务端遵循DDP协议(类似web socket)连接,好处是可以双向传递数据,实现真正的响应式,即当服务器数据改变时,客户端的数据会跟着改变。

meteor非常适用于React这种组件化的web开发框架。因为对于组件化开发最大的问题就是数据如何传入组件,如何管理组件的数据。而Meteor避免了传统的AJAX查询的方法,让数据操作封装在Methods中,客户端调用Methods,得到数据。这样使得获取数据的逻辑更加清晰,也更易于管理数据操作(而不用写一大串的AJAX请求)。

meteor另一个好处就是快速开发。meteor框架内置了很多web应用必要的模块,比如用户认证模块,引入模块后只需要简单调用接口就可以实现用户认证。跟着官方的tutorial项目学习,很快就可以构建一个web app。

但meteor也有缺点,比如生态环境还不够强大,比起koa这类框架还有不少差距。

React

组件化的web前端解决方案。

首先,让我们简单回顾一下传统web应用的设计模式:

  1. 开发出客户端的界面
  2. 开发出服务端的数据接口,提供增删改查功能
  3. 在界面中需要的地方调用(通过表单或AJAX)接口,返回的数据通过DOM操作装载到页面中需要的地方。

这种模式其实非常清晰,但是有一些比较突出的缺点:

  • 需要大量的AJAX请求夹杂在界面的js文件中。而且创建AJAX请求有很多重复的代码。
  • 将获取到的数据装填到界面上需要大量大量大量的DOM操作,如果采用这种模式会发现自己仿佛一直在写DOM操作。
  • 难以实现数据的响应式更新,数据改变的时候页面不会自动的改变,而需要开发者在每一个想要改变的地方进行DOM操作:比如有一个用户修改了头像,这时候页面中的头像是不会更新的。要想在修改头像的时候更新页面中的所有头像,就需要手动通过DOM操作将当前页面中的所有使用了头像的地方更改一下,虽然可以通过给头像设置统一的类来实现,但是也还是太麻烦。
  • 当应用复杂的时候,页面的逻辑会变得很乱,因为本质上来说,一个页面对应着一个js文件,虽然我们可以将js文件拆分,但逻辑上却还是在一起的。

前端框架有很多,为了解决上面的一些问题,基本上都实现了这些功能:

  • 组件:将页面拆分成多层组件。(可以想象乐高积木,就是用不同的“组件”拼在一起的)
  • 数据绑定:想象一下,页面中有一个article(文章)组件,我告诉这个组件,组建中的<h1>标签的内容对应article对象的title字段。这样,每当页面重新加载,或者数据发生变化的时候,articletitle字段就会自动填充到该标签中。我们要做的,只是在一开始告诉组件某个数据应该放在哪个位置,这样,数据就和页面自动“绑定”了。
  • 数据管理:组件化可以让逻辑更加清晰,避免了很多复杂的DOM操作。但是也带来了一个问题:将页面划分成多层组件后,数据绑定到组件中对应的位置上,此时如何管理组件以及组件需要的数据就成了一个问题。

组件化框架有三款主流的:

  • React
  • Angular
  • Vue

各有各的优缺点,目前我还只真正接触过React,还不能理解各个框架的优缺点,以后了解其他框架后会补上。

React相关:

Redux

状态管理的解决方案

组件化开发面临数据管理困难的问题,对于组件来说,所谓数据,也就是组件的“状态”。

Redux提出了这样一种思路:

  • 将一个web应用中的所有数据都按照逻辑划分整理成一个“状态树”,每个组件在内部可以去“订阅”这个状态树的某一部分数据,然后组件内就可以取得订阅的数据,进行使用。
  • 一个应用启动后,它的状态肯定会(因为用户操作,或者数据更新)变化的,而变化不会平白无故的发生,应该是在应用中发生了某些行为。在Redux中,将这种行为定义为action,一个action需要包含:
    • 这个行为的类型,唯一的标识
    • 这个行为的发生需要哪些数据(比如一个查询行为需要查询参数。)
  • 行为会引起“状态树”的变化,而每种行为如何改变状态树,则需要由reducer来指定。reducer能做的事情十分纯粹:接收action以及应用当前的状态,根据action的类型和action携带的数据,对状态作出对应的改变,然后返回改变后的状态。(对于react这种组件框架来说,状态(state)的改变会引起组件中使用到state的组件被重新渲染,即自动更新)。
  • 当我们定义好了reducer,就可以利用当前的reducer创建一棵状态树(store),store管理着所有的状态:因为他是由reducer创建的(reducer是由action和state创建的),所以他知道可以监听哪些action,以及如何处理监听到的action,store也会对应的更新。
  • 至此,以上都是在我们web应用被使用之前所做的准备。
  • 仅仅定义了发生了哪种行为(action),以及如何处理行为(reducer),处理后得到的新状态(state)被谁接收(订阅subscribe)。还有最后一件事情没有做,就是触发(dispatch)行为。在组件的交互中(DOM事件的发生,或组件加载的一些特殊阶段),这些机会下我们都可以触发action,action被触发后,会被我们之前定义的状态树监听到,监听到后就可以将被触发的action交给对应的reducer处理,然后处理后得到新的状态树,界面中订阅了状态树的组件就会根据新状态而发生变化(当然,没有订阅的组件就不会发生变化)

这种的流程解释起来有些啰嗦,涉及一个比较长的工具链(预先定义:action -> reducer -> store 使用时:dispatch ),但是原理还是比较清晰简洁的,稍加使用一下,就可以大致理解了。

下面来总结一下redux的优点:

  • 将组件对应的数据的管理问题变成了:触发“事件” ->处理“事件”的模型。(有点参考了DOM事件处理的感觉)
  • 该模型分成多层,每层只做单一纯粹的事情,让逻辑变得十分清晰。
react相关

配合组件开发的UI库:ant design

UI的解决方案

之前我也见过不少UI库:谷歌的material design,适用于Vue的Element和iView,当然,还有现在要讲的,适用于React的ant design,来自阿里。

先来谈谈UI库有哪些用处:

  • 有很强的交互设计感。 不管是交互的过渡动画,还是颜色搭配,外观设计,又或者是交互方式,都算的上是精品。
  • 提供了很多原生标签没有的功能。 比如下拉选择列表,tab标签页,日期范围选择框等等。这些组件自己实现也不是不可以,但是第一点,自己实现可能非常慢,你可以自己手写一个日期范围选择,或者事件选择框试一下;第二点,自己实现很难保证组件的复用性,在不同的场景就可能不得不重新实现一下。
  • 简化了UI对应的数据处理。 自己写用户交互的组件的时候,数据处理是一个很头疼的问题,特别是像多级的下拉选择框,或者表单的验证等等,原生的HTML只给我们提供了有限的原生功能,而UI库则提供了大量功能强大的拓展,你可以简单地通过设置一些属性,就可以检查表单有效性,或者设置树形列表的列表项。

如果你还没有自己做过一些交互组件,并且体会不到组件库带来的好处,我建议你可以先去用html和js写个tab标签页,下拉选择列表,多级导航菜单,日期选择器,写了一番你就能体会到如果有人帮你全部处理了所带来的好处了。

再来说说UI库适用的场景:

  • 对界面美观有一定要求,但是对界面个性化没有强烈要求的项目。 虽然UI库设计很棒,也可以有一定限度的个性化,但是对于强烈需求个性化的项目(比较少见),应该是不适用的。
  • 需要快速开发的项目。 一个完整的web应用总要使用到很多组件,单是表单处理一项,就够我们忙的了。
  • 想要用一些酷炫的组件。 有些特别酷炫的组件,比如步骤条,分页,日历等等,我们自己做起来可能很费劲,逻辑也很乱。

适用UI库开发的工作模式:

  • 你会发现,如果写好公共样式(字体颜色等)和公共组件(侧边栏,页面的header/content/footer容器等),大多数情况下,你在开发的过程中几乎都不需要考虑样式了,只需要处理一下组件的布局。
  • 做界面就只是将需要的组件安放到界面上。
  • 你的大多数时间,都在处理数据:请求数据,调用接口,在组件中绑定数据,使用数据。
  • 当然,上面的情况是在没有大量骚页面,个性化页面的情况下,如果有这类页面,还是要手写不少样式的。

webpack

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(static module bundler)

你知道什么是”静态”吗?一般来讲,网页中的html,js,css,以及其他资源文件(img,font,file…)都是静态文件。这些文件本身是静态的——不变的。

与静态相对的是动态:即数据是动态地(从服务器)获取的。

静态文件每次开始执行的时候(比如你每次访问该网站的时候),都是相同的起点。你可能会说,我每次访问网站不一样啊,比如每次上微博里面的内容都有更新,这是因为,这些更新的部分,就是所谓“动态”,而发送请求去获取动态数据,并且使用这些数据的程序,是没有变化的。

这个概念有点像“铁打的营盘,流水的兵”。营盘是静态,兵是动态。

webpack的作用是打包,打包的对象是静态文件,文件的形式是模块,这些都是什么意思,在这篇文章中我们再详细讨论。

5.总结

6.学习思考


写在最后

前端的学习之路,对于一个没有工作经验,知识储备混杂的本科生来说,实在不是一条容易的道路。我们会涌现出很多疑问,有时候甚至连问题都问不出来。我且不谈论怎样的学习方式是有效的,但是我希望热爱这项技术的人,能够认清技术的本质,克服困难,热爱生活,前进下去。

本文所有观点均为作者个人观点,如有错误,恳请指正。也欢迎与我交流,共同进步。

个人联系方式:

Update 2018年7月 前端实习

大三结束了,找了一份前端实习的工作,在魔都。历经一番波折,也算是获得了进入前端这个行业的机会。在这里就分享下我的这段实习经历。

关于实习求职

实习日记

7月13日: Day 1:入职第一天

更新时间: