2022前端面试题
---CSS/HTML部分---
这部分可能会先问你css3和html5都增加了那些新元素,然后扩展着问
0、css布局方式
1、table布局(现在少用)
2、flex布局
3、float布局
4、响应式布局
1、说一下盒子模型(常问)
标准盒模型和IE盒子模型
这两个的区别主要是
IE盒子模型的宽高包括content和padding还有border,标准盒子模型 不包括,
box-sizing:content-box 标准盒模型
box-sizing:border-box IE盒模型
2、Html5新标签
canvas 新元素
新多媒体元素
新的语义和结构元素
HTML5提供了新的元素来创建更好的页面结构:
3、BFC
BFC
(Block Formatting Context),即块级格式化上下文,它是页面中一个独立的容器,容器中的元素不会影响到外面的元素
触发条件
触发BFC
的条件包含不限于:
- 根元素,即HTML元素
- 浮动元素:float值为left、right
- overflow值不为 visible,为 auto、scroll、hidden
- display的值为inline-block、inltable-cell、table-caption、table、inline-table、flex、inline-flex、grid、inline-grid
- position的值为absolute或fixed
4、浏览器运行机制
1、创建DOM树
2、构建渲染树,CSS渲染
3、布局渲染,每个元素的大小、位置
4、绘制渲染树、再画出来
重绘:改变元素的外观属性例如div的color、background-color、等属性发生改变时
重排(回流):元素的规模尺寸、布局、隐藏改变时
代价:耗时,导致浏览器卡慢
5、居中的方式
垂直居中的方式
行高=高
绝对定位 top50%,自身宽度的50%的负值
flex布局 align---center
水平居中的方式
绝对定位
flex布局 juest---center
text-align center
6、rem、em、vh、px各自代表的含义?
px:绝对单位,页面按精确像素展示
em:相对单位,基准点为父节点字体的大小,如果自身定义了font-size
按自身来计算,整个页面内1em
不是一个固定的值
rem:相对单位,可理解为root em
, 相对根节点html
的字体大小来计算
vh、vw:主要用于页面视口大小布局,在页面布局上更加方便简单
7、有哪些方式可以隐藏页面元素?区别?
通过css
实现隐藏元素方法有如下:
- display:none
- visibility:hidden
- opacity:0
- 设置height、width模型属性为0
- position:absolute
- clip-path
关于display: none
、visibility: hidden
、opacity: 0
的区别,如下表所示:
8、什么是响应式设计?响应式设计的基本原理是什么?如何做?
响应式网站设计(Responsive Web design)是一种网络页面设计布局,页面的设计与开发应当根据用户行为以及设备环境(系统平台、屏幕尺寸、屏幕定向等)进行相应的响应和调整
响应式网站常见特点:
- 同时适配PC + 平板 + 手机等
- 标签导航在接近手持终端设备时改变为经典的抽屉式导航
- 网站的布局会根据视口来调整模块的大小和位置
实现响应式布局的方式有如下:
- 媒体查询(我们可以设置不同类型的媒体条件,并根据对应的条件,给相应符合条件的媒体调用相对应的样式表)
- 百分比
- vw/vh
- rem
响应式设计实现通常会从以下几方面思考:
- 弹性盒子(包括图片、表格、视频)和媒体查询等技术
- 使用百分比布局创建流式布局的弹性UI,同时使用媒体查询限制元素的尺寸和内容变更范围
- 使用相对单位使得内容自适应调节
- 选择断点,针对不同断点实现不同布局和内容展示
9、css选择器有哪些?优先级?
关于css
属性选择器常用的有:
- id选择器(#box),选择id为box的元素
- 类选择器(.one),选择类名为one的所有元素
- 标签选择器(div),选择标签为div的所有元素
- 后代选择器(#box div),选择id为box元素内部所有的div元素
- 子选择器(.one>one_1),选择父元素为.one的所有.one_1的元素
- 相邻同胞选择器(.one+.two),选择紧接在.one之后的所有.two元素
- 群组选择器(div,p),选择div、p的所有元素
还有一些使用频率相对没那么多的选择器:
- 伪类选择器
:link :选择未被访问的链接
:visited:选取已被访问的链接
:active:选择活动链接
:hover :鼠标指针浮动在上面的元素
:focus :选择具有焦点的
:first-child:父元素的首个子元素
- 伪元素选择器
:first-letter :用于选取指定选择器的首字母
:first-line :选取指定选择器的首行
:before : 选择器在被选元素的内容前面插入内容
:after : 选择器在被选元素的内容后面插入内容
- 属性选择器
[attribute] 选择带有attribute属性的元素
[attribute=value] 选择所有使用attribute=value的元素
[attribute~=value] 选择attribute属性包含value的元素
[attribute|=value]:选择attribute属性以value开头的元素
在CSS3
中新增的选择器有如下:
- 层次选择器(p~ul),选择前面有p元素的每个ul元素
- 伪类选择器
:first-of-type 父元素的首个元素
:last-of-type 父元素的最后一个元素
:only-of-type 父元素的特定类型的唯一子元素
:only-child 父元素中唯一子元素
:nth-child(n) 选择父元素中第N个子元素
:nth-last-of-type(n) 选择父元素中第N个子元素,从后往前
:last-child 父元素的最后一个元素
:root 设置HTML文档
:empty 指定空的元素
:enabled 选择被禁用元素
:disabled 选择被禁用元素
:checked 选择选中的元素
:not(selector) 选择非 <selector> 元素的所有元素
- 属性选择器
[attribute*=value]:选择attribute属性值包含value的所有元素
[attribute^=value]:选择attribute属性开头为value的所有元素
[attribute$=value]:选择attribute属性结尾为value的所有元素
优先级
内联 > ID选择器 > 类选择器 > 标签选择器
10、清除浮动的方法
方法一:使用带 clear 属性的空元素
在浮动元素后使用一个空元素,并在 CSS 中赋 予.clear{clear:both;}属性即可清理浮动。
方法二:使用 CSS 的 overflow 属性
给浮动元素的容器添加 overflow:hidden;或 overflow:auto;可以清除浮动,另外在 IE6 中还 需要触发 hasLayout ,例如为父元素设置容器宽高或设置 zoom:1。 在添加 overflow 属性后,浮动元素又回到了容器层,把容器高度撑起,达到了清理浮动 的效果。
方法三:给浮动的元素的容器添加浮动
给浮动元素的容器也添加上浮动属性即可清除内部浮动,但是这样会使其整体浮动,影 响布局,不推荐使用。
方法四:使用 CSS 的:after 伪元素
结合:after 伪元素(注意这不是伪类,而是伪元素,代表一个元素之后最近的元素)和 IEhack ,可以完美兼容当前主流的各大浏览器,这里的 IEhack 指的是触发 hasLayout。 给浮动元素的容器添加一个 clearfix 的 class,然后给这个 class 添加一个:after 伪元素实 现元素末尾添加一个看不见的块元素清除浮动
11、常见的行内元素、块级元素
1、块级元素(div,p,h1...h6,ol,ul,table)
每个块级元素都是独自占一行、元素的高度宽度都是可以设置的
2、行内元素(span,a,img,input,strong)
可以和其他元素处于一行上,元素的高度宽度顶部和底部边距不可设置
12、position的属性
此处,问过相对定位和绝对定位的区别
相对定位:相对于当前元素的位子来移动;绝对定位如果不把父元素设置为相对定位,则相对与页面的左上角定位
13. 谈谈做好seo需要考虑什么?
- 语义化html标签
- 合理的title, description, keywords;
- 重要的html代码放前面
- 少用iframe, 搜索引擎不会抓取iframe中的内容
- 图片加上alt
**---JavaScript部分---**
0、ES6新增了哪些方法
1、includes()用于判断数组是否包含给定的值 返回一个布尔值
2、find()用于找出第一个符合条件的数组成员
3、findindex()返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1
4、set数据结构,类似于数组,但是成员的值都是唯一的,没有重复的值
5、、let声明变量、const声明常量(这里就要问你var、let、const的区别了)
6、解构赋值 ...
set 和map 的区别!!!以前被问没看过,懵逼过,所以要记住
1.Map是键值对,Set是值的集合,键和值可以是任何的值;
2.Map可以通过get方法获取值,而set不能因为它只有值,set只能用has来判断,返回一个布尔值;
4.Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储
1、promiseApi
Promise
构建出来的实例存在以下方法:
- then() 是实例状态发生改变时的回调函数,第一个参数是
resolved
状态的回调函数,第二个参数是rejected
状态的回调函数 - catch() 用于指定发生错误时的回调函数
- finally() 用于指定不管 Promise 对象最后状态如何,都会执行的操作
Promise
构造函数存在以下方法:
- all() 用于将多个
Promise
实例,包装成一个新的Promise
实例 - race() 同样是将多个 Promise 实例,包装成一个新的 Promise 实例
- allSettled()
- resolve()
- reject()
- try()
2、Var、 let 、const 区别?(常问、必记)
var
、let
、const
三者区别可以围绕下面五点展开:
- 变量提升
var声明的变量存在变量提升,即变量可以在声明之前调用,值为
undefinedlet
和const
不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错 - 暂时性死区
var
不存在暂时性死区let
和const
存在暂时性死区,只有等到声明变量的那一行代码出现,才可以获取和使用该变量 - 块级作用域
var
不存在块级作用域let
和const
存在块级作用域 - 重复声明
var
允许重复声明变量let
和const
在同一作用域不允许重复声明变量 - 修改声明的变量
var
和let
可以const
声明一个只读的常量。一旦声明,常量的值就不能改变 - 使用
能用const
的情况尽量使用const
,其他情况下大多数使用let
,避免使用var
3、== 和 ===区别
相等操作符(==)会做类型转换,再进行值的比较,全等运算符(===)不会做类型转换
let result1 = ("55" === 55); // false,不相等,因为数据类型不同
let result2 = (55 === 55); // true,相等,因为数据类型相同值也相同
null
和 undefined
比较,相等操作符(==)为true
,全等为false
let result1 = (null == undefined ); // true
let result2 = (null === undefined); // false
4、数组常用方法
增
下面前三种是对原数组产生影响的增添方法,第四种则不会对原数组产生影响
- push() 接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度
- unshift() 开头添加
- concat() 首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组,不会影响原始数组
删
下面三种都会影响原数组,最后一项不影响原数组:
- pop() 删除数组的最后一项,同时减少数组的
length
值,返回被删除的项 - shift() 删除数组的第一项,同时减少数组的
length
值,返回被删除的项 - splice() 传入两个参数,分别是开始位置,删除元素的数量,返回包含删除元素的数组
- slice() 创建一个包含原有数组中一个或多个元素的新数组,不会影响原始数组
改
即修改原来数组的内容,常用splice
传入三个参数,分别是开始位置,要删除元素的数量,要插入的任意多个元素,返回删除元素的数组,对原数组产生影响
查
即查找元素,返回元素坐标或者元素值
- indexOf() 返回要查找的元素在数组中的位置,如果没找到则返回 -1
- includes() 返回要查找的元素在数组中的位置,找到返回
true
,否则false
- find() 返回第一个匹配的元素
排序方法
数组有两个方法可以用来对元素重新排序:
- reverse() 将数组元素方向反转
下面这个被问过,所以重点展开
- sort(首元素地址(必填), 尾元素地址的下一个地址(必填), 比较函数(非必填));
如果直接sort(数组名),则从小到大排序(即升序),以下为倒叙
var arr4 = [30,10,111,35,1899,50,45];
arr4.sort(function(a,b){
return b - a;
})
console.log(arr4);//输出 [1899, 111, 50, 45, 35, 30, 10]
转换方法
常见的转换方法有:
join()
join() 方法接收一个参数,即字符串分隔符,返回包含所有项的字符串
迭代方法
常用来迭代数组的方法(都不改变原数组)有如下:
- some() 对数组每一项都运行传入的函数,如果有一项函数返回 true ,则这个方法返回 true
- every() 对数组每一项都运行传入的函数,如果对每一项函数都返回 true ,则这个方法返回 true
- forEach() 对数组每一项都运行传入的函数,没有返回值
- filter() 对数组每一项都运行传入的函数,函数返回
true
的项会组成数组之后返回 - map() 对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组.
去重方法
1、利用ES6 Set去重(ES6中最常用)
function unique (arr) {
return Array.from(new Set(arr))
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]
2、利用for嵌套for,然后splice去重(ES5中最常用)
function unique(arr){
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i]==arr[j]){ //第一个等同于第二个,splice方法删除第二个
arr.splice(j,1);
j--;
}
}
}
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}] //NaN和{}没有去重,两个null直接消失了
3、利用indexOf去重
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var array = [];
for (var i = 0; i < arr.length; i++) {
if (array .indexOf(arr[i]) === -1) {
array .push(arr[i])
}
}
return array;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
// [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}] //NaN、{}没有去重
4、利用includes
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var array =[];
for(var i = 0; i < arr.length; i++) {
if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
array.push(arr[i]);
}
}
return array
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}] //{}没有去重
5、bind、call、apply 区别
- 1.call和apply会调用函数,且会改变函数内部的this指向
2.call和apply传递的参数不一样,call传递参数aru1,aru2.形式 而apply必须是数组形式[arg]
3.bind 不会调用函数,可以改变函数内部指向 - 应用场景:
1.call经常做继承
2.apply经常和数组有关系,比如借助于数学对象实现数组的max、min
3.bind不调用函数,但改变this指向,比如改变定时器内部的this指向 - apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即 A 对象应用 B 对象的方法。 call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2); 即 A 对象调用 B 对象的方法。 bind 除了返回是函数以外,它的参数和 call 一样。
6、本地存储的方式有哪些?区别及应用场景?
javaScript
本地缓存的方法我们主要讲述以下四种:
- cookie
- sessionStorage
- localStorage
- indexedDB
区别
关于cookie
、sessionStorage
、localStorage
三者的区别主要如下:
- 存储大小:
cookie
数据大小不能超过4k
,sessionStorage
和localStorage
虽然也有存储大小的限制,但比cookie
大得多,可以达到5M或更大 - 有效时间:
localStorage
存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;sessionStorage
数据在当前浏览器窗口关闭后自动删除;cookie
设置的cookie
过期时间之前一直有效,即使窗口或浏览器关闭 - 数据与服务器之间的交互方式,
cookie
的数据会自动的传递到服务器,服务器端也可以写cookie
到客户端;sessionStorage
和localStorage
不会自动把数据发给服务器,仅在本地保存
应用场景
在了解了上述的前端的缓存方式后,我们可以看看针对不对场景的使用选择:
- 标记用户与跟踪用户行为的情况,推荐使用
cookie
- 适合长期保存在本地的数据(令牌),推荐使用
localStorage
- 敏感账号一次性登录,推荐使用
sessionStorage
- 存储大量数据的情况、在线文档(富文本编辑器)保存编辑历史的情况,推荐使用
indexedDB
7、说说你对闭包的理解?闭包使用场景
闭包就是函数中包含另一个函数,可以让你在函数外部读取到内部的变量(就是在函数内部再定义一个函数),让这些变量的值始终保持在内存中,可以达到延长变量生命周期的效果,过多使用会导致内存泄漏的问题
(在创建私有变量和想延长变量的生命周期时会用到闭包)
8、深拷贝浅拷贝的区别?
浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝
如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址
在JavaScript
中,存在浅拷贝的现象有:
- Object.assign
- Array.prototype.slice()
- Array.prototype.concat()
- 使用拓展运算符实现的复制
深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
常见的深拷贝方式有:
- _.cloneDeep()
- jQuery.extend()
- JSON.stringify()
- 手写循环递归
9、JavaScript中的数据类型?
string、number、Boolean、undefined、null、object
10、什么是防抖和节流?
定义
- 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
- 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖
电梯第一个人进来后,15秒后准时运送一次,这是节流
11、如何解决数字精度丢失的问题?
理论上用有限的空间来存储无限的小数是不可能保证精确的,但我们可以处理一下得到我们期望的结果
当你拿到 1.4000000000000001
这样的数据要展示时,建议使用 toPrecision
凑整并 parseFloat
转成数字后再显示,如下:
parseFloat(1.4000000000000001.toPrecision(12)) === 1.4 // True
封装成方法就是:
function strip(num, precision = 12) {
return +parseFloat(num.toPrecision(precision));
}
最后还可以使用第三方库,如Math.js、BigDecimal.js
12、 JavaScript 中内存泄漏的几种情况?
使用闭包
13、原型,原型链 ? 有什么特点?
JavaScript
常被描述为一种基于原型的语言——每个对象拥有一个原型对象
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾
原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法
14、如何实现上拉加载,下拉刷新?
开源社区有很多优秀的解决方案,如iscroll
、better-scroll
、pulltorefresh.js
库等等
15、说说你对作用域链的理解
1、作用域就是变量与函数的可访问范围
2、一般情况下,变量取值到创建这个变量的函数的作用域中取值。 但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链
16、typeof 与 instanceof 区别
typeof
与instanceof
都是判断数据类型的方法,区别如下:
typeof
会返回一个变量的基本类型,instanceof
返回的是一个布尔值instanceof
可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型- 而
typeof
也存在弊端,它虽然可以判断基础数据类型(null
除外),但是引用数据类型中,除了function
类型以外,其他的也无法判断
17、js基本数据类型
string、number、null、defined、boolean、object、symbol、bigint
18、ajax、axios、jsonp的理解
1、jsonp是一种可以解决跨域问题的方式,就是通过动态创建script标签用src引入外部文件实现跨域,script加载实际上就是一个get请求,并不能实现post请求。(其他实现跨域的方法有:iframe,window.name,postMessage,CORS...)
2、ajax是一种技术,ajax技术包含了get和post请求的,但是它仅仅是一种获取数据的技术,不能直接实现跨域,只有后台服务器配置好Access-Control-Allow-Origin,才可以实现请求的跨域。
4、axios是通过promise实现对ajax技术的一种封装,axios是ajax,ajax不止axios。
总结:
juery的$.ajax实现get请求能跨域是因为jsonp或者因为原生ajax和服务器的配合,post请求能跨域就只能是因为原生ajax和服务器的配合。
19、ajax的请求过程
// ajax 提交 post 请求的数据
// 1. 创建核心对象
var xhr = new XMLHttpRequest();
// 2. 准备建立连接
xhr.open("POST", "register.php", true);
// 3. 发送请求
// 如果要POST提交数据,则需要设置请求头
// 有的面试官会问为什么要设置请求头? 知道请求正文是以什么格式
// Content-Type: application/x-www-form-urlencoded,请求正文是类似 get 请求 url 的请求参数
// Content-Type: application/json,请求正文是一个 json 格式的字符串
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// 发送数据
xhr.send(querystring);
// 4. 处理响应
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) { // 请求处理完毕,响应就绪
if (xhr.status === 200) { // 请求成功
var data = xhr.responseText;
console.log(data);
}
}
}
20、ajax请求的时候get 和post方式的区别
1、get请求不安全,post安全 ;
2、get请求数据有大小限制,post无限制 ;
3、get请求参数会在url中显示,容易被他人窃取,post在请求体中,不会被窃取;
4、post需要设置请求头。
21、什么是事件委托以及优缺点
js事件委托就是利用冒泡的原理,把本应该添加到某个元素上的事件委托给他的父级,从而减少DOM交互达到网页优化。
优点:
1.可以大量节省内存占用,减少事件注册。比如ul上代理所有li的click事件就很不错。 2.可以实现当新增子对象时,无需再对其进行事件绑定,对于动态内容部分尤为合适
缺点:
事件代理的常用应用应该仅限于上述需求,如果把所有事件都用事件代理,可能会出现事件误判。即本不该被触发的事件被绑定上了事件。
---Vue部分---
1、为什么使用虚拟DOM(常问)
- 创建真实DOM的代价高:真实的 DOM 节点 node 实现的属性很多,而 vnode 仅仅实现一些必要的属性,相比起来,创建一个 vnode 的成本比较低。
- 触发多次浏览器重绘及回流:使用 vnode ,相当于加了一个缓冲,让一次数据变动所带来的所有 node 变化,先在 vnode 中进行修改,然后 diff 之后对所有产生差异的节点集中一次对 DOM tree 进行修改,以减少浏览器的重绘及回流。
- 虚拟dom由于本质是一个js对象,因此天生具备跨平台的能力,可以实现在不同平台的准确显示。
- Virtual DOM 在性能上的收益并不是最主要的,更重要的是它使得 Vue 具备了现代框架应有的高级特性。
2、Vue组件通信
父组件向子组件传值
- 父组件发送的形式是以属性的形式绑定值到子组件身上。
- 然后子组件用属性props接收
- 在props中使用驼峰形式,模板中需要使用短横线的形式字符串形式的模板中没有这个限制
子组件向父组件传值
- 子组件用
$emit()
触发事件 $emit()
第一个参数为 自定义的事件名称 第二个参数为需要传递的数据 $(event)来接收- 父组件用v-on 缩写为@ 监听子组件的事件
兄弟之间的传递
- 兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据
- 提供事件中心 var hub = new Vue()
- 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)
- 接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
- 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
3、Vue中key是用来做什么的?为什么不推介使用index作为key?
1、key的作用主要是为了高效的更新虚拟DOM(使用key,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素)
2、当以数组的下标index作为index值时,其中一个元素(如增删改查)发生了变化就有可能导致所有元素的key值发生变化
4、生命周期:
从Vue实例创建、运行、到销毁期间,伴随着的各种事件,这些事件统称为生命周期
生命周期函数分类:
- 创建期间的生命周期函数:
- beforeCreate:实例刚在内存中被创建出来,此时还没有初始化好data和methods属性
- created:实例已经在内存中创建出来,此时的data和methods以及创建完成,但是还没有开始编译模板
- beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面上
- mounted:已经将编译好的模板,挂载到了页面指定的容器中显示
- 运行期间的生命周期函数:
- beforeUpdate:状态更新之前执行此函数,此时data中的状态值是最新的,但是界面上显示的数据还是旧的,因为此时还没有开始重新渲染DOM节点
- updated:实例更新完毕之后调用此函数,此时data中的状态值和界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了
- 销毁期间的生命周期函数:
- 注意 !!!vue3,则是beforeunmount和unmount
- beforeDestory:实例销毁之前调用,在这一步,实例仍然完全可用
- destroyed:Vue实例销毁之后调用。调用后,Vue实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁
5、v-show和v-if的区别
v-show原理是修改元素的css属性display:none来决定是显示还是隐藏
v-if则是通过操作DOM来进行切换显示
6、双向数据绑定
实现mvvm的双向绑定,是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
7、Vue导航守卫的钩子函数有哪些?
全局守卫
- router.beforeEach:全局前置守卫,进入路由之前
- router.beforeResolve:全局解析守卫,在beforeRouteEnter调用之后调用
- router.afterEach:全局后置钩子,进入路由之后
路由组件内的守卫
- beforeRouteEnter():进入路由前
- beforeRouteUpdate():路由复用同一个组件时
- beforeRouteLeave():离开当前路由时
8、vue编程式的导航跳转传参的方式有哪些?
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
9、vuex是什么?怎么使用?哪种功能场景使用它?
在main.js引入store,注入。新建了一个store目录,然后….. export 。 场景:单页应用中,组件之间的共享状态和方法 state Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。 mutations mutations定义的方法动态修改Vuex 的 store 中的状态或数据。 getters 类似vue的计算属性,主要用来过滤一些数据。 action actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。 modules 项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
10、mvc和mvvc的区别
MVC
MVC包括view视图层、controller控制层、model数据层。各部分之间的通信都是单向的。
View 传送指令到 Controller Controller 完成业务逻辑后,要求 Model 改变状态 Model 将新的数据发送到 View,用户得到反馈
MVVM
MVVM包括view视图层、model数据层、viewmodel层。各部分通信都是双向的。
采用双向数据绑定,View的变动,自动反映在 ViewModel,反之亦然。 mvvm代表框架:Angularjs、React、Vue mvvm主要解决了mvc中大量 dom操作使得页面渲染性能降低,加载速度变慢,影响用户体验
11、说出至少vue 3个常用事件修饰符?
.stop 阻止点击事件冒泡
.prevent 阻止默认事件
.once 只执行一次
.self 只在元素本身触发
12、vuex有哪几种属性
有五种,分别是State , Getter , Mutation , Action , Module (就是mapAction)
- state:vuex的基本数据,用来存储变量
- geeter:从基本数据(state)派生的数据,相当于state的计算属性
- mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。
- action:和mutation的功能大致相同,不同之处在于 ==》1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。
- modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
HTTP
1、说一下http和https
http:超文本传输协议,是一个客户端和服务器端请求和应答的标准(TCP)
https:是以安全为目标的HTTP通道,即HPPT下加入SSL层,比http更安全
区别:
http传输的数据都是未加密的(明文),https协议是由https和SSL协议构建的可进行加密传输和身份认证的网络协议,需要ca证书,费用较高
2、tcp三次握手,一句话概括
客户端和服务端都需要直到各自可收发,因此需要三次握手
3、HTTP状态码
1xx Informational(信息性状态码) 接受的请求正在处理
2xx Success(成功状态码) 请求正常处理完毕
(1)、200 OK:表示从客户端发送给服务器的请求被正常处理并返回;
(2)、204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
(3)、206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
3xx Redirection(重定向) 需要进行附加操作以完成请求
(1)、301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
(2)、302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;
(3)、301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)
(4)、303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;
(5)、302与303的区别:后者明确表示客户端应当采用GET方式获取资源
(6)、304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;
(7)、307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
4xx Client error(客户端错误) 客户端请求出错,服务器无法处理请求
400 Bad Request:表示请求报文中存在语法错误;
401 Unauthorized:未经许可,需要通过HTTP认证;
403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
5xx Server Error(服务器错误) 服务器处理请求出错
500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;
503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
问你项目描述:
1.你这个项目的整体描述,需求,功能;
2.你这个项目所用到的技术栈,以及选择该技术栈的原因;
3.你这个项目中所遇到的问题,以及解决方法。
问你前端优化:
1、降低请求量:合并资源,减少HTTP请求数,minify/gzip压缩
2、加快请求速度:预解析DNS,减少域名数,并行加载
3、缓存:HTTP协议缓存请求,离线缓存manifest,离线数据缓存localStorage
4、渲染:JS/CSS优化,加载顺序,服务端渲染
原链接:https://zhuanlan.zhihu.com/p/422730888