前端知识梳理
web-notes
记录一个本科生的前端开发学习之路,记录我对前端学习的思考,以及我对某些技术和问题的理解。
这个README文档,按照不同知识点由前到后,同类知识点由浅入深的顺序来组织内容。
开始之前
本文档的目的:
- 知识梳理
- 探究技术细节
- 为其他学习者提供参考
文档写作的原则:
- 以大学生的视角去看待学习中遇到的问题
- 内容由浅入深
- 不简单抄袭拷贝,会根据参考文章谈论自己的理解
- 每篇文章都会讨论一个完整的知识点,避免碎片知识点
- 虽然会梳理知识,但只涉及体系结构,内容只包括比较学习中遇到的重要的问题,而不是面面俱到
技术脉络
1.网页本质
网页的本质是信息的交流(其实互联网的本质也是如此)
而网页前端开发所做的事情,简单来说,就是将信息展示给用户。注意,关键词是 “展示” 。 而“展示”其实包含很多方面,不妨简单思考一下:
- 要展示的具体内容
- 以怎样的模样展示
- 不可能一次展现出所有信息,所以要考虑信息如何管理,以及信息切换的逻辑
- 信息的获取方式,如何获取新信息,如何从已经存储的信息中筛选应该展示的信息
- 信息的存储和管理,包括效率,安全等问题
- ……
要全部说完几乎是不可能的,甚至会演变为哲学问题…
但是对于web开发者来说,重要的是这种看待信息的方式——要想当个艺术家,就要像艺术家一样思考问题。web开发也一样。
2.基础
注意!基础不等于简单,也不等于可以快速掌握,这也是很多初学者和自学者容易走错的地方。
这一部分对于web前端开发者的重要性,就像素描对于画家的重要性——每个人学习都要从这一阶段开始,并且要学的足够扎实,不然在进阶道路上将会一脸茫然。
此外,即便开始学习更高阶的技术,也经常需要回过头来补足薄弱之处。
2.1 HTML(Hyper Text Markup Language:超文本标记语言)
名称解释:
强大的组织文本/信息的语言。
功能:
前文提到过网页的本质是信息的交流,而HTML在网页中扮演的角色就是,将网页的信息的具体内容通过之间的关系(层级关系,逻辑关系)组织起来。
换言之,HTML负责组织网页的内容。HTML基础:
- 通过分类来理解HTML标签
HTML5特性:
- HTML5带来的功能提升
- HTML5带来了哪些语义化提升
2.2 CSS (Cascading Style Sheets:层叠样式表)
名称解释:
(层叠式的)控制样式的表单
功能:
过去网页刚出现的时候,作为文献传播工具,其中的信息几乎是以纯文本展示的,没有样式可言。但是现在网页已经用于展示各类信息,我们的需求不再只是信息本身,更是如何提高可读性,如何让网页更加吸引人。
CSS就负责控制网页中的信息的以怎样的样式展示。
CSS基础:
- CSS选择器
- 通过分类来理解CSS属性
CSS进阶:
- CSS布局
- CSS动画
2.3 JavaScript
JavaScript最重要的功能,就是控制网页的一切。
那么是通过怎样的方式来控制的呢?
- JavaScript肯定要有自己的语法和基本数据结构(即对ECMAScript标准的实现)。
- DOM(Document Object Model:文档对象模型): 对于HTML来说,DOM将HTML文档看作一个树形结构模型,树中的每个节点都是一个对象,与HTML文档中的内容一一对应。通过这个树形结构中的各个对象的接口(由W3C组织指定的标准接口),从而对文档进行操作。
- BOM(Browser Object Model:浏览器对象模型):控制浏览器显示的页面内容之外的部分,但是现在还未形成标准,不同的浏览器有不同的实现。
所以,JavaScript是通过控制DOM来控制网页的。
JavaScript基本语法:
- 语法
- 控制语句
- 内置对象
- 函数
- 对象
- Eventloop说明
- JavaScript面向对象详解(原理)
控制DOM:
前文说了,JavaScript通过控制DOM来控制网页的方方面面,那么JavaScript又是如何控制DOM的呢?
- 改变DOM总不能随机的改变,需要有一个“契机”,或者说有一个条件,只有当满足这个条件的时候,网页才做出相应的改变。(就好比枪膛里的子弹不会无缘无故的发射,只有当扣下扳机的时候,才会义无反顾的发射出去。)这个“契机”就叫做——事件。
- 事件又有很多类型,比如子弹不会在你上膛的时候发射。而在网页中,事件有可能是鼠标单击了一下,或者在键盘上敲击了某个键,甚至可能是页面加载到某一个阶段,因此,事件都有一个具体的类型,即——事件类型。
- 而每个事件,都应该是在网页中的某个部分触发的,可能是整个网页,也可能是网页中的某个按钮或者表单等等,也就是说,事件都需要有一个——事件源。
- 而要在事件源触发事件的那一刻立即响应,我们就需要时刻关注着事件源的变化,这种行为就叫做——事件监听。
- 当事件发生变化之后,我们就要开始正式改变DOM了,而这时我们要做的其实就是——事件处理程序
所以JavaScript控制DOM的流程可以分为两步:
- 监听事件源的某种类型的事件,并绑定对应的事件处理程序。
- 当事件发生的时候,执行事件处理程序,完成对DOM的改变。(这才是真正的操作DOM的部分)
所以我们需要考虑的也就是这两个问题:
- 如何合理的绑定事件
- 事件类型一览
- 跨浏览器事件处理
- 如何改变DOM
- DOM中的对象类型一览
- 理解浏览器的window对象和document对象
- DOM操作
- 浏览器重流详解
JavaScript的浏览器兼容性问题处理:
前面提到过,JavaScript主要包括两部分:对ECMAScript的实现,以及DOM。
然而一方面,因为ECMAScript和DOM的标准都会持续更新变化,所以迄今已经历经了很多版本。而在版本变化时,浏览器肯定要实现最新的版本,所以浏览器也会有版本升级(比如IE6,IE7,IE8这样),在新版本的浏览器中实现新的标准(旧的版本还是仅支持旧的标准)。
另一方面,不同浏览器对于W3C制定的同一DOM标准可能会有不同的实现(这其中最大的xx就是微软的IE浏览器!)。也就是说,有时候,想做同一件事,在不同的浏览器中却有不同的方式。
这两个方面,就是导致浏览器兼容性问题的根本原因。因为我们不可能奢望所有的用户都用最新版的浏览器。更不可能要求所有的用户都用同一种浏览器,因此,为了我们的网站可以跨浏览器兼容,我们应该处理这些问题。而因为浏览器对ECMAScript的实现倒是没有什么有差异的地方(当然较新的ES6除外),所以我们在这主要关心DOM的浏览器兼容性。
- DOM相关的浏览器兼容性问题一览
- 如何自己实现一个getElementsByClassName方法
书籍推荐:
在这里不得不推荐一本书:
《JavaScript高级程序设计》(Nicholas C.Zakas)
推荐理由:权威,详细,实用性强,知识点全面
3.进阶
Ajax
Node.js
HTTP
ES6
网页优化
浏览器兼容性问题一览
其他
4.工具
SASS
SASS是一个CSS预处理器
原生的CSS在使用上会有很多不方便地方,当然,原生CSS的设计是没有问题的,我估计之所以保持简单,是为了渲染速度的考量。
然而在开发过程中,没有渲染的需求,所以提出了这样一种解决方案:
- 在开发的时候,我用一种功能更强大的语言(如SASS)编写样式表
- 开发结束后,再将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应用的设计模式:
- 开发出客户端的界面
- 开发出服务端的数据接口,提供增删改查功能
- 在界面中需要的地方调用(通过表单或AJAX)接口,返回的数据通过DOM操作装载到页面中需要的地方。
这种模式其实非常清晰,但是有一些比较突出的缺点:
- 需要大量的AJAX请求夹杂在界面的js文件中。而且创建AJAX请求有很多重复的代码。
- 将获取到的数据装填到界面上需要大量大量大量的DOM操作,如果采用这种模式会发现自己仿佛一直在写DOM操作。
- 难以实现数据的响应式更新,数据改变的时候页面不会自动的改变,而需要开发者在每一个想要改变的地方进行DOM操作:比如有一个用户修改了头像,这时候页面中的头像是不会更新的。要想在修改头像的时候更新页面中的所有头像,就需要手动通过DOM操作将当前页面中的所有使用了头像的地方更改一下,虽然可以通过给头像设置统一的类来实现,但是也还是太麻烦。
- 当应用复杂的时候,页面的逻辑会变得很乱,因为本质上来说,一个页面对应着一个js文件,虽然我们可以将js文件拆分,但逻辑上却还是在一起的。
前端框架有很多,为了解决上面的一些问题,基本上都实现了这些功能:
- 组件:将页面拆分成多层组件。(可以想象乐高积木,就是用不同的“组件”拼在一起的)
- 数据绑定:想象一下,页面中有一个article(文章)组件,我告诉这个组件,组建中的
<h1>
标签的内容对应article
对象的title
字段。这样,每当页面重新加载,或者数据发生变化的时候,article
的title
字段就会自动填充到该标签中。我们要做的,只是在一开始告诉组件某个数据应该放在哪个位置,这样,数据就和页面自动“绑定”了。 - 数据管理:组件化可以让逻辑更加清晰,避免了很多复杂的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.学习思考
写在最后
前端的学习之路,对于一个没有工作经验,知识储备混杂的本科生来说,实在不是一条容易的道路。我们会涌现出很多疑问,有时候甚至连问题都问不出来。我且不谈论怎样的学习方式是有效的,但是我希望热爱这项技术的人,能够认清技术的本质,克服困难,热爱生活,前进下去。
本文所有观点均为作者个人观点,如有错误,恳请指正。也欢迎与我交流,共同进步。
个人联系方式:
- Twitter:Sputnik Wang
- Email:sputnik_wang@outlook.com
Update 2018年7月 前端实习
大三结束了,找了一份前端实习的工作,在魔都。历经一番波折,也算是获得了进入前端这个行业的机会。在这里就分享下我的这段实习经历。
关于实习求职
实习日记
7月13日: Day 1:入职第一天