前端面试套路
前端方面:
1. transition和animation的区别?
Animation和transition大部分属性是相同的,他们都是随时间改变元素的属性值,他们的主要区别是transition需要触发一个事件才能改变属性,而animation不需要触发任何事件的情况下才会随时间改变属性值,并且transition为2帧,从from .... to,而animation可以一帧一帧的。transition规定动画的名字 规定完成过渡效果需要多少秒或毫秒 规定速度效果 定义过渡效果何时开始。animation指定要绑定到选择器的关键帧的名称。
2. 怎么使不确定宽高的div居中?
使用flex在父盒子设置display: flex; justify-co
ntent: center;align-items: center
使用css的transform 父盒子设置:display:relative
Div设置: transform: translate(-50%,-50%);position: absolute;top: 50%;left: 50%;
display:table-cell 父盒子设置:display:table-cell; text-align:center;vertical-align:middle;
Div设置: display:inline-block;vertical-align:middle;
position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;
3. 浮动问题?
Float的取值:
left左浮 right右浮 none默认
2. Float的特性:
浮动元素会从普通文档流中脱离,但浮动元素影响的不仅是自己,它会影响周围的元素对齐进行环绕。
不管一个元素是行内元素还是块级元素,如果被设置了浮动,那浮动元素会生成一个块级框,可以设置它的width和height,因此float常常用于制作横向配列的菜单,可以设置大小并且横向排列。
浮动元素在浮动的时候,其margin不会超过包含块的padding。PS:如果想要元素超出,可以设置margin属性
如果两个元素一个向左浮动,一个向右浮动,左浮动元素的marginRight不会和右浮动元素的marginLeft相邻。
如果有多个浮动元素,浮动元素会按顺序排下来而不会发生重叠的现象。
如果有多个浮动元素,后面的元素高度不会超过前面的元素,并且不会超过包含块。
如果有非浮动元素和浮动元素同时存在,并且非浮动元素在前,则浮动元素不会高于非浮动元素
浮动元素会尽可能地向顶端对齐、向左或向右对齐
3. 父元素高度塌陷问题?
解决父元素高度塌陷问题:一个块级元素如果没有设置height,其height是由子元素撑开的。对子元素使用了浮动之后,子元素会脱离标准文档流,也就是说,父级元素中没有内容可以撑开其高度,这样父级元素的height就会被忽略,这就是所谓的高度塌陷。
4. 清除浮动的方法?
方法1:给父级div定义 高度 原理:给父级DIV定义固定高度(height),能解决父级DIV 无法获取高度得问题。 优点:代码简洁 缺点:高度被固定死了,是适合内容固定不变的模块。(不推荐使用)
方法二:使用空元素,如
(.clear{clear:both})原理:添加一对空的DIV标签,利用css的clear:both属性清除浮动,让父级DIV能够获取高度。 优点:浏览器支持好 缺点:多出了很多空的DIV标签,如果页面中浮动模块多的话,就会出现很多的空置DIV了,这样感觉视乎不是太令人满意。方法三:父元素设置overflow:hidden、auto; 原理:这个方法的关键在于触发了BFC。在IE6中还需要触发 hasLayout(zoom:1) 优点:代码简介,不存在结构和语义化问题 缺点:无法显示需要溢出的元素。
方法四:父级div定义 伪类:after 和 zoom
.clearfix:after{
content:'.';
display:block;
height:0;
clear:both;
visibility: hidden;
}.clearfix {zoom:1;}
原理:IE8以上和非IE浏览器才支持:after,原理和方法2有点类似,zoom(IE转有属性)可解决ie6,ie7浮动问题 优点:结构和语义化完全正确,代码量也适中,可重复利用率(建议定义公共类) 缺点:代码不是非常简洁(极力推荐使用)
经益求精写法
.clearfix:after {
content:”\200B”;
display:block;
height:0;
clear:both;
}
.clearfix { *zoom:1; }照顾IE6,IE7就可以了
5. px,em,rem的区别?
px像素(Pixel)。绝对单位。像素 px 是相对于显示器屏幕分辨率而言的,是一个虚拟长度单位,是计算机系统的数字化图像长度单位,如果 px 要换算成物理长度,需要指定精度 DPI。
em是相对长度单位,相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置, 则相对于浏览器的默认字体尺寸。它会继承父级元素的字体大小,因此并不是一个固定的值。
rem是 CSS3 新增的一个相对单位(root em,根 em),使用 rem 为元素设定字体大小时,仍然是相对大小, 但相对的只是 HTML 根元素。
6. CSS引入的方式有哪些? link 和@import 的区别是?
有四种:内联(元素上的style属性)、内嵌(style标签)、外链(link)、导入(@import) link和@import的区别:
link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。
link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。
link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
link支持使用Javascript控制DOM去改变样式;而@import不支持。
7.流式布局与响应式布局
流式布局使用非固定像素来定义网页内容,也就是百分比布局,通过盒子的宽度设置成百分比来根据屏幕的宽度来进行伸缩,不受固定像素的限制,内容向两侧填充。
响应式开发利用CSS3中的 Media Query(媒介查询),通过查询 screen 的宽度来指定某个宽度区间的网页布局。
8.消除图片底部间隙的方法
图片块状化-无基线对齐:img { display: block; }
图片底线对齐:img { vertical-align: bottom; }
行高足够小-基线位置上移:.box { line-height: 0; }
9. 什么是函数防抖和函数节流区别
函数防抖就是在规定的时间只执行一次,如果事件触发多次,重新计算函数执行时间,只执行最后一次
函数节流就是在限制一个函数在规定的时间内只执行一次
函数节流与函数防抖的区别: 我们以一个案例来讲一下它们之间的区别:设定一个间隔时间为一秒,在一分钟内,不断的移动鼠标,让它触发一个函数,打印一些内容。函数防抖:会打印1次,在鼠标停止移动的一秒后打印。函数节流:会打印60次,因为在一分钟内有60秒,每秒会触发一次。总结:节流是为了限制函数的执行次数,而防抖是为了限制函数的执行时机。
10. var let count
const:定义的变量不可修改,必须初始化 var:定义的变量可以修改,如果不初始化输出undefined,不会报错 let:块级作用域,函数内部使用let定义后,会函数外部无影响 let const不会造成变量的提升
11. null和undefined的区别
undefined类型只要一个,即undefined,当声明变量还未被初始化时就是undefined null类型也只有一个值,即null。null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象 NaN与任何值都是相比较的结果都是false
12. http和https的区别
https:是以安全为目标的HTTP通道,简单讲是HTTP的安全版本,通过SSL加密http:超文本传输协议。是一个客服端和服务器端请求和应答的标准(tcp),使浏览器更加高效,使网络传输减少
13. Ajax的原理
ajax的原理:相当于在用户和服务器之间加一个中间层(ajax引擎),使用户操作与服务器响应异步化。 优点:在不刷新整个页面的前提下与服务器通信维护数据。不会导致页面的重载可以把前端服务器的任务转嫁到客服端来处理,减轻服务器负担,节省宽带 劣势:不支持back。对搜索引擎的支持比较弱;不容易调试 怎么解决呢?通过location.hash值来解决Ajax过程中导致的浏览器前进后退按键失效,解决以前被人常遇到的重复加载的问题。主要比较前后的hash值,看其是否相等,在判断是否触发ajax
Vue方面:
1. Vue的核心思想:
组件化开发和数据驱动
2. 什么是vuex?有什么作用?
vuex是vue的状态管理工具
作用:项目数据状态的集中管理,复杂组件的数据通信问题。
3. Vuex的核心属性:
State:存储数据状态的地方,但是不可以直接修改里面的数据
Mutations: mutations定义的方法动态修改vuex的store中的状态或数据
Actions:简单的说就是异步操作数据,view层通过store.dispatch来分发action.
Getters:类似vue的计算属性,主要用来过滤数据
Modules:模块化管理 项目特别复杂的时候,可以让每一个模块拥有自己的state,mutation,action,getters,使得结构非常清晰,方便管理
4. vuex的工作流程?
在vue组件里面,通过dispatch来触发actions提交修改数据的操作
然后再通过actions的commit来触发mutations来修改数据
Mutations接收到commit的请求,就会自动通过mutate来修改state里面的数据
最后由store触发每一个调用它的组建的更新。
5. Vue的生命周期?
BeforeCreated(实例创建前):此时的vue实例还没有挂载元素$el,数据对象data也是undefined
Created(实例创建完成):vue实例的数据对象data有了,但是$el还没有
beforeMount(实例载入前):vue的实例的$el和data都初始化了,但还是挂载在之前的虚拟DOM节点上,data.message还没替换。
Mounted(实力载入完成):vue实例挂载完成,data.message成功渲染。
beforeUpdate(实例更新前):data发生变化前
Updated(实例更新前):data发生变化后
BeforeDestory(实例销毁前):在实例销毁之前调用,实例仍然可用
Destory(实例销毁完成):所有的监听事件会被消除,所有的子实例也会被销毁
6. vue常用的指令?
V-model v-html v-text v-for v-show v-if v-on
7. V-if和v-show的区别?
V-if是通过添加和删除DOM节点来控制显示隐藏,v-show是通过操作css的display属性来控制显示隐藏;
V-if拥有更高的切换成本,v-show拥有更高的渲染成本。
频繁切换的时候使用v-show,不经常切换就使用v-if.
8. V-for和v-if的优先级?
当它们处于同一节点,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for的循环中。
9. MVC MVP MVVM的区别?
MVC: MVC之间的数据通信都是单向的。View(视图层)发送指令到controller(控制层),完成业务逻辑后,要求Model(模型层)改变状态,匠心的数据发送到(view)视图层,用户得到反馈。
MVP:在MVP中,view和model之间没有任何通信关系,所有的通信和业务逻辑都放在presenter层中。View层发送指令到presenter层,presenter层处理业务逻辑,要求model层改变状态,完成状态修改之后,发送指令到presenter层,之后再通知view层做出改变。
MVVM: Model专门用来处理数据模型。View专门用来处理用户视图,ViewModel用来使view和model双向绑定,view的任何变化都会通知ViewModel,而model的任何变化也会通知ViewModel,无论哪一项发生改变,都会使对应的视图/数据模型同时发生改变。
10. Vue插槽?
11. 什么是axios?
就是请求后台资源的模块,前台通过它获取后台数据,类似ajax交互
12. 怎么封装axios?
13. 路由传参的方法?
https://segmentfault.com/a/1190000012393587?utm_source=tag-newest
14. Vuex中actions和mutations的区别?
Mutations的更改是同步更改,用于用户执行直接数据更改,this.$store.commit(‘名’)触发
Actions的更改是异步操作,用于需要与后端交互的数据更改,this.$store.dispath(“名”)触发
注意:
1):定义actions方法创建一个更改函数时,这个函数必须携带一个context参数,用于触发mutations方法,context.commit(‘修改函数名’ , ’异步请求值’);
2):mutations第一个参数必须传入state,第二个参数是新值
15. 渐进式框架的理解?
项目介绍1
项目介绍:
项目背景:
商品列表渲染:
路由跳转:
商品分类怎么实现的;
单选多选全选怎么实现的:
加入购物车怎么实现的;
登录注册怎么实现;
登录流程:
Loading动画怎么实现;
上拉加载,下拉刷新怎么实现:
图片懒加载怎么实现;
商品持久化存储怎么实现的:(区别)
sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。
webstorage和cookie的区别WebStorage的概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。除此之外,WebStorage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie。但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在,而WebStorage仅仅是为了在本地“存储”数据而生。
做这个项目的过程中遇到的bug,怎么解决的:
移动端的性能优化:
首屏加载和按需加载,懒加载 资源预加载 图片压缩处理,使用base64内嵌图片 合理缓存dom对象 使用touchstart代替click(click 300毫秒的延迟) 利用transform:translateZ(0),开启硬件GUP加速 不滥用web字体,不滥用float(布局计算消耗性能),减少font-size声明 使用viewport固定屏幕渲染,加速页面渲染内容 尽量使用事件代理,避免直接事件绑定
项目介绍2
项目介绍:
项目背景:
数据渲染:
后台权限管理是怎么实现的:
定义两张路由表,一张是静态路由表(无需权限的使用),另一张是权限路由表(和后台返回的权限进行匹配使用)。用户登录,判断登录是否成功,登录成功后判断是否获取用户权限列表,获取到后,将权限数据存储到Vuex中。用Vuex中的权限数据和定义好的需要访问权限的路由表进行比对。比对完后生成当前账户对应的权限路由表。通过addRouters方法动态添加路由规则,生成可访问的侧边栏菜单。
跨域问题,怎么解决的:
原生javascript:
promise封装axios(手写):
如何合并对象(多个对象合成一个):
Object.assign(o1,o2,o3,…)
Foreach和map的区别:
Foreach:没有返回值,遍历数组对每个值进行处理
Map():有返回值,返回值组成一个新的数组
JSON.parse()与JSON.stringify()的区别:
JSON.parse()从一个字符串中解析出json对象
JSON.stringify()从一个对象中解析出字符串
跨域解决方法:
Jsonp:jsonp的原理,通过动态的创建script标签,其src属性可以跨域引用文件,jsonp是请求之后后台包装好的一段json,并且把数据存放在一个callback回调函数中,返回一个js文件,动态的引入这个文件,调用callback,进行数据访问。
回调地狱问题(异步回调):
promise、generator、async/await promise:
1.是一个对象,用来传递异步操作的信息。代表着某个未来才会知道结果的时间,并未这个事件提供统一的api,供进异步处理 2.有了这个对象,就可以让异步操作以同步的操作的流程来表达出来,避免层层嵌套的回调地狱 3.promise代表一个异步状态,有三个状态pending(进行中),Resolve(以完成),Reject(失败) 4.一旦状态改变,就不会在变。任何时候都可以得到结果。从进行中变为以完成或者失败 promise.all()里面状态都改变,那就会输出,得到一个数组 promise.race()里面只有一个状态变为rejected或者fulfilled即输出 promis.finally()不管指定不管Promise对象最后状态如何,都会执行的操作(本质上还是then方法的特例)
数组去重(手写代码):
let arr = [1, 2, 3, 4, 5, 1, 2, 3, 5, 6, 7, 8, 1, 5];
function noRepeat(arr) {
let result = [];
for(let i = 0; i < arr.length; i++) {
if(!result.includes(arr[i])) {
result.push(arr[i]);
}
}
return result;
}
console.log(noRepeat(arr));
字符串反转(手写代码):
var num = "123456789";
var result = num.split('').reverse().join('');
console.log(result);
闭包闭包作用:
闭包就是能够读取其他函数内部变量的函数。闭包是将函数内部和函数外部连接起来的桥梁。
作用可以读取函数内部的变量让这些变量的值始终保持在内存中
缺点1.闭包的缺点就是常驻内存会增大内存使用量,并且使用不当容易造成内存泄漏2.如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。
原型 原型链:
作用域 作用域链:
作用域就是变量与函数的可访问范围
作用域分为全局作用域(所声明的变量全局都可以访问),局部作用域(所声明的变量只在其内部可以访问)
作用域链:当我们在一个函数内部访问当前作用域内不存在的变量时,就会逐层向外查找,如果一直找不到就会报错。当我们在局部作用域中,调用外部变量时,就产生了作用域链
描述一次完整的http请求:
查询NDS(域名解析),获取域名对应的IP地址查询浏览器缓存 2.浏览器与服务器建立tcp链接(三次握手)
第一次握手:客服端发送一个请求连接,服务器端只能确认自己可以接受客服端发送的报文段 第二次握手:服务端向客服端发送一个链接,确认客服端收到自己发送的报文段 第三次握手:服务器端确认客服端收到了自己发送的报文段3.浏览器向服务器发送http请求(请求和传输数据)4.服务器接受到这个请求后,根据路经参数,经过后端的一些处理生成html代码返回给浏览器5.浏览器拿到完整的html页面代码开始解析和渲染,如果遇到外部的css或者js,图片一样的步骤6.浏览器根据拿到的资源对页面进行渲染,把一个完整的页面呈现出来
浏览器是如何渲染页面的:
流程:解析html以及构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树 概念:
1.构建DOM树: 渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)生成内容树 2.构建渲染树: 解析对应的css样式文件信息(包括js生成的样式和外部的css) 3.布局渲染树:从根节点递归调用,计算每一个元素的大小,位置等。给出每个节点所在的屏幕的精准位置 4.绘制渲染树:遍历渲染树,使用UI后端层来绘制每一个节点
事件委托的原理:
事件委托又叫事件冒泡,指把自身的事件交给父元素或祖先元素代为执行
什么是深拷贝什么是浅拷贝:
把字符串转驼峰(手写) 例get-element-by-id转为getElementById:
let str = 'get-element-by-id';
function toCamBakStr(str){
let strArr = str.split('-');
for(let i = 1; i < strArr.length; i++){
let start = strArr[i].charAt(0).toUpperCase();
let end = strArr[i].slice(1);
strArr[i] = start + end;
}
return strArr.join('');
}
let newStr = toCamBakStr(str);
console.log(newStr)//getElementById
http常见的状态码:
200:服务器成功处理了请求
400:客户端发送了一个错误的请求
404:未找到资源
405:客户端请求的额方法被禁止
408:服务器等待客户端发送的请求时间过长,超时
500:服务器内部出现错误
501:服务器遇到错误,使其无法对请求提供服务
同步异步问题:
同步:由于js单线程,同步任务都在主线程上排队执行,前面任务没有执行完成,后面的任务会一直等待 异步:不进入主线程,进入任务队列,等待主线程任务执行完成,开始执行。最基本的异步操作SetTimemot和SetInterval,等待主线程任务执行完,在开始执行里面的函数
举个例子.........
前端性能优化手段:
尽可能使用雪碧图
使用字体图标代替图片
Html,css,js文件进行压缩
模块按需加载
资源懒加载与资源预加载
避免使用层级较深的选择器,以提高css渲染效率
缓存DOM,减少DOM深度以及DOM数量
移动端点透问题,如何解决:
点透问题出现的原因就是移动端click事件300ms延迟问题,当点击上层元素时,先触发touchstart事件,然后在300ms后会触发click事件,而此时上层元素已经消失,所以下边的元素会触发click事件,这就是点透
解决方法:
使用一个透明遮罩,屏蔽所有事件,然后400ms(对于IOS来说是个理想值)后自动屏蔽
touchstart换成touchend,因为触发touchend需要200ms所以可以把触发时间这个原理问题解决掉
zepto最新版已经修复了这个问题,或者使用fastclick等通用库
直接使用click,不考虑延迟
下层避开click事件,如a链接改为span等标签,使用js跳转页面
Javascript数据类型:
Number String Undefined Null Object Boolean Symbol
单页面和多页面的区别优缺点:
判断字符串中出现次数最对的字符窜,并统计出现的次数(手写代码):
var string = 'yhthththt';
var obj = new Object();
for(var i=0;i<string.length;i++){
var value = string.charAt(i);
console.log(value)
if(obj[value]>0){
obj[value]++;
}else{
obj[value]=1;
}
}
for(var a in obj){
console.log(a+"出现的次数"+obj[a]+"次")
}
将数字12345678转化成 RMB 形式 如: 12,345,678(手写代码):
let price = 12345678;
function toRMB(price) {
let strArr = (price + '').split('').reverse();
let result = [];
for (let i = 0; i < strArr.length; i++) {
if (i % 3 === 0 && i !== 0) {
result.push(',');
}
result.push(strArr[i]);
}
return result.reverse().join('');
}
console.log(toRMB(price)); // 12,345,678
Es6你都用过哪些:
Css优先级算法:
!important>内联>ID选择器>class选择器>元素选择器>通配符选择器>继承>浏 览器默认属性