licong96 / blogs Goto Github PK
View Code? Open in Web Editor NEWIt's a blog and a resume.
It's a blog and a resume.
请求部分:请求行、请求头、空行、请求体
响应部分:响应行、响应头、空行、响应体
方法 + 路径 + http版本
GET /home HTTP/1.1
http版本 + 状态码
HTTP/1.1 200 OK
key-val的值
用来区分开请求头和请求体
问:如果说在头部中间故意加一个空行会怎么样?
答:那么空行后的内容全部被视为请求体。
就是具体的数据了,也就是body部分。请求报文对应请求体, 响应报文对应响应体。
请求方法是以下三种方法之一:HEAD,GET,POST
HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type(只限于三个值application/x-www-form-urlencoded、 multipart/form-data、text/plain)
凡是不同时满足上面两个条件,就属于非简单请求。
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。"预检"请求用的请求方法是OPTIONS
RFC 规定 HTTP 的状态码为三位数,被分为五类:
特点:
缺点:
HTTP 针对这一场景,采取了范围请求的解决方案,允许客户端仅仅请求一个资源的一部分。
前提是服务器要支持范围请求,要支持这个功能,就必须加上这样一个响应头: Accept-Ranges: none。
有两种主要的表单提交的方式,体现在两种不同的Content-Type取值:
由于表单提交一般是POST请求,很少考虑GET,因此这里我们将默认提交的数据放在请求体中。
在实际的场景中,对于图片等文件的上传,基本采用multipart/form-data。
前面说到了 HTTP 是一个无状态的协议,每次 http 请求都是独立、无关的,默认不需要保留状态信息。但有时候需要保存一些状态,怎么办呢?
HTTP 为此引入了 Cookie。
浏览器遵循同源政策(scheme(协议)、host(主机)和port(端口)都相同则为同源)。
非同源站点有这样一些限制:
当浏览器向目标 URI 发 Ajax 请求时,只要当前 URL 和目标 URL 不同源,则产生跨域,被称为跨域请求。
CORS 其实是 W3C 的一个标准,全称是跨域资源共享。它需要浏览器和服务器的共同支持,服务器需要附加特定的响应头。
浏览器根据请求方法和请求头的特定字段,将请求做了一下分类,具体来说规则是这样,凡是满足下面条件的属于简单请求:
请求方法为 GET、POST 或者 HEAD
请求头的取值范围: Accept、Accept-Language、Content-Language、Content-Type(只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)
浏览器画了这样一个圈,在这个圈里面的就是简单请求, 圈外面的就是非简单请求,然后针对这两种不同的请求进行不同的处理。
Nginx 是一种高性能的反向代理服务器,相当于一个中间跳板,可以用来轻松解决跨域问题。
正向代理帮助客户端访问客户端自己访问不到的服务器,然后将结果返回给客户端。
反向代理拿到客户端的请求,将请求转发给其他的服务器,主要的场景是维持服务器集群的负载均衡,换句话说,反向代理帮其它的服务器拿到请求,然后选择一个合适的服务器,将请求转交给它。
性能的提升主要在于两点:
解决队头阻塞问题。
当然还有一些颠覆性的功能实现:
浏览器使用一种流式处理的方法,只需要一次绘制操作就可以布局所有的元素。
当浏览器接收到服务器响应来的HTML文档后,会遍历文档节点,生成DOM树。当前节点的所有子节点都构建好后,才会去构建当前节点的下一个兄弟节点。
需要注意:
display: none
的元素也会在DOM树中script
标签也会在DOM树中这个算法分为两个阶段:
对应的两个过程就是词法分析和语法分析。
标记化算法:这个算法输入为HTML文本,输出为HTML标记,也成为标记生成器。
建树算法:标记生成器会把每个标记的信息发送给建树器。建树器接收到相应的标记时,会创建对应的 DOM 对象。
浏览器是无法直接识别 CSS 样式文本的,因此浏览器会解析CSS文件并生成CSSOM,每个CSS文件都被分析成一个StyleSheet对象,每个对象都包含CSS规则。CSS规则对象包含对应于CSS语法的选择器和声明对象以及其他对象。
样式已经被格式化和标准化,接下来就可以计算每个节点的具体样式信息了。
主要就是两个规则: 继承和层叠。
每个子节点都会默认继承父节点的样式属性,如果父节点中没有找到,就会采用浏览器默认样式。
所有的样式值会被挂在到window.getComputedStyle
当中,也就是可以通过JS来获取计算后的样式。
需要注意:
现在已经生成了DOM树和DOM样式,接下来要做的就是通过浏览器的布局系统确定元素的位置,也就是要生成一棵布局树(Layout Tree)。
大致工作如下:
需要注意:
display: none
的元素不在Render Tree中visibility: hidden
的元素在Render Tree中接下来就来拆解下一个过程——渲染。
分为以下几个步骤:
浏览器在构建完布局树之后,还会对特定的节点进行分层,构建一棵图层树(Layer Tree)。目的是为了处理一些复杂的场景,比如3D动画如何呈现出变换效果,当元素含有层叠上下文时如何控制显示和隐藏等等。
一般情况下,节点的图层会默认属于父亲节点的图层(这些图层也称为合成层)。那什么时候会提升为一个单独的合成层呢?
有两种情况需要分别讨论,一种是显式合成,一种是隐式合成。
一、 拥有层叠上下文的节点。
HTML根元素本身就具有层叠上下文。
普通元素设置position不为static并且设置了z-index属性,会产生层叠上下文。
元素的 opacity 值不是 1
元素的 transform 值不是 none
二、需要剪裁的地方。
如果容器出现了滚动条,那么滚动条会被单独提升为一个图层。
简单来说就是层叠等级低的节点被提升为单独的图层之后,那么所有层叠等级比它高的节点都会成为一个单独的图层。
值得注意的是,当需要repaint时,只需要repaint本身,而不会影响到其他的层。
接下来渲染引擎会将图层的绘制拆分成一个个绘制指令,比如先画背景、再描绘边框......然后将这些指令按顺序组合成一个待绘制列表,相当于给后面的绘制操作做了一波计划。
现在开始绘制操作,实际上在渲染进程中绘制操作是由专门的线程来完成的,这个线程叫合成线程。
绘制列表准备好了之后,渲染进程的主线程会给合成线程发送commit消息,把绘制列表提交给合成线程。然后合成线程会选择视口附近的图块,把它交给栅格化线程池生成位图。
栅格化操作完成后,合成线程会生成一个绘制命令,即"DrawQuad",并发送给浏览器进程。
浏览器进程中的viz组件接收到这个命令,根据这个命令,把页面内容绘制到内存,也就是生成了页面,然后把这部分内存发送给显卡。
渲染层合并,由上一步可知,对页面中 DOM 元素的绘制是在多个层上进行的。在每个层上完成绘制过程之后,浏览器会将所有层按照合理的顺序合并成一个图层,然后显示在屏幕上。
默认只有一个复合图层,所有的DOM节点都是在这个复合图层下,如果开启了硬件加速功能,可以将某个节点变成复合图层。复合图层之间的绘制互不干扰,由GPU直接控制。
这里讨论的是 WebKit,描述的是 Chrome 的实现细节。
Chrome 拥有两套不同的渲染路径(rendering path):硬件加速路径和旧软件路径(older software path)
Chrome 中有不同类型的层: RenderLayer(渲染图层)和GraphicsLayer(复合图层),只有 GraphicsLayer 是作为纹理(texture)上传给GPU的。
渲染图层,是页面普通的文档流。我们虽然可以通过绝对定位,相对定位,浮动定位脱离文档流,但它仍然属于默认复合层,共用同一个绘图上下文对象(GraphicsContext)。
复合图层,又称图形层。它会单独分配系统资源,每个复合图层都有一个独立的绘图上下文对象(GraphicsContext)。(当然也会脱离普通文档流,这样一来,不管这个复合图层中怎么变化,也不会影响默认复合层里的回流重绘)
某些特殊的渲染层会被提升为复合成层(Compositing Layers),复合图层拥有单独的 GraphicsLayer,而其他不是复合图层的渲染层,则和其第一个拥有 GraphicsLayer 父层共用一个。
硬件加速会使页面流畅。
一个元素开启硬件加速后会变成合成层,可以独立于普通文档流中,改动后可以避免整个页面重绘,提升性能。
关键渲染路径是指浏览器从最初接收请求来的HTML、CSS、javascript等资源,然后解析、构建树、渲染布局、绘制,最后呈现给用户能看到的界面这整个过程。
用户看到页面实际上可以分为两个阶段:页面内容加载完成和页面资源加载完成,分别对应于DOMContentLoaded和Load。
DOMContentLoaded 事件触发时,初始的 HTML 文档被完全加载和解析完成之后,无需等待样式表、图像完全加载。
Load 事件触发时,页面上所有的DOM,样式表,脚本,图片都已加载完成。
JS可以操作DOM来修改DOM结构,可以操作CSSOM来修改节点样式,这就导致了浏览器在遇到<script>标签时,DOM构建将暂停,直至脚本完成执行,然后继续构建DOM。如果脚本是外部的,会等待脚本下载完毕,再继续解析文档。现在可以在script标签上增加属性defer或者async。脚本解析会将脚本中改变DOM和CSS的地方分别解析出来,追加到DOM树和CSSOM规则树上。
每次去执行JavaScript脚本都会严重地阻塞DOM树的构建,如果JavaScript脚本还操作了CSSOM,而正好这个CSSOM还没有下载和构建,浏览器甚至会延迟脚本执行和构建DOM,直至完成其CSSOM的下载和构建。所以,script标签的位置很重要。
JS阻塞了构建DOM树,也阻塞了其后的构建CSSOM规则树,整个解析进程必须等待JS的执行完成才能够继续,这就是所谓的JS阻塞页面。
由于CSSOM负责存储渲染信息,浏览器就必须保证在合成渲染树之前,CSSOM是完备的,这种完备是指所有的CSS(内联、内部和外部)都已经下载完,并解析完,只有CSSOM和DOM的解析完全结束,浏览器才会进入下一步的渲染,这就是CSS阻塞渲染。
CSS阻塞渲染意味着,在CSSOM完备前,页面将一直处理白屏状态,这就是为什么样式放在head中,仅仅是为了更快的解析CSS,保证更快的首次渲染。
需要注意的是,即便你没有给页面任何的样式声明,CSSOM依然会生成,默认生成的CSSOM自带浏览器默认样式。
当解析HTML的时候,会把新来的元素插入DOM树里面,同时去查找CSS,然后把对应的样式规则应用到元素上,查找样式表是按照从右到左的顺序去匹配的。
当浏览器发现布局发生了变化,这个时候就需要倒回去重新渲染,这个回退的过程叫reflow。
reflow会从html这个root frame开始递归往下,依次计算所有的结点几何尺寸和位置,以确认是渲染树的一部分发生变化还是整个渲染树。
reflow几乎是无法避免的,因为只要用户进行交互操作,就势必会发生页面的一部分的重新渲染,且通常我们也无法预估浏览器到底会reflow哪一部分的代码,因为他们会相互影响。
repaint则是当我们改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸和位置没有发生改变。
需要注意的是,display:none
会触发reflow,而visibility: hidden
属性则只会触发repaint。
另外有些情况下,比如修改了元素的样式,浏览器并不会立刻reflow或repaint一次,而是会把这样的操作积攒一批,然后做一次reflow,这又叫异步reflow或增量异步reflow。
现代浏览器会对回流做优化,它会等到足够数量的变化发生,再做一次批处理回流。
reflow回流必定引起repaint重绘,重绘可以单独触发。
来源:
浏览器渲染原理与过程
浏览器解析
"html2canvas": "1.0.0-rc.1" 版本比较稳定,IOS 13,没有兼容问题
从本质上讲,所有Web应用都是一种运行在网页浏览器中的软件,这些软件的图形用户界面(Graphical User Interface,简称GUI)即为前端。
前端是GUI软件。
主要有两种:
注入API
拦截URL SCHEME。
注入 API 方式的主要原理是:通过 WebView 提供的接口,向 JavaScript 的 Context(window)中注入对象或者方法,让 JavaScript 调用时,直接执行相应的 Native 代码逻辑,达到 JavaScript 调用 Native 的目的。
拦截 URL SCHEME 的主要流程是:Web 端通过某种方式(例如 iframe.src)发送 URL Scheme 请求,之后 Native 拦截到请求并根据 URL SCHEME(包括所带的参数)进行相关操作。
将方法注册到Native中,从外部调用 JavaScript 中的方法, 方法必须在全局的 window 上。
罗列一下知识点
WKWebView 和 UIWebView
WKScriptMessageHandler(只适用于WKWebView,iOS8+)
IOS 8之前在 UIWebView 中使用 schema 方式
WKWebView的内存开销比UIWebView小很多
官方宣称的高达60fps的滚动刷新率以及内置手势
支持了更多的HTML5特性
有Safari相同的JavaScript引擎
提供常用的属性,如加载网页进度的estimatedProgress属性
WKWebview本身提供了API实现JS交互,不需要借助JavaScriptCore或者webJavaScriptBridge。使用WKUserContentController实现js native交互。简单的说就是先注册约定好的方法,然后再调用。
注册一个方法,调用以及注册好的方法。
性能优化不能只着眼于局部的代码,需要从端到端的业务场景建立体系来考虑。
正确地评估现状和建立指标是最关键的一步。
什么样的性能指标能更好地评估它的体验?
什么样的指标会影响业务价值呢?
重要指标:
页面加载性能,跟用户的流失率有非常强的关联性,而用户流失率,正是公司业务非常看重的指标。
网页的加载时间,不但跟体积有关系,还跟请求数有很大关系
涉及的并不仅是前端技术,有服务端、客户端、设计师团队,想做好性能优化,不能把自己限制在局部的视角,必须是整个业务一起考虑。
浏览器相关优化:
代码本身上的优化
React相关优化
Webpack相关优化
做好数据的采集和展示。
利用浏览器Performace API
。
之前的相关解决方案是:高阶组件、render props。
缺点是组件会形成“嵌套地狱”。
现在,React为共享状态逻辑提供了更好的原生途径。使用 Hook 从组件中提取状态逻辑,使得这些逻辑可以单独测试并复用。Hook 使你在无需修改组件结构的情况下复用状态逻辑。
起初很简单的组件,会逐渐被状态逻辑和副作用充斥。相关的代码被进行了拆分,而不相关的代码却被组合在一起,这样会导致逻辑混乱,很容易产生BUG。
为了解决这个问题,Hook 将组件中相互关联的部分拆分成更小的函数。
Hook 使你在非 class 的情况下可以使用更多的 React 特性。
Hook 就是 JavaScript 函数。更具体的来说Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。
答案是 React 靠的是 Hook 调用的顺序。
只要 Hook 的调用顺序在多次渲染之间保持一致,React 就能正确地将内部 state 和对应的 Hook 进行关联。
通过自定义 Hook,可以将组件逻辑提取到可重用的函数中。
自定义 Hook 必须以 “use” 开头吗?必须如此。这个约定非常重要。不遵循的话,由于无法判断某个函数是否包含对其内部 Hook 的调用,React 将无法自动检查你的 Hook 是否违反了 Hook 的规则。
用于更新 state。它接收一个新的 state 值并将组件的一次重新渲染加入队列。
函数式更新
惰性初始 state。
跳过 state 更新。
useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API。
与 componentDidMount 或 componentDidUpdate 不同,使用 useEffect 调度的 effect 不会阻塞浏览器更新屏幕,这让你的应用看起来响应更快。
React 会等待浏览器完成画面渲染之后才会延迟调用 useEffect,因此会使得额外操作很方便。
推荐把函数逻辑移动到你的 effect 内部。这样就能很容易的看出来你的 effect 使用了哪些 props 和 state。
当 effect 执行时,我们会创建一个闭包,并将 state 的值保存在该闭包当中。要解决这个问题,我们可以使用 setState 的函数式更新形式。它允许我们指定 state 该 如何 改变而不用引用 当前 state。
每个组件内部都有一个「记忆单元格」列表。它们只不过是我们用来存储一些数据的 JavaScript 对象。当你用 useState() 调用一个 Hook 的时候,它会读取当前的单元格(或在首次渲染时将其初始化),然后把指针移动到下一个。这就是多个 useState() 调用会得到各自独立的本地 state 的原因。
浏览器是多进程的,有一个主控进程,以及每一个tab页面都会新开一个进程(某些情况下多个tab会合并进程)。
进程可能包括主控进程,插件进程,GPU,tab页(浏览器内核)等等。
每一个tab页面可以看作是浏览器内核进程,然后这个进程是多线程的,它有几大类子线程
输入URL后,会进行解析(URL的本质就是统一资源定位符)
URL一般包括几大部分:
每次网络请求时都需要开辟单独的线程进行,譬如如果URL解析到http协议,就会新建一个网络线程去处理资源下载。
先检查强缓存,如果命中直接使用,否则进入下一步。
由于我们输入的是域名,而数据包是通过IP地址传给对方的。因此我们需要得到域名对应的IP地址。
大致流程:
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
http的本质就是tcp/ip请求,需要了解3次握手规则建立连接以及断开连接时的四次挥手。
tcp将http长报文划分为短报文,通过三次握手与服务端建立连接,进行可靠传输
客户端:hello,你是server么?
服务端:hello,我是server,你是client么
客户端:yes,我是client
需要通过三次握手,才能确认双方的接收与发送能力是否正常。建立连接成功后,接下来就正式传输数据。
然后,待到断开连接时,需要进行四次挥手(因为是全双工的,所以需要四次挥手)
主动方:我已经关闭了向你那边的主动通道了,只能被动接收了
被动方:收到通道关闭的信息
被动方:那我也告诉你,我这边向你的主动通道也关闭了
主动方:最后收到数据,之后双方无法通信
浏览器对同一域名下并发的tcp连接是有限制的(2-10个不等),Chrome 6个。
而且在http1.0中往往一个资源下载就需要对应一个tcp/ip请求,http2.0已经实现复用。
所以针对这个瓶颈,又出现了很多的资源优化方案。
其实就是一个概念: 从客户端发出http请求到服务器接收,中间会经过一系列的流程。
简括就是:
从应用层的发送http请求,到传输层通过三次握手建立tcp/ip连接,再到网络层的ip寻址,再到数据链路层的封装成帧,最后到物理层的利用物理介质传输。
现在TCP连接建立完毕,浏览器可以和服务器开始通信,即开始发送 HTTP 请求。浏览器发 HTTP 请求要携带三样东西: 请求行、请求头和请求体。
服务端在接收到请求时,内部会进行很多的处理。
对于大型的项目,由于并发访问量很大,所以往往一台服务器是吃不消的,所以一般会有若干台服务器组成一个集群,然后配合反向代理实现负载均衡。
用户发起的请求都指向调度服务器(反向代理服务器,譬如安装了nginx控制负载均衡),然后调度服务器根据实际的调度算法,分配不同的请求给对应集群中的服务器执行,然后调度器等待实际服务器的HTTP响应,并将它反馈给用户。
前后端交互时,http报文作为信息的载体
报文一般包括了:通用头部,请求/响应头部,请求/响应体
Request Url: 请求的web服务器地址
Request Method: 请求方式(Get、POST、OPTIONS、PUT、HEAD、DELETE、CONNECT、TRACE)
Status Code: 请求的返回状态码,如200代表成功
Remote Address: 请求的远程服务器地址(会转为IP)
200——表明该请求被成功地完成,所请求的资源发送回客户端
304——自从上次请求后,请求的网页未修改过,请客户端使用本地缓存
400——客户端请求有错(譬如可以是安全模块拦截)
401——请求未经授权
403——禁止访问(譬如可以是未登录时禁止)
404——资源未找到
500——服务器内部错误
503——服务不可用
cookie是浏览器的一种本地存储方式,一般用来帮助客户端和服务端通信的,常用来进行身份校验,结合服务端的session使用。
使用场景:
在登陆页面,用户登陆了
此时,服务端会生成一个session,session中有对于用户的信息(如用户名、密码等)
然后会有一个sessionid(相当于是服务端的这个session对应的key)
然后服务端在登录页面中写入cookie,值就是:jsessionid=xxx
然后浏览器本地就有这个cookie了,以后访问同域名下的页面时,自动带上cookie,自动检验,在有效时间内无需二次登陆。
http的下一代规范
http2.0与http1.0的显著不同点:
http2.0的一些特性:
https就是安全版本的http
https与http的区别就是: 在请求前,会建立ssl链接,确保接下来的通信都是加密的,无法被轻易截取
前后端的http交互中,使用缓存能很大程度上的提升效率,而且基本上对性能有要求的前端项目都是必用缓存的
缓存可以简单的划分成两种类型:强缓存(200 from cache)与协商缓存(304)
区别简述如下:
强缓存(200 from cache)时,浏览器如果判断本地缓存未过期,就直接使用,无需发起http请求
协商缓存(304)时,浏览器会向服务端发起http请求,然后服务端告诉浏览器文件未改变,让浏览器使用本地缓存
对于协商缓存,使用Ctrl + F5强制刷新可以使得缓存无效
对于强缓存,在未过期时,必须更新资源路径才能发起新的请求(更改了路径相当于是另一个资源了,这也是前端工程化中常用到的技巧)
通过不同的http头部控制区分强缓存和协商缓存。
属于强缓存控制的:
(http1.1)Cache-Control/Max-Age
(http1.0)Pragma/Expires
属于协商缓存控制的:
(http1.1)If-None-Match/E-tag
(http1.0)If-Modified-Since/Last-Modified
跨域资源共享 CORS 详解
ajax出现请求跨域错误问题,主要原因就是因为浏览器的“同源策略”。
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求。
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type(只限于三个值application/x-www-form-urlencoded、 multipart/form-data、text/plain)
凡是不同时满足上面两个条件,就属于非简单请求。
get和post虽然本质都是tcp/ip,但两者除了在http层面外,在tcp/ip层面也有区别。
get会产生一个tcp数据包,post两个
具体就是:
第一种现象:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 404
出现这种情况的原因如下:
本次ajax请求是“非简单请求”,所以请求前会发送一次预检请求(OPTIONS)
服务器端后台接口没有允许OPTIONS请求,导致无法找到对应接口地址
解决方案: 后端允许options请求
第二种现象:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 405
这种现象和第一种有区别,这种情况下,后台方法允许OPTIONS请求,但是一些配置文件中(如安全配置),阻止了OPTIONS请求,才会导致这个现象
解决方案: 后端关闭对应的安全配置
第三种现象:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且status 200
这种现象和第一种和第二种有区别,这种情况下,服务器端后台允许OPTIONS请求,并且接口也允许OPTIONS请求,但是头部匹配时出现不匹配现象
比如origin头部检查不匹配,比如少了一些头部的支持(如常见的X-Requested-With头部),然后服务端就会将response返回给前端,前端检测到这个后就触发XHR.onerror,导致前端控制台报错
解决方案: 后端增加对应的头部支持
第四种现象:heade contains multiple values '*,*'
表现现象是,后台响应的http头部信息有两个Access-Control-Allow-Origin:*
解决方案:
建议删除代码中手动添加的*,只用项目配置中的即可
建议删除IIS下的配置*,只用项目配置中的即可
一般ajax跨域解决就是通过JSONP解决或者CORS解决,如以下:(注意,现在已经几乎不会再使用JSONP了,所以JSONP了解下即可)
实际项目中,后端应该如何配置以解决问题(因为大量项目实践都是由后端进行解决的)
来源: 页面加载的过程
CSS 世界的诞生就是为图文信息展示服务的
文档流
一套规则,决定元素按照什么机制进行布局。
内联盒模型
内容区域(content area)、内联盒子(inline box)、行框盒子(line box)、包含盒子(containing box)
containing box
替换元素img的样式content属性和src有一样的效果
三无准则
“无宽度,无图片,无浮动”
表现为“外部尺寸”的块级元素一旦设置了宽度,流动性就丢失了。
width
width作用于content-box 。
宽度分离,padding-box,border-box
box-sizing盒尺寸,决定width作用于哪个box
margin-box???
height
普通文档流中的元素,百分比高度值要想起作用, 其父级必须有一个可以生效的高度值。
max-width
!important 比直接在元素的 style 属性中设置 CSS 声明还要高,但是 max-width 会覆盖 width,超越!important
max-height默认值是auto,auto无法和具体值进行换算,可以设置具体指和一个更大的值制作动画
padding
给内联元素设置padding, 对视觉层和布局层具有双重影响,添加一个背景颜色可以看出来,所有类似“垂直方向 padding 对内联元素没有作用”的说法是不正确的。
Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:
当拿到一段 JavaScript 代码时,浏览器或者 Node 环境首先要做的就是,传递给 JavaScript 引擎,并且要求它去执行。
在 ES3 和更早的版本中,JavaScript 本身还没有异步执行代码的能力,这也就意味着,宿主环境传递给 JavaScript 引擎一段代码,引擎就把代码直接顺次执行了,这个任务也就是宿主发起的任务。
但是,在 ES5 之后,JavaScript 引入了 Promise,这样,不需要浏览器的安排,JavaScript 引擎本身也可以发起任务了。采纳 JSC 引擎的术语,我们把宿主发起的任务称为宏观任务,把 JavaScript 引擎发起的任务称为微观任务。
每次的执行过程,其实都是一个宏观任务。我们可以大概理解:宏观任务的队列就相当于事件循环。
在宏观任务中,JavaScript 的 Promise 还会产生异步代码,JavaScript 必须保证这些异步代码在一个宏观任务中完成,因此,每个宏观任务中又包含了一个微观任务队列。
宿主环境发起的任务。
JS引擎发起的任务。
Promise 是 JavaScript 语言提供的一种标准化的异步管理方式,它的总体**是,需要进行 io、等待或者其它异步操作的函数,不返回真实结果,而返回一个“承诺”,函数的调用方可以在合适的时机,选择等待这个承诺兑现(通过 Promise 的 then 方法的回调)。
Promise本身是同步的立即执行函数 new Promise直接执行。then后面的函数被分发到微任务Event Queue中。
如果俩个微任务的优先级相同,那么任务队列自上而下执行,但是Promise的优先级高于async,所以先执行Promise后面的回调函数。
async/await 是 ES2016 新加入的特性。
async 函数必定返回 Promise,我们把所有返回 Promise 的函数都可以认为是异步函数。
async 函数是一种特殊语法,特征是在 function 关键字之前加上 async 关键字,这样,就定义了一个 async 函数,我们可以在其中使用 await 来等待一个 Promise。
async 函数强大之处在于,它是可以嵌套的。我们在定义了一批原子操作的情况下,可以利用 async 函数组合出新的 async 函数。
此外,generator/iterator 也常常被跟异步一起来讲,我们必须说明 generator/iterator 并非异步代码,只是在缺少 async/await 的时候,一些框架(最著名的要数 co)使用这样的特性来模拟 async/await。
但是 generator 并非被设计成实现异步,所以有了 async/await 之后,generator/iterator 来模拟异步的方法应该被废弃。
这段代码什么意思?
setTimeout(function() {
console.log('执行')
}, 3000)
解释是::3秒后,setTimeout里的函数被会推入Event Queue
,而Event Queue里的任务,只有在主线程空闲时才会执行。
所以只有满足这两个条件: (1)3秒后;(2)主线程空闲。才会执行该函数。
如果主线程执行内容很多,执行时间超过3秒,假如执行了4秒,那么这个函数只能在4秒后执行。
JavaScript 标准把一段代码(包括函数),执行所需的所有信息定义为:“执行上下文”。
包含三个部分:
在 ES5 中,改进了命名方式,把执行上下文最初的三个部分改为下面这个样子:
在 ES2018 中,执行上下文又变成了这个样子,this 值被归入 lexical environment,但是增加了不少内容。
全局上下文中的变量对象就是全局对象。
函数上下文中,我们用活动对象(activation object, AO)来表示变量对象。
执行上下文的代码会分成两个阶段进行处理:分析和执行,我们也可以叫做:
变量对象会包括:
先梳理JS引擎编译执行过程大致的三个阶段
在第一步里有个词法分析,它用来登记变量声明、函数声明、函数声明的形参,后续代码执行的时候就知道去哪里拿变量的值和函数了,这个登记的地方就是Lexical Environment(词法环境)。
维基百科上面闭包的定义:闭包是一个record,它存储了一个函数和它的环境,这个环境存储了该函数的自由变量,JS的函数完全符合这个定义,所以跟闭包对应的概念就是“函数”。
最新版本对SVG处理有兼容问题,使用"html2canvas": "^1.0.0-rc.1" 可以解决。
它是什么?
它有什么作用?
它接受哪些参数?这些参数都有什么作用?
它返回什么?
它是怎么实现的?
拥有层叠上下文属性的元素会生成一个新的层叠上下文对象,每个层叠上下文对象都是一个渲染图层,渲染图层与复合图层是不同的概念,渲染图层更像是一个纯二维的概念,无论其怎么层叠覆盖最终都归依于根层叠上下文。而复合图层则完全脱离根层叠上下文,相当于开辟新的位面。
让HTML元素在2D平面堆叠出3D的视觉效果,根据层叠规则将哪个元素置于视觉最近处,哪个次之,以此类推。
层叠等级的比较只有在当前层叠上下文元素中才有意义。不同层叠上下文中比较层叠等级是没有意义的。
不需要发送请求。
通过相应的字段来进行检查,HTTP/1.0使用Expires,HTTP/1.1使用Cache-Control。
Expires即过期时间。如果服务器的时间和浏览器的时间不一致,那服务器返回的这个过期时间可能就是不准确的。因此这种方式很快在后来的HTTP1.1版本中被抛弃了。
Cache-Control: max-age=3600,代表这个响应返回后在 3600 秒,也就是一个小时之内可以直接使用缓存。
强缓存失效之后,浏览器在请求头中携带相应的缓存tag来向服务器发请求,由服务器根据这个tag,来决定是否使用缓存,这就是协商缓存。
这样的缓存tag分为两种: Last-Modified 和 ETag。
Last-Modified:即最后修改时间。
ETag:是服务器根据当前文件的内容,给文件生成的唯一标识,只要里面的内容有改动,这个值就会变。
当强缓存命中或者协商缓存中服务器返回304的时候,我们直接从缓存中获取资源。那这些资源究竟缓存在什么位置呢?
浏览器中的缓存位置一共有四种,按优先级从高到低排列分别是:
首先通过Cache-Control
验证强缓存是否可用。
Cookie 最开始被设计出来其实并不是来做本地存储的,而是为了弥补HTTP在状态管理上的不足。
因为HTTP 协议是一个无状态协议,所以Cookie 的作用就是用来做状态存储的。
特点和缺陷:
特点:
localStorage有较大容量和持久特性,可以利用localStorage存储一些内容稳定的资源。
sessionStorage和localStorage基本相同,只有一个本质的区别,sessionStorage只是会话级别的存储,并不是持久化存储。会话结束,也就是页面关闭,这部分sessionStorage就不复存在了。
IndexedDB是运行在浏览器中的非关系型数据库, 本质上是数据库,绝不是和刚才WebStorage的 5M 一个量级,理论上这个容量是没有上限的。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.