前端优化
我们可以使用以下几种方式做前端优化
CDN:
CDN利用最靠近每位用户的服务器,更快、更可靠地将音乐、图片、视频、应用程序及其他文件发送给用户,来提供高性能、可扩展性及低成本的网络内容传递给用户。
CDN的作用:
(1)在性能方面,引入CDN的作用在于:
- 用户收到的内容来自最近的数据中心,延迟更低,内容加载更快
- 部分资源请求分配给了CDN,减少了服务器的负载
(2)在安全方面,CDN有助于防御DDoS网络攻击:
- 针对DDoS:通过监控分析异常流量,限制其请求频率
懒加载:
懒加载也叫做延迟加载、按需加载,指的是在长网页中延迟加载图片数据,是一种较好的网页性能优化的方式。 比如:在较长的网页中。如果有很多图片,所有的图片都被加载出来,而用户只能看到可视窗口的那一部分图片数据,这样就浪费了性能。
如果我们使用图片的懒加载就可以解决这个问题,在滚动屏幕之前,可视化区域之外的图片不会进行加载,在屏幕滚动时才加载,这样减少了服务器的负载,使网页的加载速度更快
回流与重绘
在渲染树中,部分或全部元素的尺寸、结构或者属性发生变化时,浏览器会重新渲染文档的过程就叫回流
下面这些操作会导致回流:
- 页面的首次渲染
- 浏览器的窗口大小发生变化
- 元素的内容发生变化
- 元素的尺寸或者位置发生变化
- 元素的字体大小发生变化
- 激活CSS伪类
- 查询某些属性或者调用某些方法
- 添加或者删除可见的DOM元素
当页面中某些元素的样式发生变化,但是不会影响其在文档流中的位置时,浏览器就会对元素进行重新绘制,这个过程就是重绘
下面这些操作会导致重绘:
- color、background 相关属性:background-color、background-image 等
- outline 相关属性:outline-color、outline-width 、text-decoration
- border-radius、visibility、box-shadow
注意: 当触发回流时,一定会触发重绘,但是重绘不一定会引发回流。
如何避免回流与重绘?
减少回流与重绘的措施:
- 操作DOM时,尽量在低层级的DOM节点进行操作
- 不要使用
table
布局, 一个小的改动可能会使整个table
进行重新布局 - 使用CSS的表达式
- 不要频繁操作元素的样式,对于静态页面,可以修改类名,而不是样式。
- 使用absolute或者fixed,使元素脱离文档流,这样他们发生变化就不会影响其他元素
- 避免频繁操作DOM,可以创建一个文档片段
documentFragment
,在它上面应用所有DOM操作,最后再把它添加到文档中 - 将元素先设置
display: none
,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。 - 将DOM的多个读操作(或者写操作)放在一起,而不是读写操作穿插着写。这得益于浏览器的渲染队列机制。
如何优化动画?
对于如何优化动画,我们知道,一般情况下,动画需要频繁的操作DOM,就就会导致页面的性能问题,我们可以将动画的position
属性设置为absolute
或者fixed
,将动画脱离文档流,这样他的回流就不会影响到页面了。
节流与防抖
- 函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。
- 函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。(持续触发的函数每隔一段时间触发一次)节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。
图片优化
如何对项目中的图片进行优化?
- 不用图片。很多时候会使用到很多修饰类图片,其实这类修饰图片完全可以用 CSS 去代替。
- 小图使用 base64 格式
- 将多个图标文件整合到一张图片中(雪碧图)
- 小图使用 PNG,其实对于大部分图标这类图片,完全可以使用 SVG 代替
- 照片使用 JPEG
Webpack优化
如何提⾼webpack的打包速度?
-
优化 Loader
可以将 Babel 编译过的文件缓存起来,下次只需要编译更改过的代码文件即可,这样可以大幅度加快打包时间
对于 Loader 来说,影响打包效率首当其冲必属 Babel 了。因为 Babel 会将代码转为字符串生成 AST(AST (Abstract Syntax Tree)是抽象语法树 ),然后对 AST 继续进行转变最后再生成新的代码,项目越大,转换代码越多,效率就越低。当然了,这是可以优化的。
-
代码压缩
在 Webpack3 中,一般使用
UglifyJS
来压缩代码,但是这个是单线程运行的,为了加快效率,可以使用webpack-parallel-uglify-plugin
这个插件来并行运行UglifyJS
,从而提高效率。
如何⽤webpack来优化前端性能?
⽤webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运⾏快速⾼效。
压缩代码:删除多余的代码、注释、简化代码的写法等等⽅式。可以利⽤webpack的 UglifyJsPlugin 和 ParallelUglifyPlugin 来压缩JS⽂件, 利⽤ cssnano (css-loader?minimize)来压缩css
利⽤CDN加速: 在构建过程中,将引⽤的静态资源路径修改为CDN上对应的路径。可以利⽤webpack对于 output 参数和各loader的 publicPath 参数来修改资源路径
Tree Shaking: 将代码中永远不会⾛到的⽚段删除掉。可以通过在启动webpack时追加参数 --optimize-minimize 来实现
Code Splitting: 将代码按路由维度或者组件分块(chunk),这样做到按需加载,同时可以充分利⽤浏览器缓存
提取公共第三⽅库: SplitChunksPlugin插件来进⾏公共模块抽取,利⽤浏览器缓存可以⻓期缓存这些⽆需频繁变动的公共代码
HTTP协议常问的面试题(吐血整理)
1、http协议请求方式 :
HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT
下面是它们的作用(背的时候可以挑常见的请求去背诵)
GET: 通常用于请求服务器发送某些资源
POST: 发送数据给服务器
PUT: 用于新增资源或者使用请求中的有效负载替换目标资源的表现形式
PATCH: 用于对资源进行部分修改
DELETE: 用于删除指定的资源
HEAD: 请求资源的头部信息, 并且这些头部与 HTTP GET 方法请求时返回的一致. 该请求方法的一个使用场景是在下载一个大文件前先获取其大小再决定是否要下载, 以此可以节约带宽资源
OPTIONS: 用于获取目的资源所支持的通信选项
CONNECT: HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
TRACE: 回显服务器收到的请求,主要用于测试或诊断
2、GET和POST有什么区别?
数据传输方式不同:GET请求通过URL传输数据,而POST的数据通过请求体传输。
安全性不同:POST的数据因为在请求主体内,所以有一定的安全性保证,而GET的数据在URL中,通过历史记录,缓存很容易查到数据信息。
数据类型不同:GET只允许 ASCII 字符,而POST无限制
GET无害: 刷新、后退等浏览器操作GET请求是无害的,POST可能重复提交表单
特性不同:GET是安全(这里的安全是指只读特性,就是使用这个方法不会引起服务器状态变化)且幂等(幂等的概念是指同一个请求方法执行多次和仅执行一次的效果完全相同),而POST是非安全非幂等
3、什么是无状态协议,HTTP 是无状态协议吗,怎么解决
无状态协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息。状态协议解决办法:通过1、Cookie 2、通过Session会话保存。
无状态协议(Stateless Protocol) 就是指浏览器对于事务的处理没有记忆能力。举个例子来说就是比如客户请求获得网页之后关闭浏览器,然后再次启动浏览器,登录该网站,但是服务器并不知道客户关闭了一次浏览器。
HTTP 就是一种无状态的协议,他对用户的操作没有记忆能力。可能大多数用户不相信,他可能觉得每次输入用户名和密码登陆一个网站后,下次登陆就不再重新输入用户名和密码了。这其实不是 HTTP 做的事情,起作用的是一个叫做 小甜饼(Cookie) 的机制。它能够让浏览器具有记忆能力。
4、UDP 和 TCP 的区别
UDP 是什么?
UDP 的全称是 User Datagram Protocol,用户数据报协议。它不需要所谓的握手操作,从而加快了通信速度,允许网络上的其他主机在接收方同意通信之前进行数据传输。
数据报是与分组交换网络关联的传输单元。
UDP 的特点主要有:
UDP 能够支持容忍数据包丢失的带宽密集型应用程序
UDP 具有低延迟的特点
UDP 能够发送大量的数据包
UDP 能够允许 DNS 查找,DNS 是建立在 UDP 之上的应用层协议。
TCP 是什么?
TCP 的全称是Transmission Control Protocol ,传输控制协议。它能够帮助你确定计算机连接到 Internet 以及它们之间的数据传输。通过三次握手来建立 TCP 连接,三次握手就是用来启动和确认 TCP 连接的过程。一旦连接建立后,就可以发送数据了,当数据传输完成后,会通过关闭虚拟电路来断开连接。
TCP 的主要特点有:
TCP 能够确保连接的建立和数据包的发送
TCP 支持错误重传机制
TCP 支持拥塞控制,能够在网络拥堵的情况下延迟发送
TCP 能够提供错误校验和,甄别有害的数据包。
TCP 和 UDP 的区别(重点来了)
TCP 是面向连接的协议 。 UDP 是无连接的协议
TCP 在发送数据前先需要建立连接,然后再发送数据 。 UDP 无需建立连接就可以直接发送大量数据
TCP 会按照特定顺序重新排列数据包 。 UDP 数据包没有固定顺序,所有数据包都相互独立
TCP 传输的速度比较慢 。 UDP 的传输会更快
TCP 的头部字节有 20 字节 。 UDP 的头部字节只需要 8 个字节
TCP 是重量级的,在发送任何用户数据之前,TCP需要三次握手建立连接。 UDP 是轻量级的。没有跟踪连接,消息排序等。
TCP 会进行错误校验,并能够进行错误恢复 。 UDP 也会错误检查,但会丢弃错误的数据包。
TCP 有发送确认。 UDP 没有发送确认
TCP 会使用握手协议,例如 SYN,SYN-ACK,ACK。 UDP无握手协议
TCP 是可靠的,因为它可以确保将数据传送到路由器。 UDP 中不能保证将数据传送到目标。
5、说一下Http协议中302状态?
http协议中,返回状态码302表示重定向。这种情况下,服务器返回的头部信息中会包含一个Location字段,内容是重定向到的url。
6、Http协议有什么组成?
请求报文包含三部分:请求行:包含请求方法、URI、HTTP版本信息;请求首部字段;请求内容实体。
7、cookies机制和session机制的区别是什么?
(1)cookies数据保存在客户端,session数据保存在服务端;
(2)cookies可以减轻服务器压力,但是不安全,容易进行cookies欺骗;
(3)session安全一点,但是占用服务器资源。
8、HTTP协议有什么特点?
(1)http无连接:限制每次连接只处理一个请求,服务端完成客户端的请求后,即断开连接。(传输速度快,减少不必要的连接,但也意味着每一次访问都要建立一次连接,效率降低);
(2)http无状态:对于事务处理没有记忆能力。每一次请求都是独立的,不记录客户端任何行为;
(3)客户端/服务端模型:客户端支持web浏览器或其他任何客户端;
(4)简单快速;
(5)灵活:可以传输任何类型的数据。
9、http和https有什么区别?
(1)https有ca证书,http一般没有;
(2)http是超文本传输协议,信息是明文传输。https则是具有安全性的ssl加密传输协议;
(3)http默认80端口,https默认443端口。
10、为什么有了HTTP为什么还要HTTPS?
https是安全版的http,因为http协议的数据都是明文进行传输的,所以对于一些敏感信息的传输就很不安全,HTTPS就是为了解决HTTP的不安全而生的。
11、HTTP的keep-alive是干什么的?
在早期的HTTP/1.0中,每次http请求都要创建一个连接,而创建连接的过程需要消耗资源和时间,为了减少资源消耗,缩短响应时间,就需要重用连接。在后来的HTTP/1.0中以及HTTP/1.1中,引入了重用连接的机制,就是在http请求头中加入Connection: keep-alive来告诉对方这个请求响应完成后不要关闭,下一次咱们还用这个请求继续交流。协议规定HTTP/1.0如果想要保持长连接,需要在请求头中加上Connection: keep-alive。
keep-alive的优点:
- 较少的CPU和内存的使用(由于同时打开的连接的减少了)
- 允许请求和应答的HTTP管线化
- 降低拥塞控制 (TCP连接减少了)
- 减少了后续请求的延迟(无需再进行握手)
- 报告错误无需关闭TCP连
12、http的请求报文是什么样的?
请求报文有4部分组成:
请求行
请求头部
空行
请求体
请求行包括:请求方法字段、URL字段、HTTP协议版本字段。它们用空格分隔。例如,GET /index.html HTTP/1.1。
请求头部:请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔
- User-Agent:产生请求的浏览器类型。
- Accept:客户端可识别的内容类型列表。
- Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
- 请求体: post put等请求携带的数据
13、http的响应报文是什么样的?
响应报文有4部分组成:
响应行
响应头
空行
响应体
响应行: 由协议版本,状态码和状态码的原因短语组成,例如
HTTP/1.1 200 OK
。响应头:响应部首组成
响应体:服务器响应的数据
14、聊一聊HTTP的部首有哪些?
通用首部字段(General Header Fields):请求报文和响应报文两方都会使用的首部
- Cache-Control 控制缓存 ✨
- Connection 连接管理、逐条首部 ✨
请求首部字段(Reauest Header Fields):客户端向服务器发送请求的报文时使用的首部
User-Agent 客户端程序信息 ✨
Host 请求资源所在服务器 ✨
If-Match 比较实体标记(ETage) ✨
If-None-Match 比较实体标记(ETage)与 If-Match相反 ✨
If-Modified-Since 比较资源更新时间(Last-Modified)✨
If-Unmodified-Since比较资源更新时间(Last-Modified),与 If-Modified-Since相反 ✨
响应首部字段(Response Header Fields):从服务器向客户端响应时使用的字段
- Server 服务器的信息 ✨
- Location 令客户端重定向的URI ✨
实体首部字段(Entiy Header Fields):针对请求报文和响应报文的实体部分使用首部
- Last-Modified 资源最后的修改资源 ✨
- Expires 实体主体的过期资源 ✨
- Allow 资源可支持http请求的方法 ✨
15、聊一聊HTTP的状态码有哪些?
2XX 成功
- 200 OK,表示从客户端发来的请求在服务器端被正确处理 ✨
- 201 Created 请求已经被实现,而且有一个新的资源已经依据请求的需要而建立
- 202 Accepted 请求已接受,但是还没执行,不保证完成请求
- 204 No content,表示请求成功,但响应报文不含实体的主体部分
- 206 Partial Content,进行范围请求 ✨
3XX 重定向
- 301 moved permanently,永久性重定向,表示资源已被分配了新的 URL
- 302 found,临时性重定向,表示资源临时被分配了新的 URL ✨
- 303 see other,表示资源存在着另一个 URL,应使用 GET 方法丁香获取资源
- 304 not modified,表示服务器允许访问资源,但因发生请求未满足条件的情况
- 307 temporary redirect,临时重定向,和302含义相同
4XX 客户端错误
- 400 bad request,请求报文存在语法错误 ✨
- 401 unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息 ✨
- 403 forbidden,表示对请求资源的访问被服务器拒绝 ✨
- 404 not found,表示在服务器上没有找到请求的资源 ✨
- 408 Request timeout, 客户端请求超时
- 409 Confict, 请求的资源可能引起冲突
5XX 服务器错误
- 500 internal sever error,表示服务器端在执行请求时发生了错误 ✨
- 501 Not Implemented 请求超出服务器能力范围,例如服务器不支持当前请求所需要的某个功能,或者请求是服务器不支持的某个方法
- 503 service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求
- 505 http version not supported 服务器不支持,或者拒绝支持在请求中使用的 HTTP 版本
16、TCP 三次握手和四次挥手
TCP 三次握手和四次挥手也是面试题的热门考点,它们分别对应 TCP 的连接和释放过程。下面就来简单认识一下这两个过程
TCP 三次握手
在了解具体的流程前,我们需要先认识几个概念
消息类型 描述
SYN 这个消息是用来初始化和建立连接的。
ACK 帮助对方确认收到的 SYN 消息
SYN-ACK 本地的 SYN 消息和较早的 ACK 数据包
FIN 用来断开连接
SYN:它的全称是 Synchronize Sequence Numbers,同步序列编号。是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立 TCP 连接时,首先会发送的一个信号。客户端在接受到 SYN 消息时,就会在自己的段内生成一个随机值 X。
SYN-ACK:服务器收到 SYN 后,打开客户端连接,发送一个 SYN-ACK 作为答复。确认号设置为比接收到的序列号多一个,即 X + 1,服务器为数据包选择的序列号是另一个随机数 Y。
ACK:Acknowledge character, 确认字符,表示发来的数据已确认接收无误。最后,客户端将 ACK 发送给服务器。序列号被设置为所接收的确认值即 Y + 1。
看了上面是不是人都傻掉了 接下来我用一个简单的例子去帮大家通俗易懂的去理解:happy:
小明👩 - 客户端
小红👨 - 服务端
小明给小红打电话,接通了后,小明说喂,能听到吗,这就相当于是连接建立。
小红给小明回应,能听到,你能听到我说的话吗,这就相当于是请求响应。
小明听到小红的回应后,好的,这相当于是连接确认。在这之后小明和小红就可以通话/交换信息了。
TCP 四次挥手
在连接终止阶段使用四次挥手,连接的每一端都会独立的终止。下面我们来描述一下这个过程。
首先,客户端应用程序决定要终止连接(这里服务端也可以选择断开连接)。这会使客户端将 FIN 发送到服务器,并进入 FIN_WAIT_1 状态。当客户端处于 FIN_WAIT_1 状态时,它会等待来自服务器的 ACK 响应。
然后第二步,当服务器收到 FIN 消息时,服务器会立刻向客户端发送 ACK 确认消息。
当客户端收到服务器发送的 ACK 响应后,客户端就进入 FIN_WAIT_2 状态,然后等待来自服务器的 FIN 消息
服务器发送 ACK 确认消息后,一段时间(可以进行关闭后)会发送 FIN 消息给客户端,告知客户端可以进行关闭。
当客户端收到从服务端发送的 FIN 消息时,客户端就会由 FIN_WAIT_2 状态变为 TIME_WAIT 状态。处于 TIME_WAIT 状态的客户端允许重新发送 ACK 到服务器为了防止信息丢失。客户端在 TIME_WAIT 状态下花费的时间取决于它的实现,在等待一段时间后,连接关闭,客户端上所有的资源(包括端口号和缓冲区数据)都被释放。
还是可以用上面那个通话的例子来进行描述
小明对小红说,我所有的东西都说完了,我要挂电话了。
小红说,收到,我这边还有一些东西没说。
经过若干秒后,小红也说完了,小红说,我说完了,现在可以挂断了
小明收到消息后,又等了若干时间后,挂断了电话。
浏览器兼容问题
面试官问我我该这样回答:
我会针对浏览器不同的版本去选择合适的框架(比如大于等于ie8版本的我会选择bootstrap)(大于等于ie9的我会去选择vue)
面对不同的浏览器,他们对CSS的解析认识不完全一样,因此会导致生成的页面效果不一样,得不到我们所需要的页面效果。 这个时候我们就需要对不同的浏览器去写不同的CSS让他们能在不同的浏览器中也能得到我们想要的页面效果
不同浏览器的扩展功能(例如
-moz
,-webkit
开头的样式),对W3C标准也是个推进;说它是坏事,因为,多个浏览器同时存在,这些浏览器在处理一个相同的页面时,表现有时会有差异。我们把引起这些差异的问题统称为“浏览器兼容性问题”。
什么是兼容想问题?
就是同样的代码,在不同的浏览器上显示的页面效果是不一样的
不一样的原因是什么?
因为各浏览器的内核不同,他们处理同一件事情的时候思路不同
浏览器的兼容性大体分为样式兼容性(css),交互兼容性(javascript),浏览器 hack 三个方面。
- 1.样式兼容性(css兼容)
因为历史原因,不同浏览器样式存在差异,我们可以通过Normalize.css抹平差异,也可以定制自己的reset.css比如我们可以通过通配符选择器,全局重置样式
2.交互性差异(JavaScript兼容)
1.事件兼容的问题,我们通常需要会封装一个适配器的方法,过滤事件句柄绑定、移除、冒泡阻止以及默认事件行为处理 2.addEventListener 与 attachEvent 区别: attachEvent ——兼容:IE7、IE8;不兼容firefox、chrome、IE9、IE10、IE11、safari、opera。 addEventListener——兼容:firefox、chrome、IE、safari、opera;不兼容IE7、IE8 3.集合类对象问题: 在ie可以使用() 和 []获取集合类对象,Firefox下,只能使用 [ ] 获取集合类对象。 解决方案:统一使用 [] 获取集合类对象。 4.自定义属性问题: IE下,可以使用获取常规属性的方法来获取自定义属性,也可以使用 getAttribute() 获取自定义属性; Firefox下,只能使用 getAttribute() 获取自定义属性。 解决方案:统一通过 getAttribute() 获取自定义属性。 5.const问题 问题说明:Firefox下,可以使用 const 关键字或 var 关键字来定义常量;IE下,只能使用 var 关键字来定义常量。 解决方案:统一使用 var 关键字来定义常量。 6.window.location.href 问题: 问题说明:IE或者Firefox2.0.x下,可以使用 window.location 或 window.location.href;Firefox1.5.x下,只能使用 window.location。解决方案:使用 window.location 来代替 window.location.href 。当然也可以考虑使用 location.replace()方法。
数组去重的方法
利用Set()+Array.from()
Set中的元素只会出现一次,即Set中的元素是唯一的。 Array.from() 方法:对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
利用两层循环+数组的splice方法
通过两层循环对数组元素进行逐一比较,然后通过splice方法来删除重复的元素。此方法对NaN是无法进行去重的,因为进行比较时NaN !== NaN。
利用数组的indexOf方法
新建一个空数组,遍历需要去重的数组,将数组元素存入新数组中,存放前判断数组中是否已经含有当前元素,没有则存入。此方法也无法对NaN去重。 function removeDuplicate(arr) { const newArr = [] arr.forEach(item => { if (newArr.indexOf(item) === -1) { newArr.push(item) } }) return newArr // 返回一个新数组 }
利用数组的includes方法
用includes方法来判断是否包含重复元素。 includes()方法:用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
利用Map()
Map对象是JavaScript提供的一种数据结构,结构为键值对形式,将数组元素作为map的键存入 然后结合has()和set()方法判断键是否重复。 使用Map()也可对NaN去重,原因是Map进行判断时认为NaN是与NaN相等的
利用sort
利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。
样式的深层组件,但是不能通过class修改?
- 如果是css,一般采用>>>的写法,示例如下:前面的类一般是后面组件的父类或祖先类。
.aaa >>> .bbb
- 如果是less或其他预处理语言,需要使用/deep/语法,一般使用如下示例:deep前面可以不用写类名,有时候使用deep可能会报错,可以改成::v-deep,用法与deep一致。
- 有时候会出现以上三种情况都不能生效的问题,这个时候需要考虑组件的样式是否是在嵌套的组件中了。 如果设置了scoped属性,可能会被影响,如果不生效,可以尝试去掉scoped这一属性,但这并不是一个好的写法
less sass 除了用到它的嵌套功能(嵌套写法[],还会用到他们自身的哪些功能?比如说函数样式计算 或者参数等等) 还会用到什么功能?
Less和Sass在语法上有些共性,比如下面这些:
1、混入(Mixins)——class中的class;
2、参数混入——可以传递参数的class,就像函数一样;
3、嵌套规则——Class中嵌套class,从而减少重复的代码;
4、运算——CSS中用上数学;
5、颜色功能——可以编辑颜色;
6、名字空间(namespace)——分组样式,从而可以被调用;
7、作用域——局部修改样式;
8、JavaScript 赋值——在CSS中使用JavaScript表达式赋值。
swiper怎么在vue中使用
在vue2中swiper5的版本比较稳定好用,7和8是针对vue3
首先下包:
npm i swiper@5
在组件中用import导入swiper这个构造函数
import swiper from 'swiper'
接着引入swiper.css:
import 'swiper/css/swiper.min.css'
容器修改为swiper-container
<div class="swiper-container">
这是swiper5版本的要求把大小也复制一下(可以自行修改)
然后初始化swiper在vue生命周期
mounted
中去使用mounted(){ new Swiper ('.swiper-container', { direction: 'vertical', // 垂直切换选项 loop: true, // 循环模式选项 // 如果需要分页器 pagination: { el: '.swiper-pagination', }, // 如果需要前进后退按钮 navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, // 如果需要滚动条 scrollbar: { el: '.swiper-scrollbar', }, }) } // 注意不需要创建变量因为创建变量的时候vue会报错
默认方向是纵向,我们可以用direction去控制方向
在created里发请求去遍历渲染
swiper-slide
在created里的请求是异步的,而在初始化swiper的mounted是同步的这样打开页面是没有轮播图效果的
那么就需要我们更新完毕banner图之后去初始化swiper,在生命周期函数updated中去做初始化,可以拿到
swiper-container
的真实DOM结构最后根据官方提供的API文档去修改相应的效果
项目打包测试,遇到报错无法定位到准确行怎么处理
我们在开发过程中代码出现了错误,在浏览器中只能定位到打包后的代码中出现错误的地方,而无法定位到打包前代码的错误位置,这使得我们在查找错误点时相当的麻烦。 然而有了SourceMap,它可以对打包前后的文件进行映射。Sourcemap就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置。有了这种映射关系后,出错时,可以在控制台直接显示源代码中出错的位置。
前端大文件上传
普通表单上传:
使用PHP来展示常规的表单上传是一个不错的选择。首先构建文件上传的表单,并指定表单的提交内容类型为enctype="multipart/form-data",表明表单需要上传二进制数据。 然后编写index.php上传文件接收代码,使用move_uploaded_file方法即可 注意: form表单上传大文件时,很容易遇见服务器超时的问题。通过xhr,前端也可以进行异步上传文件的操作,一般由两个思路。
文件编码上传:
将文件进行编码,然后在服务端进行解码 主要实现原理就是将图片转换成base64进行传递 base64编码的缺点在于其体积比原图片更大(因为Base64将三个字节转化成四个字节,因此编码后的文本,会比原文本大出三分之一左右),对于体积很大的文件来说,上传和解析的时间会明显增加。 除了进行base64编码,还可以在前端直接读取文件内容后以二进制格式上传
formData异步上传:
FormData对象主要用来组装一组用 XMLHttpRequest发送请求的键/值对,可以更加灵活地发送Ajax请求。可以使用FormData来模拟表单提交。 let files = e.target.files // 获取input的file对象 let formData = new FormData(); formData.append('file', file); axios.post(url, formData);
iframe无刷新页面
让用户体验异步上传文件的感觉,可以通过framename指定iframe来实现。把form的target属性设置为一个看不见的iframe,那么返回的数据就会被这个iframe接受,因此只有该iframe会被刷新,至于返回结果,也可以通过解析这个iframe内的文本来获取。
大文件切片上传
编码方式上传中,在前端我们只要先获取文件的二进制内容,然后对其内容进行拆分,最后将每个切片上传到服务端即可。 在JavaScript中,文件FIle对象是Blob对象的子类,Blob对象包含一个重要的方法slice,通过这个方法,我们就可以对二进制文件进行拆分。
组件封装后涉及到组件传值的操做,怎么做?
父组件向子组件传值
父组件通过属性的方式向子组件传值,子组件通过 props 来接收。 1.在父组件的子组件标签中绑定自定义属性 // 父组件 <user-detail :myName="name" /> 2.在子组件中使用props(可以是数组也可以是对象)接收即可。可以传多个属性。
子组件向父组件传值
1.子组件绑定一个事件,通过 this.$emit() 来触发 2.通过 $parent / $children 或 $refs 访问组件实例 (这两种都是直接得到组件实例,使用后可以直接调用组件的方法或访问数据。) 注:这种方式的组件通信不能跨级 3.$attrs / $listeners - 如果子组件想被绑定点击的DOM不是根组件,那么需要绑定$listeners(this.$listeners拿到的是父组件传递的原生事件)需要在对应的DOM标签上添加v-on="$listeners" - this.$attes拿的是父组件除了子组件props定义之外的属性和值
兄弟组件之间传值
1.还是通过 $emit 和 props 结合的方式 在父组件中给要传值的两个兄弟组件都绑定要传的变量,并定义事件 2.通过一个 空 vue 实例 创建一个 EventBus.js 文件,暴露一个 vue 实例 步骤: import Vue from 'Vue' export default new Vue() 在要传值的文件里导入这个空 vue 实例,绑定事件并通过 $emit 触发事件函数 (也可以在 main.js 中全局引入该 js 文件,我一般在需要使用到的组件中引入) 在接收传值的组件中也导入 vue 实例,通过 $on 监听回调,回调函数接收所有触发事件时传入的参数 3.使用 vuex
多层父子组件通信
有时需要实现通信的两个组件不是直接的父子组件,而是祖父和孙子,或者是跨越了更多层级的父子组件 这时就需要用到 vue 提供的更高阶的方法:provide/inject。(依赖注入) 允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深 简单来说就是在父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量,不管组件层级有多深,在父组件生效的生命周期内,这个变量就一直有效。 // 父组件 export default { provide: { // 它的作用就是将 **name** 这个变量提供给它的所有子组件。 name: 'Jack' } } // 子组件 export default { inject: ['name'], // 注入了从父组件中提供的name变量 mounted () { console.log(this.name); // Jack } } 注意:provide 和 inject 绑定并不是可响应的。即父组件的name变化后,子组件不会跟着变。
你认为什么样的情况会封装一个组件?
我认为一段代码在项目中出现两次就要开始考虑是否应该进行封装,出现三次就肯定要封装组件,大到一个页面,一个组件,小到一个函数和一个css样式
封装出来的组件必须具有高性能,低耦合的特性
封装组件的好处:
- 降低系统各个功能的耦合性
- 提高了前端工程化
- 代码维护难度降低
- 开发效率以及开发成本的提升
写好的页面发现样式不生效,你从哪几个方面来着手处理这个问题?
首先,我会清除缓存,重启浏览器吗,如果无效在排查是否确认关联了样式表、选择器是否写错了。关联位置,样式名称是否正确,是否有语法错误 样式表编码格式是否utf-8,是否有语法错误、是否样式被层叠了
vue-loader 是什么?使用它的用途有哪些?
答:解析.vue 文件的一个加载器,跟 template/js/style 转换 成 js 模块。
用途:js 可以写 es6、style 样式可以 scss 或 less、template 可以加 jade
详细说一下你对生命周期的理解?
答:总共分为 8 个阶段创建前/后,载入前/后,更新前/后, 销毁前/后
创建前/后:在 beforeCreated 阶段,vue 实例的挂载元素
$el
和数据对象 data 都为 undefined,还未初始化。在 created 阶段,vue 实例的数据对象 data 有了,$el 还没有 。载入前/后:在 beforeMount 阶段,vue 实例的$el 和 data 都初始化了,但还是挂载之前为虚拟的dom节点,data.message 还未替换。在mounted阶段,vue实例挂载完成,data.message 成功渲染 。
更新前/后:当 data 变化时,会触发 beforeUpdate 和 updated 方法 。
销毁前/后:在执行 destroy 方法后,对 data 的改变不会再 触发周期函数,说明此时 vue 实例已经解除了事件监听以及 和 dom 的绑定,但是 dom 结构依然存在 。
自定义指令(v-check、v-focus)的方法有哪些?它有 哪些钩子函数?还有哪些钩子函数参数?
答:
全局定义指令:
在 vue 对象的 directive 方法里面有两个 参数,一个是指令名称,另外一个是函数。
组件内定义指令:
directives 钩子函数:bind(绑定事件触发)、inserted(节点插入的时候 触发)、update(组件内相关更新) 钩子函数参数:el、binding
vue-router 有哪几种导航钩子?
三种
- 第一种是全局导航钩子:
router.beforeEach(to,from,next)
作用:调转前进行判断拦截- 第二种:组件内的钩子
- 第三种:单独路由独享组件
简述一下Vuex的原理和使用方法
Vuex的数据是单向流动的,一个应用可以看作是由三部分组成:View、Actions、State,数据的流动也是从
View-->Actions-->State-->View
以此达到数据的单向流动但是项目较大的,组件嵌套过多的时候,多组件共享同一个State会在数据传递时出现很多问题。Vuex就是为了解决这些问题而产生的
Vuex可以看作项目中所有组件的数据中心,我们将所有组件中共享的State抽离出来,任何组件都可以访问和操作我们的数据中心
Vuex的组成:一个实例化的
Vuex.Store
由state、mutations、和actions三个属性组成
- State中保存着共享数据
- 改变state中的数据只有通过mutations中的方法,且mutations中的方法必须是同步的
- 如果要写异步的方法,需要在actions中,并通过commit到mutations中进行state中数据的更改
什么是TCP?什么是TCP连接的三次握手?
TCP即传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通讯协议。
TCP把连接作为最基本的对象,每一条TCP连接都有两个端点,这种断点我们叫作套接字(socket),它的定义为端口号拼接到IP地址即构成了套接字,例如,若IP地址为192.3.4.16 而端口号为80,那么得到的套接字为192.3.4.16:80。
三次握手:
三次握手的原文是
three-way handshake
,整个名词的可以翻译为:需要三个步骤才能建立握手/连接的机制。当然,三次握手也可以叫three-message handshake
,通过三条消息来建立的握手/连接。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的 初始化序列号(Init Sequense Number, ISN) 为后面的可靠性传输做准备。
1)第一次握手:客户端向服务端发送一个 SYN 报文(SYN = 1),并指明客户端的初始化序列号 ISN(x),即图中的 seq = x,表示本报文段所发送的数据的第一个字节的序号。此时客户端处于
SYN_Send
状态。
SYN-SENT
:在发送连接请求后等待匹配的连接请求2)第二次握手:服务器收到客户端的 SYN 报文之后,会发送 SYN 报文作为应答(SYN = 1),并且指定自己的初始化序列号 ISN(y),即图中的 seq = y。同时会把客户端的 ISN + 1 作为确认号 ack 的值,表示已经收到了客户端发来的的 SYN 报文,希望收到的下一个数据的第一个字节的序号是 x + 1,此时服务器处于
SYN_REVD
的状态。
SYN-RECEIVED
:在收到和发送一个连接请求后等待对连接请求的确认3)第三次握手:客户端收到服务器端响应的 SYN 报文之后,会发送一个 ACK 报文,也是一样把服务器的 ISN + 1 作为 ack 的值,表示已经收到了服务端发来的的 SYN 报文,希望收到的下一个数据的第一个字节的序号是 y + 1,并指明此时客户端的序列号 seq = x + 1(初始为 seq = x,所以第二个报文段要 +1),此时客户端处于
Establised
状态。服务器收到 ACK 报文之后,也处于
Establised 状态
,至此,双方建立起了 TCP 连接。
一个页面从输入URL到页面加载显示完成,这个过程中都发生了什么
- 浏览器查找域名对应的IP地址(DNS查询:浏览器缓存–>系统缓存–>路由器缓存–>ISP DNS缓存–>根域名服务器)
- 浏览器向web服务器发送一个HTTP请求(TCP三次握手)
- 服务器301重定向(从http://baidu.com)重定向到(http://www.baidu.com)
- 浏览器跟踪重定向地址,请求另一个带www的网址
- 服务器处理请求(通过路由读取资源)
- 服务器返回一个HTTP响应(报头中把Content-type设置为‘text/html’)
- 浏览器进行DOM树构建
- 浏览器发送请求获取嵌在HTML中的资源(图片、音频、视频、CSS、JS等)
- 浏览器显示完成页面
- 浏览器发送异步请求
$route
和$router 的区别
$router
为 VueRouter 实例,想要导航到不同 URL, 则使用$router.push
方法
$route
为当前 router 跳转对象里面可以获 取 name 、 path 、 query 、 params
对vue生命周期的理解
vue实例有一个完整的生命周期,生命周期也就是指一个实例从开始创建到销毁的过程
beforeCreated() 在实例创建之间执行,数据未加载状态
created() 在实例创建、数据加载后,能初始化数据,dom 渲染之前执行
beforeMount() 虚拟 dom 已创建完成,在数据渲染前最后一 次更改数据
mounted() 页面、数据渲染完成,真实 dom 挂载完成
beforeUpadate() 重新渲染之前触发
updated() 数据已经更改完成,dom 也重新 render 完成,更 改数据会陷入死循环
beforeDestory() 和 destoryed() 前者是销毁前执行(实例仍 然完全可用),后者则是销毁后执行
vue如何去除url中的#
vue-router
默认使用hash模式,所以在路由加载的时候,项目中的url会自带#。如果不想使用#,可以使用vue-router的另一种模式history
模式new Router({ mode:'history', routesL[] })
需要注意的是,当我们启用 history 模式的时候,由 于我们的项目是一个单页面应用,所以在路由跳转的 时候,就会出现访问不到静态资源而出现 404 的情 况,这时候就需要服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该 返回同一个 index.html
对比 jQuery ,Vue 有什么 不同
jQuery专注视图层,通过操作DOM去实现页面的一些逻辑渲染,
Vue专注数据层,通过数据的双向绑定,最终表现在DOM层面,减少了DOM操作
Vue实现了组件化思想,使得项目子集职责清晰,提高了开发效率,方便重复利用,便于协同开发
请求拦截器:
作用:统一给有权限的接口注入请求头token
添加判断条件:
如果用户没有登录,token值为null,报错,所以要添加判断条件if(user && user.token){} === if(null && null.token)
如果为null 则退出判断条件
在config配置项里添加headers请求头
在请求拦截器添加headers后就可以把api/user.js中的headers注释掉了
无感刷新(响应拦截器)
作用:无感刷新、统一处理错误、统一对数据进行过滤
短token:用来发请求,在请求头里携带,一般两小时过期
refresh_token
:长token 用来获取新的短token 一般14天过期
能不能把短token过期时间加长 比如14天?
答:不能,因为涉及到安全问题,防止token被盗 (只有两个一起盗取才会泄漏信息)我们可以对登录密码加密—md5.js加密,(MD5加密本质是一个插件,调用他的方法就可以生成加密后的代码) 我们需要和后端配合(后端解密)
使用长token的思路:
- 用户发请求,后端返回401,说明token过期 这时要统一监测后端返回的401代码
- 监测到401报错,就拿长token
refresh_token
发请求获取最新的token - 自动的再发一次用户上次发的请求
- 添加响应拦截器
- 主要作用:
- 无感刷新
- 对后端返回的数据进行统一的处理
- 对后端数据的错误进行统一的处理
- 主要作用:
使用长token的思路(具体步骤):
-
当用户发请求时,如果后端返回401,就说明token过期 这时我们要统一监测后端返回的401代码
-
我们需要添加响应拦截器,在拦截器里的报错函数中监测判断token是否过期,代码如下:
if (error.response.status === 401) { console.log('token过期') }
-
-
监测到401报错,就拿长token
refresh_token
发请求获取最新的token-
注意点:不能用request发,
会死循环
,因为request设置了请求拦截器,会注入老token (前提
-