.4.22
这段时间准备换工作,陆陆续续面了一下外包和正经公司,总结一下遇到的面试问题和答案。持续更新。
本文只记录重点答案,每条下面会贴一个详细讲解这个问题的链接,想要详细了解问题答案及原理请阅读链接。
一、css篇
必问题:
1.讲一下盒模型。
盒模型分为标准盒模型和怪异盒模型(也称IE盒模型)。
标准盒模型:包括border+content.
怪异盒模型:包括border+content+padding.
标准盒模型变为怪异盒模型的方法:box-sizing:border-box;
详细讲解链接:css的两种盒模型_zwkkkk1的博客-CSDN博客_盒模型
2.讲一下定位。
定位常用三种。
1.relative:相对定位,根据初始位置的相对位置来移动。
2.absolute:绝对定位,向上寻找第一个设置了定位(除了static以外)的父元素位置来移动,如果父元素都没有设置定位,就根据根元素来定位。如果父元素设置了static,子元素会继续追溯到祖辈元素一直到body。
3.fixed:绝对定位,根据浏览器窗口进行定位,无论浏览器怎么滚动移动,位置都不变。
以上三种都可以通过z-index进行层次分级。
定位详解:position 属性的常用的5种取值_kaze_001的博客-CSDN博客_position的属性值有哪些
3.Flex布局
flex是弹性布局,通常用来解决垂直居中的问题。
设为Flex布局以后,子元素的float、clear和vertical-align属性将失效,所有子元素自动成为容器成员。
需要记住的几个重要属性:
1.justify-content:定义了项目在主轴上的对齐方式
2.align-items:定义项目在交叉轴上如何对齐。
3.align-content:定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
4.flex-direction:决定主轴的方向
5.flex:1——一个简写属性,用来设置 flex-grow, flex-shrink 与 flex-basis。flex: 1; === flex: 1 1 0;
这个布局复杂,功能太多,具体看详解
详解:Flex 布局语法教程 | 菜鸟教程
4.垂直居中的几种方式。
宽高不固定的方法:
1.position: absolute;top: 0;bottom: 0;right: 0;left: 0;margin:auto;
2.position: absolute;top:50%;left:50%;width:100%;transform:translate(-50%,-50%);
3.给父元素加 display: flex; justify-content:center; align-items: center;
宽高固定的方法,以宽高200px为例
1.position: absolute;top: 50%;left: 50%;margin-top: -100px;margin-left: -100px;
2.position:absolute; top: calc(50% - 100px); left: calc(50% - 100px);
更多方式:css垂直水平居中 - china_coding - 博客园
5.css中常用的长度单位以及它们的区别
1.px:最常见的像素单位
2.rem:根据根元素的字体尺寸来计算的单位。 例:根元素尺寸为12px,那么2rem=12*2=24px;
3.em:根据父的字体尺寸来计算的单位。 例:父尺寸为12px,那么2em=12*2=24px;
4.rpx:跟rem类似,常用于移动端,可以适配各个分辨率。
5.vw/vh:根据浏览器视窗计算的宽度/高度。1vw/1vh=浏览器视窗的1/100;
6.%:根据其父元素的样式来计算该值
有问到过一两次的问题:
1.BFC是什么?
BFC:块级格式化上下文,一个BFC区域包含创建该上下文元素的所有子元素,但是不包括创建了新的BFC的子元素的内部元素.每一个BFC区域都是独立隔绝的,互不影响。
使用BFC可以解决外边距塌陷的问题、清除浮动。
成为BFC必须满足以下几种条件之一
1.根元素
2.float除了none以外的设置
3.overflow:hidden|auto|scroll
4.table:table-tell
5.flex布局
6.display:inline-block
BFC详解:BFC是什么?10 分钟讲透BFC 原理
2.怎么画一条0.5px的线
1.transform: scale(0.5,0.5);
2.height: 1px; background: none; box-shadow: 0 0.5px 0 #000;
参考:如何画一条0.5px的线_一月清辉的博客-CSDN博客_画一条0.5px直线
3.左侧固定,右侧宽度自适应的写法
1. calc计算宽度
.left{width:300px;}.right{width:calc(100% - 300px)}
2.浮动+BFC原理
.left{width:300px;float:left;}.right{overflow:hidden}
3.定位加margin
.left{width:300px;position: absolute;left: 0;top:0;}.right{margin-left:100px;}
4.flex布局
父元素:{display: flex;}.left{flex:0 1 300px;} //第三个属性就是左边的固定宽度.right{flex:1;}
更多写法:css实现两栏布局,左侧固定宽,右侧自适应的7中方法 - 前端_奔跑的蜗牛 - 博客园
4.@import 和link的区别
1.link是html标签,而@import是css提供的。
2.@import在ie5以下有兼容问题,link没有。
3.link和页面同时加载,@import要等到页面全部下载完才加载。
4.用js控制样式时只能控制link标签里的样式,@import不是dom可以控制的。
参考链接:link和import的区别_高先生的猫的博客-CSDN博客_link和import的区别
二、html篇
必问题:
1.html5新特性
新特性有很多,以下几个是必须答出来的常用重点:
1.sessionstorage和localstorage。
2.canvas绘画
3.新增语义化标签:<hearder><footer><nav>等
4.新增音视频标签<audio><video>
5.WebSocket实时更新。
6.内联SVG
7.地理定位功能getloaction
详解:html5的新特性有哪些-H5教程-PHP中文网
2.cookie、sessionStorage和localStorage的区别
cookies:本地存储,很小,只有4k大小,会传给服务器,只要设置一次后,过期时间前的请求头里会一直携带cookies。可以设置很长的存储时间。可以设置限制放在哪些路径下。
设置路径详解:Cookie 有效路径 Path 的设置_少年西西的博客-CSDN博客_cookie设置路径
localStorage:和cookies基本相同,不同点为不会将数据传输给服务器,仅在本地存储。并且比较大,有5m大小。
sessionStorage:和localStorage基本相同,不同点为——只要当前会话窗口关闭,数据就消失。
详解:cookies、sessionStorage和localStorage解释及区别_前端小99的博客-CSDN博客_cookie localstorage session
有可能问:
1.严格模式和混杂模式的区别?
严格模式:更规范,对变量命名要求严格,不可以出现class/export/public之类的变量名。调用构造函数时如果不用new,那么构造函数会指向undefined。不允许变量提升,会报错。以浏览器支持的最高标准运行。
混杂模式:向后兼容,模拟老式浏览器,防止浏览器无法兼容页面。
严格模式详解:JavaScript 严格模式(use strict) | 菜鸟教程
三、JavaScript篇
必问题:
1.js的数据类型有哪些?哪些是引用类型,哪些是基础类型?
基础类型:字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol(es6新增的类型)
引用类型:对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。
参考:JavaScript 数据类型 | 菜鸟教程
2.原型和原型链是什么?显式原型和隐式原型是什么?
原型就是prototype,通过它,我们可以实现对象的属性继承。
当一个函数被用作构造函数来创建实例时,这个函数的prototype属性值会被作为原型赋值给所有对象实例。这个原型上挂载的所有变量和方法都会被它的对象实例所继承。这个prototype就是显式原型。
而每个引用这个构造函数的实例,会有
都有一个__proto__,也就是隐式原型
属性,__proto__中有一个constructor
属性,它指向自己构造函数的prototype。
当访问一个对象的某个属性时,会先在这个对象本身的属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。
它会一直往上层查找,直到到null还没有找到,则返回undefined。
资料参考:
【原型和原型链】什么是原型和原型链_TowYingWang的博客-CSDN博客_原型和原型链
JavaScript原型链的意义是什么? - 知乎
3.call、apply、bind的区别和作用(如果面试官问怎么改变函数内部的this指向,实际上也是在问这个问题)。
call、apply、bind都是用来改变函数内部this指向的。
call是立即执行的不会创建函数,传值是挨个传的。
用法:function.call(thisArg, arg1, arg2, ...)
apply和call基本类似,也是立即执行的不会创建函数。它和call的区别是传参的不同,它传的参数是数组。
用法: function.apply(thisArg, [arg1, arg2, ...])取数组最大值时可以用apply: Math.max.apply(数组)
bind不是立即执行,而是稍后调用,会创建一个函数。多次bind无效。
用法: (function (age, gender) { console.log(1)}).bind(指向对象)
它们第一个参数都是this所要指向的对象,可以用后续参数进行传参。
想深入理解建议看下面这篇详解。
详解:深入理解 call,apply 和 bind - 一像素 - 博客园
4.内存泄漏和内存溢出
内存泄漏是指程序在申请内存后,无法释放已申请的内存空间。内存溢出是指程序申请内存时,没有足够的内存供申请者使用;
这里涉及到JavaScript的垃圾回收机制,JavaScript会定期回收掉没用的变量来释放内存。
内存泄漏是我存了个全局变量,却没回收掉,永久占了块内存,而常说的闭包就会导致内存泄漏。
而内存溢出就是我还想存东西,但我需要的内存比系统还剩的内存要大,这叫内存溢出。
内存泄漏太多就会造成内存溢出。
会引起内存泄漏的几种情况:
1.闭包内被遗忘的计时器
2.意外的全局变量
3.被遗忘的时间监听器
4.被遗忘的发布订阅事件
5.被遗忘的闭包
详解:前端内存泄漏和溢出情况 - 程序yuan - 博客园
5.闭包是什么?
这是个前端必问题了。
简而言之,闭包就是可以获取到函数内部的变量。
如果面试官问你,什么情况会使用闭包呢?
你就可以回答:现在vue2里的data()就是闭包函数,而把它写成闭包是为了将变量私有化,不污染全局变量,让每一个组件都有自己的私有作用域。
被遗忘的闭包过多会引起内存泄漏。
详解:闭包_百度百科
6.怎么解决跨域?
这也是个必问题了,平时工作中,跨域这个事情,前后端都能解决。
以前ajax的年代,前端用dataType: 'jsonp'来解决。
现在vue的年代,前端用proxyTable代理来解决。
我们公司是用nginx来代理跨域。
更多解决方案:解决跨域问题9个方法_Jade-beads的博客-CSDN博客_解决跨域问题
7.为什么会跨域?
那你肯定会回答,跨域是因为同源策略嘛。面试官紧接着就会问你,那什么是同源策略呢?
同源策略是一个安全策略,为了保护本地数据不被JavaScript代码获取回来的数据污染,你只能请求同源的对象/数据,请求了不同域的数据/对象,就会跨域。
面试官又问了,那什么算同源呢?
protocol(协议)、domain(域名)、port(端口)三者一致,即为同源。
同源策略_百度百科
8.数组去重的方法
let arr = [1,1,8,8,12,12,15,15,16,16];
1.用es6语法new Set(arr)
let newArr = new Set(arr);
2.for循环+includes
let newArr=[] for(var i = 0; i < arr.length; i++) {if( !newArr.includes( arr[i]) ) {//includes 检测数组是否有某个值newArr.push(arr[i]);}}
3.利用 filter去重
arr.filter((item,index)=>arr.indexOf(item)===index)
不常问的
1.数组扁平化
var arr = [1, [2, [4, [5, [6]]]]];arr.flat(Infinity) //第一种 ES6的flatwhile(arr.some(item=>Array.isArray(item))){arr=[].concat(...arr)} //第二种 用someJSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g,'')+ ']') //第三种 用正则
2.js事件流
事件流就是页面接受事件的顺序,事件发生后会在元素节点之间按照某种顺序传播
规定的事件流包括三个阶段“事件捕获阶段、出于目标阶段和事件冒泡阶段”。一般来说,出于目标阶段会被看成冒泡阶段的一部分
事件传播的顺序对应浏览器的两种事件流模型:捕获型事件流和冒泡型事件流。
冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标。即从DOM树的叶子到根。【推荐】
捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标。即从DOM树的根到叶子。
JavaScript事件流的概念是什么 - web开发 - 亿速云
详解:Javascript事件流 - SegmentFault 思否
3.什么是事件委托
事件委托也叫事件代理,“事件代理”即是把原本需要绑定在子元素的响应事件(click、keydown…)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。
事件委托的优点:
1.可以大量节省内存占用,减少事件注册,比如在ul上代理所有li的click事件。
2.可以实现当新增子对象时无需再次对其绑定(动态绑定事件)
参考详解:什么是事件委托?_哪吒U的博客-CSDN博客_事件委托
四、http篇
以下几题大公司必问,小公司问的少。
1.https和http的区别是什么?
一、HTTPS协议需要到证书颁发机构CA申请证书,HTTP不用申请证书;
二、HTTP是超文本传输协议,属于应用层信息传输,HTTPS 则是具有SSL加密传安全性传输协议,对数据的传输进行加密,相当于HTTP的升级版;
三、HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
四、HTTP的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。
简单讲就是,1.它俩端口不同。2.https比http更安全,https的传输加密。3.https需要申请证书,它的维护费用更高。
参考:https和http有哪些区别_东北一绝、英俊侠的博客-CSDN博客_https和http的区别
2.TCP和UDP的区别?
TCP协议面向字节流传输,它按顺序传输,不丢包,是可靠的有连接传输协议,三次握手后才能传输数据。传输时只能一对一传输。
UDP面向报文,只保证数据快速到达,不管数据丢不丢失,是不可靠的无连接传输协议,不需要三次握手也可以传输数据。传输时可以一对多。
参考自:tcp和udp有什么区别-常见问题-PHP中文网
3.连接三次握手和四次挥手过程是什么?
TCP三次握手的过程如下:
客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
大白话讲解一下,客户端A发送了个SYN告诉服务器:“兄弟,我要连你了。”(第一次握手)
服务器B想了想同意了,于是它做好了被连的准备(进入SYN_RECV)状态,并且给客户端A回复了请求:“行,我准备好了,你连吧。(ACK报文)” (第二次握手)
客户端A收到了服务器B回复的消息,于是它高兴的回给服务器B:“我也准备好了。(ACK报文)”(第三次握手)
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。
TCP四次挥手
1.客户端A发送一个FIN,用来关闭客户A到服务器B的数据传输。
2.服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
3.服务器B关闭与客户端A的连接,发送一个FIN给客户端A。
4.客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。
看着有点懵,用大白话讲解一下其实很简单:
客户端A跟服务器B说:“你的数据就这么多,都送到了,咱俩可以断了。(FIN)”(第一次挥手)
服务器B“:收到,我现在开始关。(ACK)”(第二次挥手)
服务器B:“我关完了。(FIN)”(第三次挥手)
客户端A:“我也关完了,再见。(ACK报文)”(第四次挥手)
参考自:tcp和udp有什么区别-常见问题-PHP中文网
tcp四次挥手_百度百科
不常问的:
1.HTTP常见状态码都有哪些?
工作中经常见到的
200:成功。
204:服务器没返回内容。
400:传的数据语法有误,服务器理解不了。
403:服务器拒绝请求。
404:页面没找到。
500:服务器问题。
502:后台没启动。
504:超时。
有心的同学可以多背点:常见状态码_weijian_48031311的博客-CSDN博客_状态码
五、es6篇
必问题
1、es6新特性
这题一定要答好,因为面试官会根据你回答的这个问题来问接下来的问题,基本你提到什么他就问什么。别的不说,下面几个常用的特性一点要回答上,你不答面试官会觉得你没用过。
1.let const
2.箭头函数
3.promise函数
4.字符串模板,反斜杠。
5.解构赋值
6.class语法糖
7.set,map
8.对象扩展
下面这两个答上能加分,不答的话……其实我觉得工作中确实不常用。
9.Symbol数据类型
10.for...of循环(Symbol就能用)
更多特性和特性详解:面试题之ES6的新特性(详细) - 知乎
2. var、let、const的区别
var可以声明提升,在定义前就打印变量会undfined,不存在块级作用域,可以跨块访问。
let比var更安全更规范,在定义前就打印变量会报错,拥有块级作用域,不可以跨块访问。
const通常只赋值一次,也拥有块级作用域。定义时必须赋值,赋值时最好大写,如果改变它的引用地址则会报错。
参考自:var、let、const的区别_萌小窝的博客-CSDN博客_const let var 区别
3.箭头函数有什么好处?
1.肯定是书写更方便了,使用“箭头”(=>
)直接定义函数。
2.箭头函数没有绑定自己的this,它的this默认指向外层。
3.定义参数的时候可以直接赋默认值。
1、什么是箭头函数_abuanden的博客-CSDN博客_箭头函数
4.promise函数
面试官会问你,你了解promise吗?什么情况会用到它?
你如果说不了解,那这面试必然要凉了,如果真的想不起来了,建议把promise好好学一下,这个真的很重要。下面这篇讲promise讲的非常好
大白话讲解Promise(一)-阿里云开发者社区
此处简单介绍一下
一个普通Promise函数书写的方式:
function runAsync(){var p = new Promise(function(resolve, reject){//做一些异步操作setTimeout(function(){console.log('执行完成');resolve('成功数据');//代码执行成功后执行,进入.then 只有第一个resolve生效。reject('失败数据') //代码执行失败后执行,进入.catch}, 2000);});return p; }runAsync().then(function(data){ //程序不报错时进入.then,可以无限.thenconsole.log(data); //打印结果为成功数据,接收resolve传递过来的数据console.log('resolved');//后面可以用传过来的数据做些其他操作//......}).catch(function(reason){//程序报错时进入.catch,只有一个catchconsole.log('rejected');console.log(reason);//打印结果为失败数据,接收reject传递过来的数据});
promise函数是es6为了解决回调地狱而存在的。
从promise可以延伸出async、await函数,这两个都是基于promise上构建的,也是必背点。
async、await是为了让异步函数看起来像同步函数一样,是JavaScript Es7发布的新语法,据说是解决异步编程的终极解决方案。
async是一个修饰符,写在函数前,表示一个函数是异步的,这个函数返回的是一个 Promise 对象,所以它直接就可以.then。
而await是写在async里面的,不能单独使用。 如果await后面是一个普通值,那会直接返回该值本身,如果await后面是一个promise,会返回promise成功的结果.
async和await是一对关键字,必须成对出现
具体使用:
(async () = > { await new promise(); })()
5.for in 和 for of的区别
for...of 是ES6新引入的特性。修复了 ES5 引入的 for...in 的不足。
1.for in 输出的是数组的index下标,而for of 输出的是数组的每一项的值。
2.for in 可以遍历对象,for of遍历对象需要配合Object.keys(),并且只能遍历带有iterator接口的对象,例如Set,Map,String,Array
3.for in 会遍历自定义属性,for of不会
参考:【ES6】for of用法_汪小穆的博客-CSDN博客_for of
for in 和for of的区别 - 零度从容 - 博客园
不常问
1、export 和 export default的区别
相同点
1.都可以用于导出常量、函数、文件、模块等
2.都可以用import导入
不同点
1.一个js文件中export可以有多个,export default只能有一个
2.使用export 导出时,在导入时要加上{},export default则不需要
3.使用export default为模块指定默认输出,导入时只需要知道文件名即可
4.使用export必须知道导出的变量或者函数等,导入时的变量名要一致
原文链接:export和export default的区别_棠樾的博客-CSDN博客
六、VUE篇
必问题
1.vuex是什么?的五大属性和具体使用
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件状态,适用于大型项目,最大的特点是响应式。
一般情况下,我们会在 Vuex 中存放一些需要在多个界面中进行共享的信息。比如用户的登录状态、用户名称、头像、地理位置信息、商品的收藏、购物车中的物品等,这些状态信息,我们可以放在统一的地方,对它进行保存和管理。
想完全学会建议看视频教程,文章不够直观。
视频速学教程:Vuex基本使用【Vue小技巧】_哔哩哔哩_bilibili
此处只做简单总结。
vuex五大属性
1、state: vuex的基本数据,用来存储变量;
2、getters:从基本数据(state)派生的数据,相当于state的计算属性;
3、mutations:提交更新数据的方法,必须是同步的
4、action: 和mution的功能大致相同,不同之处在于 ①本质上Action提交的仍是mution,而不是直接变更状态,②Action可以包含任意异步操作
5、modules:模块化vuex,可以让每一个模块拥有自己的 state、mutation、action、 getters,使得结构非常清晰,方便管理
官方文档链接:Vuex 是什么? | Vuex
详解:vuex的五个属性及使用方法—金利恒旺
Vuex ——详细介绍_不情不愿的博客-CSDN博客_vuex
2.watch 和computed的区别和使用。
watch
1、watch是监听一个值的变化,然后执行对应的回调;
2、watch中的函数不需要调用;
3、watch有两个参数;
immediate:组件加载立即触发回调函数执行,
deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变
4、watch中的函数名称必须要和data中的属性名一致,watch依赖于data中的属性,data中的属性发生变化的时候,watch中的函数就会发生变化。
5、watch不支持缓存;
computed
1、computed是计算属性,通过属性计算得来的属性。
2、computed中的函数直接调用,不用()。
3、computed中的函数必须用return返回。
4、computed是依赖data中的属性,data中属性发生改变的时候,当前函数才会执行,data中属性没有改变的时候,当前函数不会执行。
5、computed中不能对data中的属性进行赋值操作,如果对data中的属性进行赋值,data中的属性发生变化,从而触发computed中的函数,就会形成死循环。
6、 computed属性的结果会被缓存,除非依赖的属性发生变化才会重新计算。
————————————————
使用场景
watch的使用场景:一个数据影响多个数据,需要在数据变化时执行异步操作或者开销较大的操作时使用。例如:购物车商品结算的时候computed:一个数据受多个数据影响,处理复杂的逻辑或多个属性影响一个属性的变化时使用。
例如:搜索数据
原文链接:watch和computed的区别及两者的使用场景_徐_三岁的博客-CSDN博客_watch和computed的区别及用法
3.双向绑定的底层原理
VUE2:通过使用 Object.defineProperty 来劫持对象属性的 geter 和 seter 操作,当数据发生改变发出通知。
(1)实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。
(2)实现一个订阅者Watcher,每一个Watcher都绑定一个更新函数,watcher可以收到属性的变化通知并执行相应的函数,从而更新视图。
(3)实现一个解析器Compile,可以扫描和解析每个节点的相关指令(v-model,v-on等指令),如果节点存在v-model,v-on等指令,则解析器Compile初始化这类节点的模板数据,使之可以显示在视图上,然后初始化相应的订阅者(Watcher)。
原理详解1:vue2.0源码之数据双向绑定原理和实现_高质量coder的博客-CSDN博客_vue2.0双向绑定原理原理详解参考2:梳理vue双向绑定的实现原理 - 程序员大本营
VUE3:其他相同,只是换成用ES6的新特性proxy来劫持数据,当数据改变时发出通知。
2. vue中数据双向绑定原理 - Ananiah - 博客园
4.vue3的优点
相比于vue2.x,使用proxy的优势如下
1.defineProperty只能监听某个属性,不能对全对象监听
2.可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可)
3.可以监听数组,不用再去单独的对数组做特异性操作 vue3.x可以检测到数组内部数据的变化
5.vue路由守卫
路由守卫就是路由跳转过程中的一些钩子函数,在路由跳转的时候,做一些判断或其它的操作。 类似于组件生命周期钩子函数 。
路由守卫分为三种 ——分别是:全局路由守卫、组件路由守卫、独享路由守卫。
1.全局路由守卫
① beforeEach(to, from, next) 全局前置守卫,路由跳转前触发
② beforeResolve(to, from, next) 全局解析守卫 在所有组件内守卫和异步路由组件被解析之后触发
③ afterEach(to, from) 全局后置守卫,路由跳转完成后触发
2.路由独享守卫
beforeEnter(to,from,next) 路由对象单个路由配置 ,单个路由进入前触发
3.组件路由守卫
① beforeRouteEnter(to,from,next) 在组件生命周期beforeCreate阶段触发
② beforeRouteUpdadte(to,from,next)当前路由改变时触发
③ beforeRouteLeave(to,from,next) 导航离开该组件的对应路由时触发
4.参数
to: 即将要进入的目标路由对象
from: 即将要离开的路由对象
next(Function):是否可以进入某个具体路由,或者是某个具体路由的路径
原文链接:vue3种路由守卫详解_沉沦与遐想。的博客-CSDN博客_vue路由守卫
6.组件间通信的方法
1. props和$emit(常⽤)
2.$attrs和$listeners
3.$emit和$on
4.provide和inject(爷孙之间通信)
5.$parent和$children
参考:vue组件之间通信的8种方式 - 百度文库
7.路由懒加载的几种方式
ponent: resolve => require(['@/components/HelloWorld'], resolve)
ponent: () => import('@/components/HelloWorld.vue')
ponent: resolve => require.ensure([], () => resolve(require('@/components/'+componentName)), 'webpackChunkName')
参考:vue 之 路由懒加载_此处该有网名的博客-CSDN博客_vue路由懒加载
8.vue-router传参的几种方式
1.router-link路由导航方式传参
路由配置:
bashbash{path:'/father/son/:num',name:A,component:A}
调用方法:
<router-link to="/father/son/传入的参数">父亲组件<router-link>子组件通过 this.$route.params.num 接受参数
2.调用$router.push实现路由传参。
路由配置:
{path: '/d/:id', name: D, component: D}
调用方法:
this.$router.push({path: `/d/${id}`})
3.name匹配路由
this.$router.push({name: 'B',params: {context: '我是传递的参数数据'}})
4.query来传递参数
this.$router.push({path: '/c',query: {context: '我是传递的参数数据'}})
参考:vue-router传参的四种方式超详细_秋田君的博客-CSDN博客_vuerouter传参
不常问的题:
1.v-model 原理
v-model本还是个语法糖,分别利用了v-bind用来绑定绑定响应式数据的值,用v-on去绑定input标准事件,用来监听当输入域内容发生变化的时候来执行一些事情,触发oninput 事件并传递数据。
v-model在内部为不同的输入元素使用不同的属性并抛出不同的事件。
参考:v-model的实现原理_烯烃@的博客-CSDN博客_v-model实现原理
2.如何封装组件
1)全局注册:
main.js中:
import DSPtable from '@/views/common/table.vue' //进入组件路径ponent('DSPtable', DSPtable) //全局注册
页面使用时:
<DSPtable ></DSPtable>
2)局部注册
在引入组件的页面中写如下代码
<template> <DSPtable ></DSPtable> //引入后直接根据注册名称使用即可</template><script>import DSPtable from '@/views/common/table.vue' //页面路径export default {components() {DSPtable:DSPtable //局部注册}}</script>
3.手写一个axios
直接看大佬写好的:手写axios - 孟冰er - 博客园
简单易懂, 手写axios - 掘金
4.vue自定义指令
例:定义一个input自动聚焦的指令。
全局注册,在 main.js写以下内容中:
Vue.directive('focus', {// 当被绑定的元素插入到 DOM 中时……inserted: function (el) {// 聚焦元素el.focus()}})
局部注册,在注册的页面写以下内容:
directives: {focus: {// 指令的定义inserted: function (el) {el.focus()}}}
参考:Vue自定义指令_仰.的博客-CSDN博客_vue自定义指令
在此放上几个常用自定义指令的定义方法
8个非常实用的Vue自定义指令 - 掘金
项目优化
根据自己的理解自由发挥,我总结了几点。
vue层面优化:
1. 路由懒加载、图片懒加载等。
2.自定义公共组件。
3.第三方库按需引入。
4.v-for里尽量不使用v-if、v-for 遍历为 item 添加 key。
5.频繁切换隐藏显示用v-show,不频繁用v-if。
puted 和 watch 区分使用场景
WebPack层面优化。
1.打包时代码分割。
2.提取公共代码。
3.优化SourceMap。
4.对静态资源缓存。
5.使用CDN。
6.对图片进行压缩。