前端面试题汇总
HTTP/HTML/浏览器
http和https
基本概念:
-
http 超文本传输协议,是一个客户端和服务端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议。
-
https 是以安全为目标的HTTP通道,简单来说,是HTTP的安全版,即HTTP下加入SSL层。
区别:
- http传输数据没有加密,是明文传输。
- https需要ca证书,费用高。
tcp三次握手
1. 第一次握手,服务器确认自己可以收到客户端的消息
2. 客户端确定服务端收到了发送的消息,并且确定自己可以收到服务器的消息
3. 服务器确定客户端收到了自己的消息
TCP和UDP区别
1. TCP是面向链接的,UDP是无连接的(即发送数据前不需要建立链接)。
2. TCP服务可靠,UDP不可靠,可能丢失信息。
3. TCP面向字节流,UDP面向报文。
4. TCP是一对一,UDP可以一对多。
WebSocket
- 支持持久性链接
- 链接完成,服务器端可以主动推送数据到客户端
web Quality(无障碍)
- 因为个别浏览器功能不全面,从而导致内容缺失。
- 解决方法:
- 优雅降级
- 渐次增强
- 使用alt属性。(图片加载不出来时显示文字)
Cookie、sessionStorage、localStorage
- 相同点: 都是保存在浏览器端,并且都是同源的。
- 不同点:
- cookie:会在http请求时自动携带,在浏览器和服务器间来回传递。存储大小很小(4K左右)
- sessionStorage:保存在本地,当关闭浏览器,sessionStorage会失效(销毁)。
- localStorage: 保存在本地,一直存在。
web worker
- 在html之中,如果执行脚本,在加载引入的js时会造成页面阻塞(即页面内容不加载,专心加载js,从而导致白屏)。
- web worker试运行在后台的js,独立于其他脚本,不会影响页面性能。
HTML语义化
- 语义化标签没有实际含义
- 语义化标签提高代码结构的阅读性
- 比如:nav表示导航条,header,footer等。
iframe
- iframe时包含一个文档的内敛框架,有些类似与组件化思想。
- 可以用iframe解决跨域问题
- 缺点:
- 会阻塞主页面的onload事件
- 搜索引擎无法解读,不利于SEO(优化)
- 影响性能
Doctype严格模式和混杂模式
- 严格模式: 排版和JS 运作模式是 以该浏览器支持的最高标准运行。
- 混杂模式:标准比较松懈。向后兼容。
http常用返回的状态码
- 300 Multiple Choices 多种选择。请求的资源包括多个位置。
- 301 Moved Permanently 永久移动。请求的资源已经被永久移动到新的URL。
- 302 found 临时移动。与301相同,但资源只是临时被移动。
- 303 See Other 查看其它地址。和301,302一样。使用GET或者POST请求查看。
- 304 Not Modified 未修改。所请求的资源未修改。
- 305 use proxy 使用代理。所使用的资源必须通过代理访问。
- 306 unused 已经被废弃了。
- 307 Temporary Redirect 临时重定向。和302类似,使用GET请求重定向。
- 400 Bad Request 客户端请求的语法错误,服务器无法理解。 产生原因:1. 语义有误,2.请求参数有误。
- 401 Unauthorized 请求要求用户的身份验证
- 402 Payment Required 保留,将来使用
- 403 Forbidden 服务器理解请求,但是拒绝执行。 产生原因:权限不够
- 404 Not Found 找不到地址 产生原因:请求的地址出错。
- 405 Method Not Allowed 客户端请求的方法被禁止。 产生原因:请求方法不对(应该用GET,你用POST)
- 406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求. 产生原因:服务器返回的数据客户端无法接受。
- 407 Proxy Authentication Required 请求要求代理的身份认证
- 408 Request Time-out 服务器等待客户端发送的请求时间过长,超时
- 409 ~ 417 不常用,有意可以自行了解
- 500 Internal Server Error 服务器内部错误
- 501 Not Implemented 服务器不支持请求的功能
- 502Bad Gateway 从远程服务器接收到了一个无效的响应
- 503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
- 504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
- 505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理
http常用请求头
| 协议头 | 说明 |
|---|---|
| accept | 可接受的相应内容类型(content-Type) |
| accept-Charset | 可接受的字符集 |
| accept-encoding | 可接受的响应内容的编码方式 |
| accept-Language | 可接受的响应内容语言列表 |
| accept-Datetime | 可接受的按照时间来响应内容版本 |
| Authorization | 用于表示HTTP协议中需要认证资源的认证信息 |
| Cache-Control | 用于指定请求/回复中是否使用缓存机制 |
| connection | 客户端想要优先使用的链接类型 |
| Cookie | 由之前服务器通过Set-Cookie(见下文)设置的一个HTTP协议Cookie |
| content-Length | 以8进制表示的请求体长度 |
| Content-MD5 | 请求体内容的二进制MD5散列值,以Base64编码的结果 |
| Content-Type | 请求体的MIME类型(用于POST和PUT) |
| Date | 发送该消息时的日期和时间 |
| Expect | 表示客户端要求服务器做出特定的行为 |
| From | 发起此请求的用户的邮件地址 |
| Host | 表示服务器的域名以及服务器所监听的端口号 |
| Max-Forwards | 限制该消息可以被代理以及网关转发的次数 |
| Origin | 发起一个针对跨域资源共享的请求 |
| Proxy-Authorization | 用于向代理进行认证的认证信息 |
| Referer | 表示浏览器访问的前一个页面 |
| TE | 浏览器与其接受的传输时的编码方式 |
| User-Agent | 浏览器的身份标识字符串 |
| Upgrade | 要求服务器升级到一个高版本协议 |
| Via | 告诉服务器,这个请求是由哪些代理发出的 |
| Warning | 一个一般性的警告,表示实体内容可能存在错误 |
强缓存,协商缓存
- 缓存分为两种:强缓存和协商缓存,根据相应的header内容决定。
| 获取资源方式 | 状态码 | 发送请求到服务器 | |
|---|---|---|---|
| 强缓存 | 从缓存中获取内容 | 200(from cache) | 否,直接从缓存中获取 |
| 协商缓存 | 从缓存中获取 | 304(not modified) | 先访问服务器,进行资源比对,如果本地缓存和服务器内容一样,则调用本地缓存 |
前端优化
| 方法 | 具体解析 | |
|---|---|---|
| 降低请求量 | 合并资源 | 精灵图 |
| 减少HTTP请求 | 强缓存,协商缓存 | |
| minify/zip压缩 | 压缩图片,压缩代码 | |
| webP | 压缩图片 | |
| lazyLoad | 懒加载 | |
| 加快请求速度 | 预解析DNS | 浏览网页时,浏览器在加载网页时对网页中的域名进行解析缓存,这样在单击当前网页中的连接时就无需进行DNS的解析,减少用户等待时间,提高用户体验。 |
| 减少域名数 | ||
| 并行加载 | 并发加载,谷歌最多支持6个。 | |
| CDN分发 | CDN全称是Content Delivery Network,即内容分发网络 | |
| 缓存 | HTTP协议缓存请求 | 通过请求头设置cookie。 |
| 离线缓存mainfest | 协商缓存,请求mainfest内容时,本地缓存先和网上内容进行比对,如果不同,请求网上内容,如果相同,则直接使用本地。 | |
| 离线数据缓存localStorage | 强缓存,将信息保存再本地,需要时不和网上进行比对直接进行使用。 | |
| 渲染 | JS/CSS优化 | 优化代码。 |
| 加载顺序 | js写在底部,css写在头部,先外链,再本页。 | |
| 服务端渲染 | vue,react等MVVM。 | |
| pipeline | pipeline是一套jenkins官方提供的插件,它可以用来在jenkins中实现和集成连续交付。 |
GET和POST的区别
| GET | POST | |
|---|---|---|
| 传递方式 | 通过url(?id=1) | 放在request body中 |
| 传递长度 | 有长度限制 | 没有长度限制 |
| 安全性 | 参数暴露在url | 不暴露 |
| 编码方式 | 只能进行url编码 | 多种编码方式 |
| 请求参数 | 保留在浏览历史记录里 | 不会被保存 |
| TCP数据包 | 产生一个TCP数据包 | 产生两个TCP数据包 |
从输入URL到页面加载的过程
在地址栏输入一个URL,到这个页面呈现,中间的过程(简略)
1. DNS解析
2. TCP连接
3. 发送http请求
4. 服务端处理http请求并返回报文
5. 浏览器解析渲染页面
6. 连接结束
具体过程(将依次拓展)
1.从浏览器接受url到开启网络请求线程(可展开浏览器的机制以及进程与线程之间的关系)
2. 开启网络线程到发出一个完整的http请求(涉及dns查询,tcp/ip请求,五层因特网协议栈等)
3.从服务器接收到请求到对应后台接收到请求(负载均衡吗,安全拦截以及后台内部的处理)
4. 后台和前台的http交互(包括http头部、响应码、报文结构、cookie等)
5. 单独拎出来的缓存问题,http的缓存(http缓存头部,etag,catch-control)
6. 浏览器接收到http数据包后的解析流程(解析html词法分析然后解析成dom树、解析css生成css规则书、合并成render树,然后layout、painting渲染,、复合图层、GPU绘制、外联资源的处理、loaded和domcontentload等)
7.css的可视化格式模型(元素的渲染规则,如包含块,BFC,IFC等概念)
8.JS引擎解析过程(JS的解释阶段,预处理阶段,执行阶段生成执行上下文,VO,作用域链,回收机制等等)
9.其他(可以拓展不同的知识模块,如跨域,web安全,hybrid模式等)
DNS查询得到IP
如果输入的是域名,需要进行dns解析成IP,大致流程:
- 如果浏览器有缓存,直接使用浏览器缓存,否则使用本机缓存,再没有的话就是用host
- 如果本地没有的话,就向dns域名服务器查询,查询到对应的ip
注意,域名查询是有可能是经过了cdn调度器的(如果有cdn存储功能的话)
而且,需要知道dns解析是很耗时的,因此如果解析域名过多,会让收评加载变的过慢,可以考虑dns-prefetch优化
浏览器接收到http数据包后的解析流程
1.解析html词法分析然后解析成dom树
2.解析css生成css规则书
3.合并成render树
4.layout、painting渲染、
5.复合图层、GPU绘制、
6.外联资源的处理、loaded和domcontentload等
多进程的浏览器
浏览器是多进程的,有一个主控进程,以及每一个tab页面都会新开一个进程(某些情况下多个tab会合并进程)
进程跨域包括主控进程,插件进程,GPU,tab页(浏览器内核)等等
- Browser进程:浏览器的主进程(负责协调、主控),只有一个
- 第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建
- GPU进程:最多一个,用于3D绘制
- 浏览器渲染进程(内核):默认每一个tab页一个进程,互不影响,控制页面渲染,脚本执行,事件处理等
多线程的浏览器内核
每一个tab页面可以看作是浏览器内核进程,然后这个进程是多线程的,他有几大类子线程
- GUI线程
- JS引擎线程
- 事件触发线程
- 定时器线程
- 网络请求线程
解析URL
输入URL后,会进行解析(URL的本质就是统一资源定位符)
URL一版包括几大部分:
- protocol,协议头,譬如http,ftp等
- host,主机域名或ip地址
- prot,端口号
- path,目录路径
- query,即查询参数
- fragment,即#
- 后面的hash值,一般用来定位到某个位置
网络请求都是单独的线程
每次网络请求时都需要开辟单独的线程进行,譬如如果URL解析到http协议,就会新建一个网络线程去处理资源下载
因此,浏览器会根据解析出的协议,开辟一个网络线程,前往请求资源(这里,暂时理解为时浏览器内核开辟)
dns-prefetch
-
什么是DNS Prefetch
- DNS Prefetch 是一种DNS预解析技术。当你浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在你单击当前网页中的链接时就无需进行DNS的解析,减少用户等待时间,提高用户体验。
- 目前每次DNS解析,通常在200ms以下。针对DNS解析耗时问题,一些浏览器通过DNS Prefetch来提高访问的流畅性。
-
如何设置dns-prefetch
-
DNS Prefetch应该尽量放在网页的前面,推荐放在后面。
-
<meta http-equiv="x-dns-prefetch-control" content="on"> <link rel="dns-prefetch" href="//www.zhix.net"> <link rel="dns-prefetch" href="//api.share.zhix.net"> <link rel="dns-prefetch" href="//bdimg.share.zhix.net"> -
<!--如果不确定是http还是https连接的话建议如下写法 --> <link rel="dns-prefetch" href="//renpengpeng.com" />
-
tcp/ip请求
http的本质就是tcp/ip请求
tcp将http长报文划分为短报文,通过三次握手与服务端建立连接,进行可靠传输
三次握手的步骤:(抽象派)
客户端:hello,你是server嘛?
服务端:heool,我是server,你是client嘛?
客户端:yes,我时client
建立链接成功后,接下来就正式传输数据
然后,待断开链接时,需要进行四次挥手(因为时全双工的,所以需要四次挥手)
四次挥手的步骤:(抽象派)
主动方:我以及关闭了向你那边的主动通道,只能被动接收了
被动方:收到通道关闭的信息
被动方:那我也告诉你,我这边向你的主动通道也关闭了
主动方:最后收到数据,双方无法通信
tcp/ip的并发限制
- 浏览器对同一域名下并发的tcp链接时有限制的(2-10个不等)
- 而且在http1.0中往往一个资源下载就对应一个tcp/ip请求
- 所以针对这个瓶颈,又出现了很多资源优化方案
五层因特网协议栈
从客户端发出http请求到浏览器接收,中间会经过一系列的流程。
简括就是:
- 从应用层的发送http请求,到传输层通过三次握手简历tcp/ip链接,再到网络层的ip寻址,再到数据链路层的封装成帧,最后到物理层的利用物理介质传输。
从服务器接收到请求到对应后台接收到请求
负载均衡
-
对于大型项目,由于并发访问量很大,所以往往一台服务其是吃不消的,所以一版会有若干台服务其组成一个集群,然后配合反向代理实现负载均衡。
-
用户发起的请求都指向调度服务其(反向代理服务其,譬如安装了nginx控制负载均衡),然后调度服务器根据实际的调度算法,分配不同的请求给对应集群中的服务器执行,然后调度器等待实际服务器的HTTP响应,并将它反馈给用户
后台的处理
- 一般后台都是部署到容器里,所以一般为:
- 先是容器接收到请求(如tomcat)
- 然后对应容器中的后台程序接收到请求(如java程序)
- 然后就是后台会有自己的统一处理,处理完后响应结果
- 概括下:
- 一般有的后端是有统一的验证的,如安全拦截,跨域验证
- 如果这一步不符合规则,就直接返回了响应的http报文(如拒绝请求等)
- 当验证通过后,才会进入实际的后台代码,此时是程序接收到请求,然后执行
- 等程序执行完毕后,就会返回一个http相应包
- 将这个包从后端发送到前端,完成交互
后台和前台的http交互
http报文结构
- 报文结构一般包括了:通用头部,请求/响应头部,请求/响应体
通用头部
-
这也是开发人员见过的最多的信息,包括如下:
Request Url:请求的web服务器地址 Request Method:请求方式(Get,POST,OPTIONS,PUT,HEAD,DELETE,CONNECT,TRACE) Status Code:请求的返回状态码 Remote Address:请求的远程服务器地址(会转为IP) -
其中,Method的话分为两批次:
http1.0定义了三种请求方法:GET,POST和HEAD方法 http1.1定义了八种请求方法:GET,POST,HEAD,OPTIONS,PUT,DELETE,TRACE和CONNECT
gzip压缩
- 首先,明确gzip是一种压缩格式,需要浏览器支持才有效(一般浏览器都支持),而且gzip压缩效率很好(高达70%)
- gzip一般是由apache、tomcat等web服务器开启
浏览器多进程到JS答线程
浏览器内核
- 浏览器的渲染是多线程的:
- GUI渲染线程
- 负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
- 当界面需要重绘或者某种操作引发回流的时候,该线程就会执行。
- GUI渲染线程和js引起线程互斥。
- JS引擎线程
- 也成为JS内核,负责处理js脚本程序
- js引擎线程负责解析js脚本,运行代码
- js引擎一直等待着任务队列中人物的到来,然后加以处理,一个tab页中无论什么时候都只有一个js线程。
- GUI渲染和js引擎线程互斥。
- 事件触发线程
- 归属于浏览器而不是js引擎,用来控制事件循环(可以理解,js引擎自己都忙不过来,需要浏览器另开线程协助)
- 当js引擎执行代码块如setTimeOut时,(火来自浏览器内核的其他线程,如鼠标点击,AJAX异步请求等),会将对应任务添加到事件线程中
- 当对应的事件符合触发条件被触发的时候,该线程会把事件添加到待处理队列的队尾,等到js引擎的处理。
- 由于js的单线程关系,所以这些待处理队列中的事件都需要排队等待js引擎处理。
- 定时触发器线程
- 传说中setInterval与setTimeout所在线程
- 浏览器定时器并不是由javaScript引擎计数(js引擎单线程,如果处于阻塞状态就会影响计时器的准确)
- 因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待js引擎空闲后执行)
- 注意,W3c在HTML标准中规定,要求setTimeout中低于4ms的时间间隔算为4ms
- 异步http请求线程
-
在XML HttpRequest在连接后是通过浏览器新开一个线程请求
-
在检测到状态变更时,如果设置有回调函数,异步引擎就会产生状态变更事件,将这个回调再放入事件队列中,再由javaScript引擎执行。
-
梳理浏览器内核中线程之间的关系
GUI线程和JS引擎线程互斥
- 因为js是可以操作dom的,如果在修改这些元素属性的同时渲染界面(即js和ui线程同时运行),那么渲染线程前后获得的元素数据可能就不一致了。
- 因此为了防止渲染出现不可预期的结果,浏览器设置GUI渲染线程和JS引擎为互斥的关系,当JS引擎执行时GUI线程会被挂起
- GUI更新则会保存在一个队列中等到JS引擎线程空闲时立即执行
JS阻塞页面加载
- 从上述互斥可以推导出,如果JS执行时间过长,就会阻塞页面。
WebWork,JS的多线程
- 创建Woker时,JS引擎向浏览器申请开一个子线程(子线程是浏览器开的,完全受主线程控制,而且不能操作DOM)
- JS引擎线程与worker线程间通过特定的方式通信(postMessage线程 API,需要通过序列化对象来与线程交互特定的数据)
- 注意,JS是单线程的,这一点的本质并未改变
浏览器渲染流程
- 解析html建立dom树
- 解析css构建render树
- 布局render树(layout/reflow),负责各元素尺寸,位置的计算
- 绘制render树
- 进行合成场景并显示
load事件和DOMContentLoaded事件的先后
- 渲染完成之后会触发load事件,这里包括两部分,load和DOMContentLoaded。
- 当DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片。(比如如果有async加载的脚本就不一定完成)
- 当onload事件触发时,页面上所有的DOM,样式表,脚本,图片都已经加载完成了
- 所以,顺序是:DOMContentLoaded -> load
css加载是否会阻塞dom树渲染
- 这里说的是头部引入css的情况
- css是由单独的下载线程异步下载的
- css加载不会阻塞DOM树解析(异步加载时DOM照常构建)
- 但会阻塞render树渲染(渲染时需等css加载完毕,因为render树需要css信息)
普通图层和复合图层
- 浏览器渲染的图层一版分为两大类:普通图层和复合图层
- 首先,普通文档流内可以理解为一个复合图层(默认符合层,里面不管添加多少元素,其实都在同一个复合图层中)
- absolute布局等,虽然会脱离普通文档流,但仍属于默认复合层
- 可以通过硬件加速的方式,声明一个新的复合图层,他会单独分配资源
- GPU中,各个复合层是单独绘制的,所以互不影响,这也是为什么某些场景硬件加速效果一级棒。
如何变成复合图层
- 把该元素变成一个复合图层,就是传说中的硬件加速技术
- 常用方法为:translate3d,translzteZ
- opacity属性/过渡动画(需要动画执行的过程才会创建合成层,动画没有开始或结束后元素还会回到之前的状态)
- will-change属性(比较偏僻),一般配合opacity和translate使用(而且经测试,除了上述可以引发硬件加速的属性外,其他属性不会变成复合层)作用时提前告诉浏览器要变化,这样浏览器会开始做一些优化工作
- video,iframe,canvas,webgl等元素
- 其他,比如以前的flash插件
复合图层的作用
- 一般一个元素开启硬件加速后会变成复合图层,可以独立于普通文档流中,改动后可以避免整个页面重绘,提升性能
- 尽量不要大量的使用符合图层,否则资源消耗过度,页面反而更卡
从Event Loop谈JS的运行机制
- 执行一个宏任务
- 执行过程中遇到微任务,把它加到微任务的任务队列中
- 宏任务执行完毕,立即开始执行当前微任务队列中的所有微任务
- 当前宏任务执行完毕,开始检查渲染,任何GUI线程接管渲染
- 渲染完毕后,js线程继续接管,开始下一个宏任务
- PS:Promise的polyfill于官方版本的区别在于,官方版本中promise是微任务,polyfill是宏任务
nextTick
这个大佬讲的非常清晰。 温故而知新,浅析 Vue nextTick 原理 - 知乎 (zhihu.com)
CSS
css盒模型
- 简介:装页面上元素的矩形区域,包括IE盒子模型和标准的W3C盒子模型
- box-sizing:border-box,padding-box,content-box
- 标准盒子模型(content-box):width = content + padding + border
- IE盒子模型(border-box): width = content
- padding-box: width = content + padding
画一条0.5px的线
- 原因:0.5px的线在不同浏览器会有不同的体现。
- 方法实现: 1 meta viewport进行缩放
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
2 border-image的方式
将图片规定为包围 div 元素的边框
3 transform: scale()
同样是使用缩放
link标签和impot标签的区别
- link属于html标签,@import是css提供的
- 页面加载时,link会同时被加载,@import引用的css要等到页面加载结束后加载。
- link是html标签,没有兼容性。@import要IE5以上才能识别
- link方式权重高于@import
transition和animation的区别
他们大部分属性相同,都是随着时间改变元素的属性值。
- 区别: 1 transition需要触发一个事件才能改变属性(比如hover)。而animation不需要。 2 transition为2帧,animation是1帧。
Flex布局
flex是‘弹性布局’,用来为盒模型提供最大的灵活性。
- 使用方法
1 在父元素定义 display:flex。
2 在父元素可定义如下属性
- flex-direction: 决定主轴方向。
- flex-wrap: 决定换行规则。
- flex-flow : 是前两个的缩写。
- justify-content: 对齐方式
- align-items: 交叉轴上如何对齐。
- align-content: 多根轴线的对齐方式,如果项目只有一根轴线,则不起作用。
3 在子元素可定义如下属性 7. order: 定义项目的排序顺序,数值越小,排列越前。 8. flex-grow: 定义项目的放大比例,默认为0(即不放大)。(如果所有项目的此属性都是1,则等分剩余空间,如果有一个为2,则其占据的空间是其他项目占据的两倍) 9. flex-shrink: 定义项目的缩小比例,默认为1(即如果空间不足,该项目会缩小)。(如果所有项目都为1,则空间不足会等比例缩小。如果其中一个为0,则空间不足时,为0的项目不缩小。) 10. flex-basis: 定义在分配多余空间之前,项目占据的主轴空间。默认为auto(项目本来大小)。 11. flex: 是上三项的简写。 12. align-self: 允许当个项目与其他项目不一样的对齐方式。默认为auto。
BFC(块级格式化上下文,用于清除浮动,防止margin重叠等)
- 块级格式化上下文,是一个独立的渲染区域,并且有一定的布局规则。
- 直白的来说:BFC区域就是将区域内的浮动元素计入布局之中(比如解决高度坍塌)。
- 生成BFC的元素: 1 根元素或者其他包含它的元素 2 浮动元素(元素的float不为none) 3 绝对定位元素(元素position为absolute或fixed) 4 内联块(display:inline-block) 5 表格单元格(diaplay:table-cell,HTML表格单元格默认属性) 6 表格标题(diaplay: table-caption,HTML表格标题默认属性) 7 具有overflow且值不为visible的块元素 8 display: flow-root 9 column-span:all 应当总会创建一个格式化上下文,即便具有column-span:all 的元素并不被包裹在一个多列容器中。 10 一个块格式化上下文包括创建它的元素内部所有内容,除了被包换与创建新的块级格式化上下文的后代元素内的元素。
垂直居中的方法
- margin: auto
- display:table-cell;vertical-align:middle;
- flex布局
div{
display:flex;
justify-content:center;
align-items: center;
}
关于JS动画和css3动画的差异性
- 功能涵盖面上,js比css大
- 实现重构的难度,css3更简单。
- css3可以做到自然降级。
- css3动画有天然事件支持
- csss3有兼容问题
优雅降级和渐进增强
-
优雅降级 先适配高版本浏览器。而后针对低版本浏览器逐次降低配置需求,使其可以实现基本功能。
-
渐进增强 一开始针对低版本浏览器满足基本功能。而后根据浏览器版本的提升依次提高页面交互,效果等新功能。
块元素和行内元素
-
块元素 独占一行,并且有自动填满父元素,可以设置margin和padding以及高度和宽度
-
行元素 不会独占以上,weight和height会失效,垂直方向的padding和margin会失效。
-
img元素例外,他是行元素,但是它具有weight和height等属性。
多行元素的文本内容省略
display: -webkit-box;
-webkit-box-orient:vertical;
-webkit-line-clamp:3;
overflow:hidden;
visivility = hidden, opacity = 0, display:none区别
-
opacity = 0 设置透明度为全透明,隐身状态,但是依然存在,不会改变页面布局,可以触发绑定的事件。
-
visibility = hidden 把该元素隐藏起来,不改变页面布局,但是绑定的事件不会触发
-
display : none 相当于直接删掉该元素。改变页面布局,绑定事件失效。
外边距折叠问题
-
问题描述: 相邻元素的margin属性重叠。
-
示例: margin:20px;margin:30px; 如上,两个元素的margin分别是20和30.但是两个元素之间距离不是50(20+30);而是30(外边距重叠)。
-
折叠结果: 1 都为正数时,是他们之间较大的值。 2 都为负数时,是他们绝对值较大的。 3 一正一负,是他们相加的和。
position属性
- fixed(固定定位) 脱离文本流,定位位置是浏览器窗口固定位置(左上角)
- relative(相对定位) 不脱离文本流,定位位置是元素本来位置。
- absolute(绝对定位) 脱离文本流,定位位置为最近的设置定位的父元素。
- static(默认定位) 默认值,没有定位。
- inherit(继承) 继承父元素的position属性。
浮动消除
1. 使用带clear属性的空元素
在浮动元素后面使用一个空元素(div),在css之中赋予 `clear : both` 属性。
2. 使用css的overflow属性
将overflow的值设为hidden或者auto。
3. 给浮动元素的容器设置浮动
不推荐,这会使整体浮动。
css选择器和优先级
css优先级高低排序:!important > 行内样式>ID选择器 > class选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
重绘和重排
- 重排 dom属性的变化(width,height等)导致浏览器需要重新计算盒子模型的排布。
- 重绘 浏览器将受到影响的部分重新绘制在屏幕上。
- 引起重排重绘的原因:
- 添加删除可见的dom
- 元素尺寸位置的改变
- 浏览器页面初始化
- 浏览器窗口大小发生改变
- 减少重绘重排的方法:
- 使用css一次性修改属性
- 使用fragment
fragment(碎片)
所谓farment,类似于组件化。 在项目中,我们可以出现要重复添加子元素(比如ul里面要添加很多个li),如果for循环添加会不停的导致重排(重绘),所以使用fragment,先全部添加到这里,而后将fragment一次性添加到ul里。
JS
前端的事件流
- 含义:从页面中接收时间的顺序。
- 三个阶段
- 事件捕获阶段
- 处于目标阶段
- 事件冒泡阶段
添加事件的方法
-
直接在html里面通过"onclick = 'functionName'"绑定
- 通过此方法只能添加一个事件,如果连续添加两个事件的话,第二个事件会覆盖第一个事件。
-
addEventListener(event,function,useCapture)(ie8之前使用 attachEvent())
- event:事件名称
- function:要执行的方法
- useCapture(选填):指定事件是否在冒泡或者捕获阶段执行,true——捕获,false(默认)——冒泡
-
注意事项
- 通过 addEventListener 可以添加多个事件,并且不会被覆盖。
- 如果在捕获,冒泡都添加了事件,需要删除两次。
- 如果样式中 onclick事件 和 js中的 addEventListener 都进行了使用,那么这两个都会绑定成功,且执行顺序为,先onclick 再 js绑定事件
删除事件的方法
-
如果是在html直接添加onclick=functionName
-
document.getElementById('button').οnclick=function(){};
-
如果是给方法定义名字的话,将方法名指向空方法即可即可。如下:
var textfunction = function(){ alert('123'); } textfunction = function(){} -
如果是jquery的话,$('#button').removeAttr('onclick');
-
-
removeEventListener(event,function,useCapture)
- 参数信息同上面。
- 如果要移除事件句柄,addEventListener() 的执行函数必须使用外部函数
防止事件冒泡或者捕获
- 防止事件冒泡: w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true。
- 冒泡的终点是windows
- 阻止默认事件: w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false。
- jquery的 return false 既可以防止事件冒泡,也可以阻止默认事件。
如何让事件先冒泡后捕获
1. 对于同一事件,监听捕获和冒泡。
2. 监听到捕获事件,暂缓执行。
3. 直到冒泡事件被捕获(冒泡完毕),执行暂缓的捕获事件
事件委托
- 含义:不在事件的发生地(比如ui下的li)上设置监听函数,而是在其父元素上设置监听函数。当点击子元素时,通过事件冒泡,父元素监听到子元素,从而进行子元素事件的触发。
- 好处:比较适合动态元素的绑定,新添加的子元素也会有监听函数和事件触发机制。
图片的懒加载和预加载
-
预加载 提前加载图片,当用户需要查看时直接在本地进行渲染。
-
懒加载 做服务端前端你的优化,减少请求书或者延迟请求数。
js的new操作符做了哪些事情
1. 新建一个空对象
2. 这个对象的原型指向构造函数的prototype。
3. 执行构造函数后返回这个对象
改变函数内部this指针的指向函数
- 通过apply和call都可以改变。
- 区别在于,apply获取的第二个参数时数组,call则是
...Array - 通过bind改变this做用户会返回一个新的函数,这个函数不会立即执行。
Ajax解决浏览器缓存问题
1. 在ajax请求前加上 anyAjaxObj.setRequestHeader("If-Modified-Since","0")。
2. 在ajax发送请求前加上 anyAjaxObj.setRequestHeader("Cache-Control","no-cache")。
3. 在URL后面加上一个随机数: "fresh=" + Math.random()。
4. 在URL后面加上时间搓:"nowtime=" + new Date().getTime()。
5. 如果是使用jQuery,直接这样就可以了 $.ajaxSetup({cache:false})。这样页面的所有ajax都会执行这条语句就是不需要保存缓存记录。
浏览器渲染原理
1. js引入
2. style样式计算
3. layout布局计算
4. paint绘制填充样式
5. composite渲染层合并
js的节流和防抖(高性能滚动csroll以及页面渲染优化)
- 含义:再绑定scroll,resize这类事件时,当他发生,触发的频率非常高。间隔很近。如果此类函数涉及大量计算,会造成浏览器的掉帧。cpu使用率增加,影响用户体验。所以出现了节流和防抖。
- 防抖 在一定时间内,规定事件被触发的次数。
- 节流 节流保证函数在规定时间内,必定会触发一次。
js中的垃圾回收机制
1. 标记清除
var a="hello world";
var b="world";
var a=b;
如上,这时,系统会释放 “hello world” 的内存。 2. 引用计数 给每个值一个引用的次数,当声明一个变量,并将一个引用类型的值赋值给该变量,这个值的引用次数+1,反之-1.当引用次数为0,系统会清理该变量。(会出现内存泄漏)
eval
将对应的字符串解析成js并执行。(很少使用,消耗性能)
js判断类型
1. typeof()
typeof()只能判断基本类型,array和object都会返回object。
2. instanceof()
3. object.prototype.tostring()
数组去重
1. indexof循环去重
2. ES6 SET去重
Array.from(new Set(Array))
闭包
-
简单来说,闭包 = 函数 + 函数能够访问的自由变量。
-
含义:有权访问另外一个函数作用域中的变量。 闭包时函数的局部变量集合,在一个函数内定义另一个函数就会产生闭包。
-
用途
- 匿名自执行函数 2.结果缓存 3.封装
promise
promise是一个对象,解决异步状态的时候使用。
- 特点:
- 对象状态不受外界影响,有三种状态,pending(进行中),fulfilled(成功),rejected(失败)
- 一旦状态改变,就不会再变。
promise+Generator+Async的对比
- 他们三者都是解决异步现象的。
- promise上面有介绍。
- generator函数,是可以分段运行的函数体,相比较于promise,解决连续异步时减少了代码冗余。
- Async 时generator的语法糖。ES7语法。
setTimeout和Promise的执行顺序
如下问题:
setTimeout(function() {
console.log(1)
}, 0);
new Promise(function(resolve, reject) {
console.log(2)
for (var i = 0; i < 10000; i++) {
if(i === 10) {console.log(10)}
i == 9999 && resolve();
}
console.log(3)
}).then(function() {
console.log(4)
})
console.log(5);
输出答案为2 10 3 5 4 1 原因:
- promise新建之后立即执行,
- then在promise函数同级任务执行完执行,
- setTimeout 不是真的立即执行,所以没有then执行快。
如何获得对象上的属性
1. for(let i in obj)依次访问对象中可枚举的内容
2. object.keys():返回数组,包含所有可枚举内容
3. object.getOwnPropetryNames:返回一个数组,包含不可枚举属性。
箭头函数和function的区别
- 箭头函数没有绑定自己的this,在箭头函数中调用this,沿作用域链向上寻找,找到最近的一个this来使用。
this关键字
- this指向的永远是一个对象
- 在方法中,this表示该方法所属的对象
- 如果单独使用,this表示全局对象
- 在函数中,this表示全局对象
- 在事件中,this表示接受事件的元素
- 箭头函数不会生成新的this,箭头函数里的this会自动寻找最近的this。
- 类似call(),apply()可以将this引入到任何对象
箭头函数(注意点)
- 函数体内的this,是定义时所在的对象,而不是使用时所在的对象
- 不可以当成构造函数,也就是说,不可以使用new命令,不然会报错
- 不可以使用arguments都西昂,该对象在函数体内不存在。如果要用,用rest参数代替。
- 不可以使用yield命令,因此箭头函数不能用作Generator函数
解构赋值
- 解构赋值时浅拷贝,即如果一个键的值时复合类型的值(数组,对象,函数),那么解构赋值拷贝的是这个值的引用,而不是副本。
说一声SEO(搜索引擎优化)
- 对自身网页而言:
- 网页头部添加TDK,即title,description,keyword这三个标签
- 使用语义化的标签。如main,article,header,footer,nav,aside等。语义化代码会让搜索引擎容易理解网页。
- 重要的内容不要放在js代码里,搜索引擎不会爬取js代码
- 提高网站性能
- 其他的一些方面
- 使用https协议
- 网址静态化,短网址,伪静态
- 全站地图sitemap,即告诉搜索引擎怎么爬取你的网址
- 提交百度收录,添加tobots机器人(一个txt文件,告诉八度引起想让他爬什么,不能爬什么)
Let 和 Const对比
- let生命的变量具有块级作用域
- let声明的变量不能在通过window.变量名进行访问
- 形如for(let x)的循环每次迭代都会为x创建新的绑定
如何实现跨域
- jsonp 和ajax不同,请求script,动态插入。
- CORS 服务器端设置Access-Control-Allow-Origin
- iframe iframe解决跨域,不推荐
- proxy代理 使用代理服务器,实现数据转发
VUE
vue生命周期
1. boefocreated (创建之前)
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
2. created(创建,生成data,可以进行data的修改,一般在这里发起ajax请求获取数据)
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
3. beforemount(挂载之前)
在挂载开始之前被调用:相关的 render 函数首次被调用。
4. mounted(挂载,挂载DOM,可以进行DOM操作,一般在这里进行DOM相关操作)
el 被新创建的 vm.$替换,并挂载到实例上去之后调用该钩子。如果实例挂载了一个文档内元素,当被调用时el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
5. beforeupdate (数据更新之前)
数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
6. update(数据更新)
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
7. beforeDestory(销毁之前)
实例销毁之前调用。在这一步,实例仍然完全可用。
8. destroyed(销毁)
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
v-for的时候为什么需要绑定key值
- key的作用主要是为了高效的更新虚拟DOM。
- VUE的虚拟DOM的Diff算法有关系。(比如在 ABCDE 中的B和C之间插入E)
- 如果没有key,系统会将C更新为F,D更新为C,E更新为D,然后在最好插入E。浪费效率。
- 如果由key,Diff算法可以正确的识别此节点,找到正确的位置进行插入。
VUE虚拟DOM
-
虚拟DOM就是为了解决浏览器性能问题而被设计出来的。
-
案例解析:
- 若一次操作中有10次更新DOM的动作,操作真实DOM,会造成连续多次的更新DOM元素,从而影响性能。
- 虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。
-
好处:页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。
VUE之中method属性方法可以实现computed属性的功能,为什么还要用computed?
- computed是有缓存的,当页面多次调用时,会进行对比,如果数据没有发生改变,将直接渲染。
- method方法没有缓存,调用一次便会执行一次,影响性能。
通过v-if切换input等组件时会出现组件复用问题
- vue会尽可能的优化性能,所以进行了组件的服用,不过需要变换的id,class都会进行更改,只是input里面的内容不会被清空。
- 防止复用的方法:为不被复用的组件设置不同的key。
父子组件之间的传值调用等方法
| 传值 | 调用方法 | |
|---|---|---|
| 父传子 | prop | 使用ref获取子组件并调用方法 |
| 子传父 | 1.vuex 2.this.parents.data | 1.使用emit来调用方法 2.使用this.parents.methods调用 |
| 兄弟组件 | VUEX,BUS | |
| 跨级组件 | VUEX,attrs,listeners,provide,inject |
关于双向绑定
vue是响应式的,如果vue中data上有一个obj对象,对一个属性没有进行声明,那么给这个属性赋值的时候,是非响应式的,不会引起重新渲染。html不会发生变化,forceUpdate可以帮助我们处理。
this.$forceUpdate()
但是不建议这么做,因为对性能会有影响。
建议使用的方法是set方法。
this.$set(this.data,'show',true)
ps:this.$nextTick()对于这类情况不产生作用。因为双向绑定依然是没有进行绑定的。
路由相关
| hash | history | |
|---|---|---|
| 样式 | www.word.com#id | www.word.com/id |
| 特性 | 1.客户端的状态(向服务端发送请求的时候,hash部分不被发送) 2.会在浏览器访问历史上增加一个记录,可以使用浏览器的前进后退 3.hashchange事件来监听 | 1.需要后台进行对应配置,不然刷新会404 2提供了对应的api来加入到路由 |