前端常见面试题
- 浏览器
- 网络安全
- 性能相关
- HTML
- CSS
- JS
- ES6
- Vue2.0
- 其他
- webpack
浏览器
输入一个URL到页面过程中发生了什么
- 首先在浏览器中输入URL地址
- 查找缓存:浏览器先查看浏览器缓存-系统缓存-路由缓存中是否有该地址页面,如果有则显示页面内容。如果没有则进行下一步。
- 首先判断输入的东西是否为域名并且合法,如果不合法,直接使用浏览器的搜索引擎进行搜索,如果合法,如果是域名的话进行DNS域名解析将其进行IP地址转化并访问该IP地址,如果是IP,直接打开。(DNS域名解析:浏览器向DNS服务器发起请求,解析该URL中的域名对应的IP地址。DNS服务器是基于UDP的,因此会用到UDP协议。)
- 输入 IP访问是不会输入端口号的,那么如果是http协议的话,默认端口是80端口,如果是https协议的话,默认端口是443。如果是https协议,会进行加密操作(SSL加密协议),此时已经拿到了完整的路径。
- 如果是nginx的话,会进行路径匹配。
- 建立TCP连接:解析出IP地址后,根据IP地址和默认80端口,和服务器建立TCP连接
- 发起HTTP请求:浏览器发起读取文件的HTTP请求,,该请求报文作为TCP三次握手的第三次数据发送给服务器
- 服务器响应请求并返回结果:服务器对浏览器请求做出响应,并把对应的html文件发送给浏览器
- 关闭TCP连接:通过四次挥手释放TCP连接
- 浏览器渲染:客户端(浏览器)解析HTML内容并渲染出来,浏览器接收到数据包后的解析流程为:
构建DOM树:词法分析然后解析成DOM树(dom tree),是由dom元素及属性节点组成,树的根是document对象
构建CSS规则树:生成CSS规则树(CSS Rule Tree)
构建render树:Web浏览器将DOM和CSSOM结合,并构建出渲染树(render tree)
布局(Layout):计算出每个节点在屏幕中的位置
绘制(Painting):即遍历render树,并使用UI后端层绘制每个节点。
超文本传输协议的超文本怎么理解
超文本传输协议一般指http协议。超文本-不是单纯的文本,包括一些文件图片这样的二进制流
浏览器渲染机制、重绘、重排
浏览器渲染机制即网页生成的过程
构建DOM树:词法分析然后解析成DOM树(dom tree),是由dom元素及属性节点组成,树的根是document对象
构建CSS规则树:生成CSS规则树(CSS Rule Tree)
构建render树:Web浏览器将DOM和CSSOM结合,并构建出渲染树(render tree)
布局(Layout):计算出每个节点在屏幕中的位置
绘制(Painting):即遍历render树,并使用UI后端层绘制每个节点。
重排
重排:当DOM的变化影响了元素的几何信息(DOM对象的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。
触发条件:
- 添加或者删除可见的DOM元素
- 元素尺寸改变——边距、填充、边框、宽度和高度
重绘
重绘:当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。
触发条件:改变元素的color、background、box-shadow等属性
网络安全
GET和POST
GET和POST的区别
get和post本质没有什么区别,都是TCP/IP协议请求的一种形式,只不过因为浏览器以及各大厂商的规定,限制了每一种请求有自己特定的用途。常说的get和post请求的区别实际上是参数放到请求头和请求体里面用法的区别
GET和POST参数应用场景的区别
-
GET在浏览器回退不会再次请求,POST会再次提交请求
-
GET请求会被浏览器主动缓存,POST不会,要手动设置
-
GET请求参数会被完整保留在浏览器历史记录里,POST中的参数不会
-
GET请求在URL中传送的参数是有长度限制的,而POST没有限制
-
GET参数通过URL传递,POST放在Request body中
-
GET参数暴露在地址栏不安全,POST放在报文内部更安全
-
GET一般用于查询信息,POST一般用于提交某种信息进行某些修改操作
-
GET产生一个TCP数据包;POST产生两个TCP数据包
HTTP和HTTPS
http 和 https 的基本概念
http: 是一个客户端和服务器端请求和应答的标准(TCP),用于从 WWW 服务器传输超文本到本地浏览器的超文本传输协议。
https:是以安全为目标的 HTTP 通道,即 HTTP 下 加入 SSL 层进行加密。其作用是:建立一个信息安全通道,来确保数据的传输,确保网站的真实性。
http 和 https 的区别
-
HTTP
的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头 -
HTTP
是不安全的,而 HTTPS 是安全的 -
HTTP
标准端口是80 ,而 HTTPS 的标准端口是443 -
在OSI
网络模型中,HTTP工作于应用层,而HTTPS 的安全传输机制工作在传输层 -
HTTP
无法加密,而HTTPS 对传输的数据进行加密 -
HTTP
无需证书,而HTTPS 需要CA机构wosign的颁发的SSL证书(SSL加密协议)
http状态码
- 200响应成功
- 301永久重定向
- 302临时重定向
- 304资源缓存
- 401未登录
- 403服务器禁止访问
- 404服务器资源未找到
- 500 502服务器内部错误 504 服务器繁忙
tcp和udp
概念:
传输控制协议(TCP):TCP(传输控制协议)定义了两台计算机之间进行可靠的传输而交换的数据和确认信息的格式,以及计算机为了确保数据的正确到达而采取的措施。TCP最大的特点就是提供的是面向连接、可靠的字节流服务。
用户数据报协议(UDP):UDP(用户数据报协议)是一个简单的面向数据报的传输层协议。提供的是非面向连接的、不可靠的数据流传输。
TCP:
在使用TCP协议进行数据传输时,往往需要客户端和服务端先建立一个“通道“、且这个通道只能够被客户端和服务端使用,所以TCP传输协议只能面向一对一的连接。
通道的建立——三次握手:
(1)在建立通道时,客户端首先要向服务端发送一个SYN同步信号。
(2)服务端在接收到这个信号之后会向客户端发出SYN同步信号和ACK确认信号。
(3)当服务端的ACK和SYN到达客户端后,客户端与服务端之间的这个“通道”就会被建立起来。
通道的关闭——四次挥手:
(1)在数据传输完毕之后,客户端会向服务端发出一个FIN终止信号。
(2)服务端在收到这个信号之后会向客户端发出一个ACK确认信号。
(3)如果服务端此后也没有数据发给客户端时服务端会向客户端发送一个FIN终止信号。
(4)客户端在收到这个信号之后会回复一个确认信号,在服务端接收到这个信号之后,服务端与客户端的通道也就关闭了。
应用场景:TCP主要应用于文件传输精确性相对要求较高且不是很紧急的情景,比如电子邮件、远程登录等。
UDP:
UDP传输协议是一种不可靠的、面向无连接、可以实现多对一、一对多和一对一连接的通信协议。UDP在传输数据前既不需要建立通道,在数据传输完毕后也不需要将通道关闭。只要客户端给服务端发送一个请求,服务端就会一次性地把所有数据发送完毕。UDP在传输数据时不会对数据的完整性进行验证,在数据丢失或数据出错时也不会要求重新传输,因此也节省了很多用于验证数据包的时间,所以以UDP建立的连接的延迟会比以TCP建立的连接的延迟更低。UDP不会根据当前的网络情况来控制数据的发送速度,因此无论网络情况是好是坏,服务端都会以恒定的速率发送数据。
应用场景:UDP被广泛应用于数据量大且精确性要求不高的数据传输,比如我们平常在网站上观看视频或者听音乐。
TCP和UDP的区别
1.是否连接:tcp是面向连接,udp无连接;
2.传输可靠性:tcp是可靠的,udp不可靠;
3.应用场景:tcp传输大量数据,udp传输少量数据;
4.速度:tcp传输速度慢,udp传输速度快。
性能相关
浏览器的存储方式
浏览器的存储方式主要分为cookie、localStorage和sessionStorage。
浏览器三种存储方式的相同点:
共同点: 都是保存在浏览器端、仅同源可用的本地存储方式
浏览器三种存储方式的不同点(web storage和cookie的区别):
- 从存储数据的大小来说:cookie数据不能超过4K,sessionStorage和localStorage可以达到5M。
- 从存储数据的种类来说:web storage存储的数据可以是JSON对象,也可以是字符串,而cookie只能是字符串。
- 从存储数据的有效期来说:sessionStorage关闭浏览器窗口就删除了,localStorage是永久存储,只有主动删除才会删除掉,cookie必须设置有效期,有效期到了就删除,也可以主动删除。
- 从存储数据的作用域来说:sessionStorage作用于本窗口,localstorage和cookie作用于所有的同源页面(同源:协议名,域名,端口名都相同)。
- 语义化方法:web storage语义化更强。
浏览器的同源策略
浏览器的同源策略:协议相同,域名相同,端口相同(如果他们三个不一致,就会出现跨域现象)
解决请求跨域的方法
- jsonp(利用script标签没有跨域限制的漏洞实现。缺点:只支持GET请求)
- CORS(设置Access-Control-Allow-Origin:指定可访问资源的域名)
- proxy代理 目前常用方式,通过服务器设置代理
- 利用h5新特性window.postMessage()
加密方式
1.md5加密(不可逆)322位
2. RSA 非对称加密,分为公钥(在服务器上)和私钥。(不规则图形可以对一起)
3. SHa加密
防抖
多次触发事件,事件处理函数只能执行一次,并且是在触发操作结束时执行。也就是说,当一个事件被触发准备执行事件函数前,会等待一定的时间(这时间是自己去定义的,比如 1 秒),如果没有再次被触发,那么就执行,如果被触发了,那就本次作废,重新从新触发的时间开始计算,并再次等待 1 秒,直到能最终执行。(如输入框中输入内容,只执行最后一次)
const debounce = (fn, delay = 1000) => {
let timer;
return function() {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
};
}
节流
事件触发后,规定时间内,事件处理函数不能再次被调用。也就是说在规定的时间内,函数只能被调用一次,且是最先被触发调用的那次。(如浏览器窗口不停 的拖动,只执行第一次)
const throttle = (fn, delay) => {
let valid = true;
return function(){
if(valid) {
setTimeout(()=> {
fn.apply(this, arguments);
valid = true;
}, delay)
valid = false;
}
}
}
HTML
常见的语义化标签
header nav main article section aside footer
语义化的优点
- 对机器友好,带有语义的文字表现力丰富,更适合搜索引擎的爬虫爬取有效信息,有利于SEO。除此之外,语义类还支持读屏软件,根据文章可以自动生成目录;
- 对开发者友好,使用语义类标签增强了可读性,结构更加清晰,开发者能清晰的看出网页的结构,便于团队的开发与维护
HTML5的新特性
- 本地存储 localstorage和sessionstorage
- canvas画布
- 音频,视频
- 语义化标签
- 超链接协议,解决跨域的新方法,websocket
- 增强型表单,如email,time,seach
script标签中defer和async的区别
多个带async属性的标签,不能保证加载的顺序;多个带defer属性的标签,按照加载顺序执行;
async属性,表示后续文档的加载和执行与js脚本的加载和执行是并行进行的,即异步执行;defer属性,加载后续文档的过程和js脚本的加载(此时仅加载不执行)是并行进行的(异步),js脚本需要等到文档所有元素解析完成之后才执行,DOMContentLoaded事件触发执行之前。
CSS
CSS3中有哪些新特性
新增各种CSS选择器 (: not(.input):所有 class 不是“input”的节点)
- 边框:阴影box-shadow,圆角 border-radius
- 背景:backgroud-img, backgroud-color
- 2D转换,3D转换 transform
- 过渡
- 动画
- 媒体查询
- 多栏布局
- css选择器,盒模型
- 线性渐变
盒模型
盒模型都是由四个部分组成的,分别是margin、border、padding和content。
标准盒模型和IE盒模型
标准盒模型的width和height属性的范围只包含了content,
IE盒模型的width和height属性的范围包含了border、padding和content。
IE盒模型转化为标准盒模型: box-sizing:content-box
标准盒模型转化为IE盒模型:box-sizing:border-box
盒子水平垂直居中方法
2.
3.
5.
隐藏元素的方法有哪些
- 使用display: none; 隐藏dom;
- 使用visibility: hidden; 隐藏dom;
- 使用z-index: -888; 把元素的层级调为负数,然后其他元素覆盖即可;
- 使用opacity: 0; 把元素的透明度调为0,也可以达到隐藏;
- 使用固定定位position: absolute; 把元素定位到看不见的区域;
- 使用transform: scale(0, 0); 把元素缩放为0,也可以实现元素隐藏。
flex常用属性
display:flex;
flex-direction: column;或者flex-direction: row;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
- flex-direction属性决定主轴的方向(即项目的排列方向)。
- align-items属性定义项目在交叉轴上如何对齐。
- justify-content属性定义了项目在主轴上的对齐方式。
- flex-wrap属性定义,如果一条轴线排不下,如何换行。
- flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap
/* 拉伸,但是子盒子不要给高度,可以继承父盒子的高度 */
align-items: stretch;
display属性以及有几个方向
横向和纵向两个方向,行和列。
position属性
position: fixed;
position: relative;
position: absolute;
top: 0;
left: 0;
- 固定定位 fixed: 元素的位置相对于浏览器窗口是固定位置,即使窗口是滚动的它也不会移动。Fixed 定 位使元素的位置与文档流无关,因此不占据空间。 Fixed 定位的元素和其他元素重叠。
- 相对定位 relative: 如果对一个元素进行相对定位,它将出现在它所在的位置上。然后,可以通过设置垂直 或水平位置,让这个元素“相对于”它的起点进行移动。 在使用相对定位时,无论是 否进行移动,元素仍然占据原来的空间。因此,移动元素会导致它覆盖其它框。
- 绝对定位 absolute: 绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那 么它的位置相对于。absolute 定位使元素的位置与文档流无关,因此不占据空间。 absolute 定位的元素和其他元素重叠。
- 粘性定位 sticky: 元素先按照普通文档流定位,然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。而后,元素定位表现为在跨越特定阈值前为相对定 位,之后为固定定位。
- 默认定位 Static: 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声 明)。 inherit: 规定应该从父元素继承 position 属性的值。
transition和animation的区别
transition是过度属性,强调过度,它的实现需要触发一个事件(比如鼠标移动上去,焦点,点击等)才执行动画。它类似于flash的补间动画,设置一个开始关键帧,一个结束关键帧。
animation是动画属性,它的实现不需要触发事件,设定好时间之后可以自己执行,且可以循环一个动画。它也类似于flash的补间动画,但是它可以设置多个关键帧(用@keyframe定义)完成动画。
CSS样式优先级
选择器:
ID选择器(权重100,#demo)> 类选择器(10,.demo),伪类选择器(10,:link),属性选择器(10) > 伪元素选择器(1,::after),标签选择器(1) > 通配符(0,*),特殊的伪元素选择器(0,:not())
写法:
!important > 内联(行内)样式 (
伪类:四个伪类,link未访问,visited访问过后,hover移动,active点击下去时。顺序:link,visited,hover,active
BFC
块格式化上下文。
- 根元素或者其他包含它的元素
- 浮动元素,float不为none
- 绝对定位元素,position为absolute或者fixed
- 内联块:display:inline-block
- overflow:hidden,具有overflow不是visible
- 表格单元格,dispaly:table-cell
- display:flow-root
1px,1em,1rem,1vw / 1vh,rpx
1、1px
相对长度单位,像素 px 是相对于显示器屏幕分辨率而言的,一般电脑的分辨率有{19201024}等不同的分辨率,19201024 前者是屏幕宽度总共有1920个像素,后者则是高度为1024个像素。
2、1em
em 就是相对于自身字体 fontSize 的大小,如果自身指定 fontSize = 20px,父元素 fontSize = 30px,那么 1em = 20px;如果自身没有指定,则是继承来自于父元素的 fontSize,1em = 30px。
3、1rem
rem 是全部的长度都相对于根元素 fontSize 的大小,如果 的 fontSize = 20px,那么 1rem = 20px。
rem的计算方法:
假如设计图是按 640px 来设计的,那么我把设计图分成 10份(随你自己分),也就是 640px = 10rem,那么就是 1rem = 64px, 在根元素 上设置的 font-size 实际就是给网页的一个标准,它的px是多少,那么子级的 1rem 就等于多少。那么在 640px的屏幕下,根元素 的 font-size 就可以计算为 640/10,但是屏幕是不指定大小的,如果屏幕缩小的,那么根元素的值也要按百分比来缩小,如:屏幕如果缩到了一半 320,(320/640)*(640/10)(屏幕宽度/设计图) *(设计图/设计图的总分成)。
4、1vw / 1vh
相当于屏幕宽度 / 高度的 1%,不过,处理宽度的时候 % 单位更合适,处理高度的话 vh 单位更好。
5.rpx
rpx是解决自适应屏幕尺寸的尺寸单位,宽度为固定的750rpx。比如iPhone6的屏幕宽度是375px,那就是1px=2rpx。
前端的五种布局方法
1、传统布局(静态布局div): 以固定的px为单位
2、自适应布局:使用媒体查询
3、流式布局:用百分比定义宽度,高度一般以px为固定单位
4、响应式布局:媒体查询 + 百分比
5、弹性布局:伸缩布局和rem单位搭配使用
JS
JS的数据类型
基本类型
Number、String、Boolean、Null、undefined、Symbol
引用类型
Object、Date、Function、Array、RegExp正则
JS的类型检测
typeof
instanceof
Object.prototype.toString.call()
null和undefined的区别
1.undefined是由null派生出来的
2.null指对象的属性值为空。而undefined是一个变量的值为空,声明了但未赋值。
3.null的typeof为object,undefined的typeof为undefined
null == undefined ; null !== undefined
字符串和对象的相互转化
字符串转化为对象:JSON.parse()
对象转化为字符串:JSON.stringify()
什么是事件流
Dom事件流包括三个阶段:1.事件捕获阶段。2.目标阶段。3.事件冒泡阶段。
事件代理(又叫事件委托)
事件代理采取的是冒泡机制。子元素需要绑定的事件委托给父元素,减少Dom操作,提高性能。
阻止冒泡,阻止默认事件
阻止冒泡:ev.stopProragation();
IE阻止冒泡:ev.cancelBubble = true;
阻止默认事件:ev.preventDefault();
IE阻止默认事件: return value;
既能阻止冒泡,又能阻止默认事件:return false;
垃圾回收机制
由一个单独的进程访问的,由系统控制的,浏览器每隔一段时间会清理一次无用的变量或者方法的浏览器机制叫做垃圾回收机制。
什么是内存泄漏
一个函数的作用域始终占用着另外一个函数的作用域中的变量,导致另一个函数的作用域始终占用着系统的内存空间,始终无法释放。假如同时开启很多脚本,当达到一定的程度的时候,会导致系统崩溃。
作用域
作用域:函数和变量可以访问的区域。有全局作用域和局部作用域。
作用域链
作用域链: 当需要从局部函数查找某一个方法和属性的时候,如果当前作用域没有找到,就会向外查找上层作用域,直到全局函数,这就形成了作用域链。
原型
每个 class都有显示原型 prototype
每个实例都有隐式原型 _ proto_
实例的_ proto_指向对应 class 的 prototype
原型链
原型链: 当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念
特点: JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。
闭包
闭包是指有权在一个函数内部去访问另一个函数作用域中的变量,并在这个函数中调用。(会导致内存泄漏,本身无法解决,但可以避免)
闭包形成的条件
- 函数的嵌套
- 内部函数引用外部函数的局部变量,延长外部函数的变量生命周期
闭包用途(好处)
- 可以让一个变量长期在内存中不被释放
- 避免全局变量的污染,和全局变量不同,闭包中的变量无法被外部使用
- 私有成员的存在,无法被外部调用,只能直接内部调用
闭包缺点
会导致函数的变量一直保存在内存中,过多的闭包可能会导致内存泄漏
内存泄漏
常见的内存泄漏:
1.意外的全局变量。
2.如果setTimeout的第一个参数使用字符串而非函数,会引发内存泄漏。
3.闭包、控制台日志、循环等。
内存泄漏的解决方法:立即执行函数可以解决内存泄漏。
闭包实例:防抖节流
//防抖:
const debounce = (fn, delay = 1000) => {
let timer;
return function() {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
};
}
//节流:
const throttle = (fn, delay) => {
let valid = true;
return function(){
if(valid) {
setTimeout(()=> {
fn.apply(this, arguments);
valid = true;
}, delay)
valid = false;
}
}
}
面向对象
面向对象其实是一种思想,是把事物封装成对象,通过操作对象的属性和方法来解决问题。
面向对象的三大特征:封装,继承和多态。
继承:父元素中定义相同的属性和方法,所有的子类不需要重新定义这些属性和方法。
继承方式:原型链继承,构造函数继承,组合继承,原型式继承,寄生式继承,拷贝继承。
如何创建一个对象
1.通过对象字面量的方式
2.通过new的方法创建
3.通过Object.creat()
虚拟DOM
虚拟DOM就是用JS对象结构表示DOM结构,然后再用这个树构建真正的DOM树放到页面中去,当我们这个虚拟DOM以JS结构的形式存在,计算性能较好,并且由于减少了实际DOM操作的次数,性能会有较大的提升。
优点:因为Javascript的运算速度远大于DOM操作的执行速度,因此,运用patching算法来计算出真正需要更新的节点,最大限度地减少DOM操作,从而提高性能。减少了浏览器的回流和重绘
缺点:首次显示要慢些:首次渲染大量DOM时,由于多了一层虚拟DOM的计算, 会比innerHTML插入慢。
new运算符的实现机制
- 首先创建了一个新的空对象
- 设置原型,将对象的原型设置为函数的prototype对象。
- 让函数的this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
- 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。
强制类型转换和隐式类型转换
强制类型转换:
1.parseInt(),把其他类型强制转换成数字类型,int类型
2.parseFloat(),把其他类型强制转换成数字类型,float类型
3.Number(),把其他类型强制转换成数字类型
4.Boolean(),把其他类型强制转换成布尔类型
5.String(),把其他类型强制转换成字符串类型
隐式类型转换:
- +,-,*,/ 操作符的隐式类型转换
- 逻辑运算符 || &&
- 一元运算符 + -
空字符串转化为0,非空字符串转化为1
0转化为布尔类型false,除了0以外的数都是true
{}+[] = 0,[]+{} = [Object Object]
call,apply,bind的区别
它们都可以放变this指向。
区别: call理论上有无数个参数,第一个参数数是要改变的this指向的对象的对象名,第二参数是要改变的对象的属性名…,第n参数都是要改变的对象的属性名。
而apply只有两个参数,第一个数是要改变this指向的对象的对象名,第二参数是要改变的属性名整合成的一个数组。
bind的用法与apply一样,区别在于bind返回的是一个函数体,只有在调用的时候才会执行这个函数体。
this指向
1.创建一个空对象
2.改变this指句, 将构造函数的原型对象指向该空对象的原型
3.解释执行构造函数中的代码,将属性和方法添加到空对象中
4.看构造函数是否返回对象,如果是,那么new操作符返回的对象就是构造函数返回的对象,如果没有,那么new操作符返回的对象就是刚创建的那个对象。
AJAX实现原理
AJAX就是浏览器提供API,通过JS调用,从而实现通过代码实现请求和响应。
实现原理:
1.创建一个XMLHttpRequest
var xhr = new XMLHttpRequest()
- open三个参数,分别是get/post , url地址 ,是否异步(true/false)
xhr.open("GET","http://-----",false)
3.监听 onreadystatechange,判断readystate属性(五个值,0,1,2,3,4),判断当值为4的时候为成功 readystate == 4 && state == 200
xhr.onreadystatechange = function(){
if(xhr.readystate != 4){
return
}
if(xhr.readystate == 4 && xhr.state == 200){
console.log(xhr.responseText)
}
}
4.敲回车,send发送请求
xhr.send()
Ajax的优势:
①减轻了客户端的内存消耗,Ajax的理念是"按需取数据"。
②无刷新更新页面,提高用户体验。
③将一部分的工作量嫁到客户端,减轻服务器压力
ajax嵌套问题
一个请求需要另一个请求返回的结果作为参数时,就是ajax嵌套,会引起回调地狱的问题,上一个ajax报错,下面的都无法执行。解决方法:使用promise来解决回调地狱的问题。
Axios
- Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。
- Axios有那些特性?
1、在浏览器中创建 XMLHttpRequests
2、在node.js则创建http请求
3、支持Promise API
4、支持拦截请求和响应
5、转换请求和响应数据
6、取消请求
7、自动转换成JSON数据格式
8、客户端支持防御XSRF - 执行get请求,有两种方式:params 是用于拼接 url 的,get 请求传参就是拼到 url 中,而 data 是放在 request body 中的,用于 post 请求
Axios和Ajax的区别
axios是通过Promise实现对ajax技术的一种封装,简单来说就是ajax技术实现了局部数据的刷新,axios实现了对ajax的封装,axios有的ajax都有,ajax有的axios不一定有。
map 跟 forEach 的区别
map有返回值 forEach 没有返回值
遍历数组的方法
常用的操作数组的方法
常用的操作字符串的方法
ES6
var/let/const
- var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。 let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。 const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,且不能修改。
- var可以先使用,后声明,因为存在变量提升;let必须先声明后使用。
- var是允许在相同作用域内重复声明同一个变量的,而let与const不允许这一现象。
- 会产生暂时性死区
var tmp = 123;
if (true) {
// 存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,
所以在let声明变量前,对tmp赋值会报错
tmp = 'abc'; // ReferenceError
let tmp;
}
js和ts
TS 拓展了 JS 的一些功能,解决了 JS 的一些缺点,TS完全兼容JS, TS 是 JS 的超集。js是弱类型语言,而ts是强类型语言,对数据类型的定义要求比较严格。js在运行的时候发现错误,而ts在编译期间就会发现并纠正错误。js的变量可以被赋予不同类型的值,而ts不允许改变变量的数据类型。
TS 的缺点: 1:不能被浏览器理解,需要被编译成 JS
2:有学习成本,写习惯了 JS 的我们要上手需要花时间去理解,而且 TS 中有一些概念还是有点难,比如泛型。
ES6常用的新特新
- 新增symbol类型 表示独一无二的值,用来定义独一无二的对象属性名;
- const/let 都是用来声明变量,不可重复声明,具有块级作用域。存在暂时性死区,也就是不存在变量提升。(const一般用于声明常量);
- 变量的解构赋值(包含数组、对象、字符串、数字及布尔值,函数参数),剩余运算符(…rest);
- 模板字符串(${data});
- 扩展运算符(数组、对象);
- 箭头函数;
- Set和Map数据结构;
- Proxy/Reflect;
- Promise;
- async函数;
ES6操作数组的方法
https://blog.csdn.net/qq_58340302/article/details/126429430
js遍历对象的方法
https://blog.csdn.net/huang_wei_xiong/article/details/124226161
Vue2.0
Vue 的生命周期
Vue2.0
- create阶段:vue实例被创建 。
beforeCreate: 创建前,此时data和methods中的数据都还没有初始化;
created: 创建完毕,data中有值,未挂载。 - mount阶段: vue实例被挂载到真实DOM节点。
beforeMount:可以发起服务端请求,去请求数据 ,数据更新时调用;
mounted: 此时可以操作Dom。 - update阶段:当vue实例里面的data数据变化时,触发组件的重新渲染。
beforeUpdateupdated: s数据更新时调用;
updated: 数据更新完毕,Dom节点也已经更新 - destroy阶段:vue实例被销毁。
beforeDestroy:实例被销毁前,此时可以手动销毁一些方法 ;
destroyed:完全销毁,所有的东西都会被解绑,事件以及事件监听都会被移除,子实例也会被销毁。
Vue3.0
setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
onBeforeMount() : 组件挂载到节点上之前执行的函数。
onMounted() : 组件挂载完成后执行的函数。
onBeforeUpdate(): 组件更新之前执行的函数。
onUpdated(): 组件更新完成之后执行的函数。
onBeforeUnmount(): 组件卸载之前执行的函数。
onUnmounted(): 组件卸载完成后执行的函数
onActivated(): 被包含在中的组件,会多出两个生命周期钩子函数。被激活时执行 。
onDeactivated(): 比如从 A组件,切换到 B 组件,A 组件消失时执行。
onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数
Vue2--------------vue3
beforeCreate -> setup()
created -> setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
activated -> onActivated
deactivated -> onDeactivated
errorCaptured -> onErrorCaptured
Vue 的通讯方式
- 父组件向子组件传值:在父组件中自定义组件进行传值,在子组件中用props进行接收。pros与data同级,里面是一个数组,内容就是自定义属性的名字。
- 子组件向父组件传值:用的是发布订阅者模式。子组件用this. e m i t ( " 事件名 " ,要传递给父组件的数据 ) , t h i s . emit("事件名",要传递给父组件的数据),this. emit("事件名",要传递给父组件的数据),this.emit发布一个自定义事件,接收俩参数,第一个参数是事件名,第二个参数是要传递的数据。父组件要在调用子组件的标签中用@事件名= "回调函数"触发自定义事件。
- 事件车:公共事件总线eventBus,实际上就是创建一个vue实例,通过一个空的vue实例作为桥梁实现vue组件之间的通信(任何两个都可以)。Bus. e m i i t ( " c l i c k " , d a t a ) 传, B u s . emiit("click",data)传,Bus. emiit("click",data)传,Bus.on(“click”,target)
- Vuex:状态管理工具。值一旦被修改,所有的引用该值的地方都会自动刷新。
五大核心:
①state :保存数据,想到于data,页面中用this. s t o r e . s t a t e 来获取定义的数据。② g e t t e r s :计算属性,也是依赖于缓存,缓存里面的值发生变化了,才会重新计算。 g e t t e r s 方法会接收一个参数,就是 s t a t e 对象。页面中属性名获取用 t h i s . store.state来获取定义的数据。 ②getters : 计算属性,也是依赖于缓存,缓存里面的值发生变化了,才会重新计算。getters方法会接收一个参数,就是state对象。页面中属性名获取用this. store.state来获取定义的数据。②getters:计算属性,也是依赖于缓存,缓存里面的值发生变化了,才会重新计算。getters方法会接收一个参数,就是state对象。页面中属性名获取用this.store.getters.getStateCount
③Mutation: 修改state的值的唯一方法。要在methods里面使用,this. s t o r e . c o m m i t ( " 方法名 " ) ④ A c t i o n s : ( 相当于 m o t h o u s ) 方法对象的集合。在 a c t i o n s 里面提交一个 m u t a t i o n s 再去修改状态值。在页面中通过 t h i s . store.commit("方法名") ④Actions: (相当于mothous)方法对象的集合。在actions里面提交一个mutations再去修改状态值。 在页面中通过this. store.commit("方法名")④Actions:(相当于mothous)方法对象的集合。在actions里面提交一个mutations再去修改状态值。在页面中通过this.store.dispath(“actions里面的方法名”)提交Actions,在actions通过actions方法里面的参数名.commit(“cutations里面的方法名”)。获取用this.$store.state.count
⑤model - 跨组件通讯 a t t r s 、 attrs、 attrs、listeners Provide、inject
vue的数据双向绑定
原理:数据劫持结合发布订阅者模式。数据被获取或者修改的时候,会触发监听者对应的回调函数,进行一些逻辑处理。
具体怎么被监听的:vue2.0用object.defineproperty()方法监听的是对象某个属性的获取修改,Vue3.0用的是proxy反向代理,监听的是整个对象属性的修改。
vue的计算属性computed与监听器watch的区别
watch 属性监听 是一个对象,键是需要观察的属性,值是对应回调函数,主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作,监听属性的变化,需要在数据变化时执行异步或开销较大的操作时使用
computed 计算属性 属性的结果会被缓存,当computed中的函数所依赖的属性没有发生改变的时候,那么调用当前函数的时候结果会从缓存中读取。除非依赖的响应式属性变化时才会重新计算,主要当做属性来使用 computed中的函数必须用return返回最终的结果 computed更高效,优先使用。data 不改变,computed 不更新。
使用场景computed:当一个属性受多个属性影响的时候使用,例:购物车商品结算功能 watch:当一条数据影响多条数据的时候使用,例:搜索数据
v-if 和 v-for 的优先级
在Vue2.0中,v-for的优先级是高于v-if的
当vue处理指令时,v-for比v-if具有更高的优先级,通过v-if移动到容器元素,不会再重复遍历列表中的每个值,取而代之的是,我们只检查它一次,且不会再v-if为否的时候运行v-for。
而Vue3.0中,v-if的优先级是高于v-for的 (官网上说到这样v-if将没有权限访问到v-for里面的变量)
因此我们不推荐v-for和v-if一起使用,可以在v-for的外面新增一个模板标签template,在template上使用v-if。因为如果两者同时出现的话,那每次循环都会执行v-if,会很浪费性能。
v-for中key的作用
- key的作用是为了在diff算法执行时更快的找到对应的节点,提高diff速度,更高效的更新虚拟DOM;
- Vue在patch过程中判断两个节点是否是相同节点,key是一个必要条件,渲染一组列表时,key往往是唯一标识,所以如果不定义key的话,Vue只能认为比较的两个节点是同一个,哪怕它们实际上不是,这导致了频繁更新元素,使得整个patch过程比较低效,影响性能;
- 从源码中可以知道,Vue判断两个节点是否相同时主要判断两者的key和元素类型等,因此如果不设置key,它的值就是undefined,则可能永 远认为这是两个相同的节点,只能去做更新操作,这造成了大量的dom更新操作,明显是不可取的。
注意:v-for中key一般不以索引作为key值
假如我们在遍历的数组的最后面加一条数据,那么索引加一,只需要改变一次即可。但是如果我们在数组的第一个加一条数据,那么新加的数据的索引为0,后面所有的数据的索引都会加一都会发生改变,那么需要重新一个一个遍历,所有的算法都要重新来一遍,消耗性能。但是如果key是一个code,通过匹配code,那么无论数据加到哪里,都只改变这一条数据。
$nextTick
- nextTick是Vue提供的一个全局API,是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用$nextTick,则可以在回调中获取更新后的DOM;
- Vue在更新DOM时是异步执行的。只要侦听到数据变化,Vue将开启1个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个watcher被多次触发,只会被推入到队列中-次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作是非常重要的。nextTick方法会在队列中加入一个回调函数,确保该函数在前面的dom操作完成后才调用;
- 比如,我在干什么的时候就会使用nextTick,传一个回调函数进去,在里面执行dom操作即可;
- 我也有简单了解nextTick实现,它会在callbacks里面加入我们传入的函数,然后用timerFunc异步方式调用它们,首选的异步方式会是Promise。这让我明白了为什么可以在nextTick中看到dom操作结果。
为什么vue里面的data是个函数呢?
<script>
export default {
name: 'BtnCount',
data () {
return {
count: 0
}
}
}
</script>
1.如果data是一个函数的话,这样每复用一次组件,就会返回一份新的data(类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据)。之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响。
2.Object是引用数据类型,里面保存的是内存地址,单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。当data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,就不会相互影响。这都是因为js本身的特性带来的,跟vue本身设计无关。
所以说vue组件的data必须是函数。
vue中动态改变对象或是数组数据,页面怎样能够实时刷新数据?
- 改变引用
data:{
obj:{
name:'gou',
age:18
}
},
直接更换变量引用
obj = {
name:'gou',
age:18,
address:'beijin'
}
- 数组使用数组函数
pop、push、splice,shift。。。。。
由于 JavaScript 的限制,Vue 不能检测以下数组的变动:
当你利用索引直接设置一个数组项时,
例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,
例如:vm.items.length = newLength
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
为了解决问题,可以使用如下方法:
修改第二个元素的值
list[1,2,3,4,5]
list.splice(1,1,5)
或者如需要修改数组length
arr.splice(newLength)
- vue的set函数,使用$set这个api修改的数据会为其添加响应式getter和setter让其拥有数据响应的特性
vm.$set(要操作的对象或数组, 要新增或者修改的数组或对象key, 对应的值)
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的
obj:{
name:'gou',
age:18
}
},
list = [1,2,3,4,5]
vm.$set(this.list,1,5);
vm.$set(vm.obj,'address','beijing')
页面视图不刷新怎么解决?
我们在开发过程中会碰到数据更新,但是视图并未改变的情况,情况如下:
第一种:动态给对象新增属性或者删除属性是不会触发视图刷新的,Vue识别不到;
第二种:通过数组下标修改数组中的元素或者手动修改数组的长度,Vue识别不到;
解决方法:
1:静默刷新(使用v-if的特性)
在修改值之后将元素销毁,然后在修改后的下一次DOM渲染完成时再显示出来,这样就会触发组件重新加载data的数据进行渲染,data中被修改的数据才是最新的。
2:Vue.$set(官方推荐)
使用这个api修改的数据会为其添加响应式getter和setter让其拥有数据响应的特性
vm.$set(要操作的对象或数组, 要新增或者修改的数组或对象key, 对应的值)
3.Object.assign(使用修改栈能触发视图更新的特性)
Object.assign能拷贝合成一个新对象,所以我们只需要将要修改的值合并成一个新对象然后赋值给data中的对象或数组,这样栈的指向被修改了.触发视图更新
4.对于数组还可以使用splice方法
Vue对于数组的操作能识别变化的api包括push()、pop()、shift()、unshift()、splice()、sort()、reverse()这些都可被vue监测到
keep-alive的实现
作用:实现组件缓存。
keep-alive是vue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。可以设置以下属性:include - 字符串或正则表达式,只有名称匹配的组件会被缓存。exclude - 字符串或正则表达式,任何名称匹配的组件都不会被缓存。max - 数字,最多可以缓存多少组件实例。
钩子函数:会在activated和deactivated这两个生命周期中进行数据变更,”activated “组件渲染后调用,
”deactivated“组件销毁后调用。
应用场景:填写表格的时候,假如要填写银行卡号,切出去找号码的时候再回来之前填写的信息都没有了,还需要重新写。加上keep-alive标签,当你访问了一个已经加入缓存的页面,本身的生命周期就不会再执行了,而是去执行新的生命周期,新增了两个生命周期activated和deactivated。
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
## Vuex
Vuex 是一个专为 Vue 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。
Vuex 的状态存储是响应式的;当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新
改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation, 这样使得我们可以方便地跟踪每一个状态的变化 Vuex主要包括以下几个核心模块:
1. State:定义了应用的状态数据
2. Getter:在 store 中定义“getter”(可以认为是 store 的计算属性),就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来, 且只有当它的依赖值发生了改变才会被重新计算
3. Mutation:是唯一更改 store 中状态的方法,且必须是同步函数
4. Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作
5. Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中
## vue页面跳转
常用template中的写法:router-link to
```javascript
<router-link to = "要跳转的页面地址">--</router-link>
vue-router 怎么传参
1.id传参
//路由配置
{
path: '/orderDetail/:id',
name: 'orderdetail',
component: () => import('../components/orderDetail.vue'),
meta: { showTabbar: false}
}
this.$router.push({path:`/orderDetail/${this.id}`})
2.query传参
this.$router.push({path:`/orderDetail`,query:{id:this.id}})
3.pramas传参
this.$router.push({name:`orderdetail`,params:{id:this.id}})
query和params路由传参的区别:
1.query要用path来引入,params需要用name来引入
接收参数: this.$route.query.name和this.$route.params.name
2.展示上,query能看到后面的参数,而params看不到后面的参数
路由取值:{{this.$route.params.参数名}}
路由守卫
vue中常见的事件修饰符
1.prevent:阻止默认事件(常用)
changes(e){
e.preventDefault()
}
- stop:阻止事件冒泡(常用)
<button @click.stop="changes">点我</button>
- once:事件只触发一次(常用)
<button @click.once="changes">点我</button>
4.captrue:使用事件的捕捉模式(不常用)
5.self:只有event.target是当前操作的元素时才触发事件(不常用)
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕(不常用)
例:点击超链接后会弹窗然后跳转到指定的url,那么我们又想阻止冒泡,又想阻止默认行为,该怎么办呢?
可以多个事件修饰符一起使用:@click.prevent.stop,页面上只会弹窗就不跳转了
<a href="http://www.baidu.com" @click.prevent.stop="changes">点我</a>
vue生命周期中,如果发一个异步请求,应该放在哪里?
一般放到created,如果要实现页面加载完之后的操作,就放到mounted里面。
异步:$nextTick以及promise的两种方法。
$nextTick
$nextTick接收一个函数作为参数,在下一个时间片执行该函数的方法。或者说在浏览器初次加载或因为某些操作导致Dom树渲染,让所有的Dom节点加载完毕之后执行的回调。通常用于执行一个方法时,Dom节点还未加载成功时。
this.$nextTick(()=>{})
promise
promise是为了解决回调地狱的问题,因为promise里面是异步的,后台请求数据是同步的,互不影响。首先创建一个promise对象,接收一个函数作为参数,函数里面有两个参数,分别是resolve,reject。promise内部有三种状态,pengding是初始状态,resolved是成功时候的状态,rejected是失败时候的状态。方法有.then,成功时候调用的方法,返回的依然是一个promise对象,.catch失败的时候调用的方法,.all,只有所有参数状态都成功时才会调用,.race只要一个状态成功,promise.race就会变成roselve
new Promise((resolve,reject)=>{
setTmieout(()=>{
console.log("执行完成");
resolve("数据");
},2000);
}).then((data)=>{
console.log("resolve",data);
}).catch((reson)=>{
console.log("reject",reson);
})
EventLoop( js的执行机制)
JS是单线程的,为了防止一个函数执行时间过长阻塞后面的代码,所以会先将同步代码压入执行栈中,依次执行,将异步代码推入异步队列,异步队列又分为宏任务队列和微任务队列,因为宏任务队列的执行时间较长,所以微任务队列要优先于宏任务队列。微任务队列的代表就是,promise的.then方法,.catch方法,process.nextTick,宏任务的话就是包括整体代码script,setTimeTou,setInterval
js的执行机制:
先执行主线程代码(js里面从上到下按顺序执行代码的过程),然后执行微任务,再执行宏任务。其中可能会碰到微任务,宏任务嵌套的问题,递归执行,先执行微任务。
promise本身没有特殊性,是主线程代码,本身是一个同步方法,promise的.then和.catch方法是微任务,是异步方法。
同步,异步
同步:在任务队列中,前一个执行完之后,后一个才执行。
异步:在任务队列中,同时执行任务。
Vue2和Vue3区别
vue经历从2.0到3.0更新之后,变得更轻,更快,使⽤起来更加⽅便,每⼀次的版本迭代都是对上⼀个版本的升级优化,不管 是对于我们开发者还是对于⽤户体验都是不断地在越来越⽅便。
区别:
1.包括数据监听,双向绑定,⽣命周期,
从数据双向绑定来说,vue2 的双向数据绑定是利⽤Object.definePropert()对数据进⾏劫持 结合 发布订阅模式的⽅式来实现的。vue3 中使⽤了 es6 的 ProxyAPI 对数据代理,通过 reactive() 函数给每⼀个对象都包⼀层 Proxy,通过 Proxy ,劫持整个对象,并返回一个代理对象;。
2.
vue3还新增了⼀些内置组件和⽅法,⽐如setup函数,对与插件或对象的⼀ 个按需引⼊,新加⼊了 TypeScript等。
Vue2.x中new出的实例对象,所有的东西都在这个vue对象上,这样其实⽆论你⽤到还是没⽤到,都会跑⼀遍,这样不仅提⾼了性能消耗,也增加了⽤户加载时间。
⽽vue3.0中可以⽤ES module imports按需引⼊,如:keep-alive内置组件、v-model指令,等等,不仅我们开发起来更加的便捷,减少 了内存消耗,也同时减少了⽤户加载时间,优化⽤户体验。
3.声明周期的变化
4.获取props
vue2:console.log(‘props’,this.xxx)
vue3:setup(props,context){ console.log(‘props’,props) }
5.给父组件传值emit
vue2:this.$emit()
vue3:setup(props,context){context.emit()}
vue3.0中的ref和reactive的区别
ref 和 reactive 都是用来定义响应式数据的 reactive更推荐去定义复杂的数据类型 ref 更推荐定义基本类型。
ref操作数据需要.value,template模板中不需要。reactive都不需要.value
ref虽然定义的是基本数据类型,但是ref也可以定义数组和对象,ref转化数据只有一层,ref只能监听元素本身的变更,而无法监听数组元素数量的更改。而reactive可以监听多层。一般数组用ref,对象用reactive定义。
用 reactive() 创建的响应式对象,整个对象是响应式的。而对象里的每一项都是普通的值 当你把它用展开运算符展开后 整个对象的普通值都不是响应式的。而用 ref() 创建的响应式的值,本身就是响应式的 并不依赖于其他对象。
token有效期
token有效期通过第三方鉴权服务由后端返回,有效期过期之后退出登录。判断token有效期是否过期。token获取时间,过期时间以及token时长。用token过期时间与token获取时间的时间差与token时长做比较,就可以知道token是否过期。
其他
git 常用命令
- git clone
- git add .
- git commit -m
- git push
- git pull
- git branch 查看本地分支
- git branch -a 查看远程分支
- git branch -d xxx 删除分支
- git checkout xxx 切换分支
- git checkout -b xxx 新建分支并且切换到改分支
- git branch -m 旧分支名 新分支名 分支重命名
- git status 查看修改的文件
- git merge 合并分支
- git checkout -b xxx origin/xxx 拉去远程分支
- git log 查看提交记录
运用:1.切换到新的分支:
git branch -a
git pull
git checkout --track origin/分支名
2.一个分支上的代码修改了,怎么同步到另外一个正在开发的分支上。
如修改了master分支上的代码,正在开发的dev分支也想拉取修改的master分支
git checkout master
git branch -a
git add .
git commit -m " "
git pull
git push origin master
//然后合并到dev分支上
git checkout dev
git pull
git merge master
git push origin dev
3.把当前分支的代码推到指定的分支上
git add .
git commit -m " "
git pull
git push origin 现分支:要推到的分支
4.解决git 冲突
①git stash 暂存本地代码
②git pull 代码重新拉取
③git stash pop 合并冲突代码,git 会将冲突代码展示出来
④手动合并冲突
优化项目
1.分隔代码(通过webpack魔法注释):Vue中运用import的懒加载语句以及webpack的魔法注释,在项目进行webpack打包的时候,对不同模块进行代码分割,在首屏加载时,用到哪个模块再加载哪个模块,实现懒加载进行页面的优化。魔法注释/* webpackChunkName:“lodash” */的做用## 标题
2.提取公共包:使用webpack的splice chunk属性来提取公共包,比如echars
3.图片懒加载(组件v-lazy),精灵图等
4.代码压缩,去除console.log(uglifyjs-webpack-plugin插件),使用cdn服务器等
代码层面
- 减少dom操作
- 避免eval和function
- 减少数组和对象的深层查找
- 尽量避免+拼接符
- 避免作用域链的查找
页面优化
- 减少http请求
- 资源合并压缩
- 图片懒加载,精灵图
- 外部脚本置底,内部脚本异步执行
降低页面加载时间的方法
- CDN缓存
- 精灵图
- 压缩js,css代码
- 服务器开启gzip压缩
- 页面懒加载,图片懒加载
webpack
常用Loader
raw-loader:加载文件原始内容(utf-8)
file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件 (处理图片和字体)
source-map-loader:加载额外的 Source Map 文件,以方便断点调试
svg-inline-loader:将压缩后的 SVG 内容注入代码中
image-loader:加载并且压缩图片文件
json-loader 加载 JSON 文件(默认包含)
babel-loader:把 ES6 转换成 ES5
ts-loader: 将 TypeScript 转换成 JavaScript
awesome-typescript-loader:将 TypeScript 转换成 JavaScript,性能优于 ts-loader
sass-loader:将SCSS/SASS代码转换成CSS
css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS
postcss-loader:扩展 CSS 语法,使用下一代 CSS,可以配合 autoprefixer 插件自动补齐 CSS3 前缀
vue-loader:加载 Vue.js 单文件组件
常用的Plugin
define-plugin:定义环境变量 (Webpack4 之后指定 mode 会自动配置)
ignore-plugin:忽略部分文件
html-webpack-plugin:简化 HTML 文件创建 (依赖于 html-loader)
web-webpack-plugin:可方便地为单页应用输出 HTML,比 html-webpack-plugin 好用
uglifyjs-webpack-plugin:不支持 ES6 压缩 (Webpack4 以前)
terser-webpack-plugin: 支持压缩 ES6 (Webpack4)
webpack-parallel-uglify-plugin: 多进程执行代码压缩,提升构建速度
mini-css-extract-plugin: 分离样式文件,CSS 提取为独立文件,支持按需加载 (替代extract-text-webpack-plugin)
serviceworker-webpack-plugin:为网页应用增加离线缓存功能
clean-webpack-plugin: 目录清理
oader 和 plugin 的区别
Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作。
Plugin 就是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
Loader 在 module.rules 中配置,作为模块的解析规则,类型为数组。每一项都是一个 Object,内部包含了 test(类型文件)、loader、options (参数)等属性。
Plugin 在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入