前端常见面试题二十一
目录:
1、手写promise封装axios
2、如何解决回调地狱
3、请详解移动端点透发生场景、原因及解决方案(最优)
4、详述前端性能优化的手段
5、浏览器输入网址回车发生了什么
6、页面的渲染过程
7、列举你知道的浏览器内核
8、如何优化SPA首屏加载慢的问题
1、手写promise封装axios
import Axios from "axios";
class Http {
//request 方法
request(params) {
return new Promise((resolve, reject) => {
Axios({
method: params.type || "get",
url: params.url,
data: params.data,
headers: params.headers
})
.then(res => {
if (res.data.code === 0) {
resolve(res);
} else {
alert(res.data.msg);
}
})
.catch(err => {
reject(err.statusText); //失败
});
});
}
}
export default Http;
使用:
ps:注册短信验证码的请求
//引入封装好的axios
import Http from "../utils/http";
//实例化一个类
const _http = new Http();
//注册的请求
class RegisterRequest {
//短信验证码
CodeVerifier(mobile) {
return _http.request({
url: `https://api.it120.cc/small4/verification/sms/get?mobile=${mobile}`
});
}
}
//抛出
export default RegisterRequest;
页面中引用
//引入
import Product from "../services/product";
//实例化
const _product = new Product();
export default {
created(){
_product.CodeVerifier().then(res => {
//res 就是响应回来的数据
res.data.data;
});
}
}
目录结构
2、如何解决回调地狱
1. 拆解 function:将各步拆解为单个的 function
function buildCatList(list, returnVal, fn) {
setTimeout(function (name) {
var catList = list === '' ? name : list + ',' + name
fn(catList)
}, 200, returnVal)
}
buildCatList('', 'Panther', getJanguar)
function getJanguar(list) {
buildCatList(list, 'Janguar', getLynx)
}
function getLynx(list) {
buildCatList(list, 'Lion', print)
}
function print(list) {
console.log(list)
}
定时器中的回调函数处在外层函数中的作用域内,并通过参数传入,没有产生全局变量,没有重复代码。但是 function 拆分的方式其实仅仅只是拆分代码块,时常会不利于后续维护
2. 通过 Promise 链式调用的方式
function buildCatList(list, returnVal) {
return new Promise(function (resolve, reject) {
setTimeout(function (name) {
var catList = list === '' ? name : list + ',' + name
resolve(catList)
}, 200, returnVal)
})
}
buildCatList('', 'Panther').then(function (res) {
return buildCatList(res, 'Janguar')
}).then(function (res) {
return buildCatList(res, 'Lion')
}).then(function (res) {
console.log(res)
})
// Panther,Janguar,Lion
Promise 函数虽然改变了之前回调地狱的写法,但是在根本上还是函数套函数,看起来不是那么的美观
参考地址:https://blog.csdn.net/fu983531588/article/details/89476190
3、请详解移动端点透发生场景、原因及解决方案(最优)
点透场景:
层A覆盖在层B上面,常见的有对话框等,层A用touchstart或者tap(zepto)事件点击进行隐藏或者移开,由于click晚于touchstart,超过300ms,当层A隐藏后,click到的是下面的层B,此时层B的click事件会触发,或者其上的a链接会跳转,input,select会吊起键盘。
解决方案:
1、使用一个(透明)遮罩层,屏蔽所有事件,然后400ms(对于IOS来说是个理想值)后自动隐藏
.touchFix{visibility: hidden;width: 100%;height: 100%;position: absolute;left: 0px;top: 0px;z-index: 9999;}
2、 touchstart换成touchend,因为触发touchend需要200ms所以可以把触发时间这个原理问题解决掉
$("#cbFinish").on("touchend", function (e) {
e.preventDefault();
});
3、下层避开click事件,如a链接改为span等标签,使用js跳转页面
4、 zepto最新版已经修复了这个问题,或者使用fastclick、hammer等通用库
zepto的tap事件原理zepto的tap事件是通过touchstart,touchend(android 4.0.x不支持touchend,通过touchmove 设置定时器触发touched)模拟出来的,事件是绑定在document上,大体思路是在touchstart的时候向对象附加点击的x,y;(其中还包含很多细节,比如设置最后点击时间,设置长按定时器等);touchmove的过程动态的计算手势在view上的偏移点,最后touchend 根据偏移点确定是否是点击,如果是点击动态的构建一个event然后根据
设置的状态获取是单机、双击。非zepto的tap事件未必会出现点透问题。
4、详述前端性能优化的手段
链接:https://www.nowcoder.com/questionTerminal/47e17ccb60d64fb9878a678cbdb81e96?toCommentId=398202
来源:牛客网
1.内容方面
减少http请求
代码压缩
js代码写在</body>之前
浏览器缓存(cookie/sessionStorage/localStorage)
将静态资源放置在子域名下,实现并行下载数目增加
缓存ajax结果
减少DOM节点数
2.服务器方面
cdn加速
gzip压缩
3.js
引用压缩过的库(.min)
减少操作DOM节点,必要时将节点缓存起来(离线更新);
少用递归或者用尾递归优化
减少全局变量
懒加载
预加载
4.css
精简css代码的编写,减少嵌套层次
使用sprite图
尽量采用简写
用link代替@import
动画要用在脱离文档流的元素上
5.图片处理
图片一般要压缩到小于200k(banner等)
可将资源放至子域名下
用iconfont代替小图标
5、浏览器输入网址回车发生了什么?
1、建立TCP连接
2、Web浏览器向Web服务器发送请求命令
3、Web浏览器发送请求头信息
4、Web服务器应答
5、Web服务器发送应答头信息
6、Web服务器向浏览器发送数据:
7、Web服务器关闭TCP连接 :
6、页面的渲染过程
1.解析html文件,创建DOM树
自上而下解析,遇到任何样式(link、style)和脚本(script)都会阻塞
1)css加载不会阻塞html文件的解析,但会阻塞dom的渲染
2)css加载会阻塞后面js语句的执行
3)js会阻塞html的解析和渲染
4)没有defer和async标签的script会立即加载并执行
5)有async标签的js,js的加载执行和html的解析和渲染并行
6)有defer标签的js,js的加载和html的解析和渲染并行,但会在html解析完成后执行,在触
发DOMContentLoaded事件前执行
7)DOMContentLoaded和onload的区别:DOMContentLoaded在html解析完毕后执行,loload在页面完全加载完成后执行(包括样式和图片)
2.解析css,生成CSSOM,css对象模型
3.dom和css合并,构建渲染树(Render Tree)
4.布局(Layout)和绘制(Paint),重绘(repaint)和重排(reflow/回流)
1)重绘:根据元素的新属性重新绘制,使元素呈现新的外观
2)重排:当渲染树中的一部分因为元素的规模尺寸,布局,隐藏等改变而需要重新构建
3)重排必定会引发重绘,但重绘不一定会引发重排
监听资源加载完成有四种方式
1. window.onload = function(){....}
2. window.addEventListener("load",function(){....});
3. document.body.onload = function(){....}
4. <body onload = "load()">
7、列举你知道的浏览器内核
1、Trident内核代表产品Internet Explorer,又称其为IE内核。Trident(又称为MSHTML),是微软开发的一种排版引擎。使用Trident渲染引擎的浏览器包括:IE、傲游、世界之窗浏览器、Avant、腾讯TT、Netscape 8、NetCaptor、Sleipnir、GOSURF、GreenBrowser和KKman等。
2、Gecko内核代表作品Mozilla FirefoxGecko是一套开放源代码的、以C++编写的网页排版引擎。Gecko是最流行的排版引擎之一,仅次于Trident。使用它的最著名浏览器有Firefox、Netscape6至9。
3、WebKit内核代表作品Safari、Chromewebkit 是一个开源项目,包含了来自KDE项目和苹果公司的一些组件,主要用于Mac OS系统,它的特点在于源码结构清晰、渲染速度极快。缺点是对网页代码的兼容性不高,导致一些编写不标准的网页无法正常显示。主要代表作品有Safari和Google的浏览器Chrome。
4、Presto内核代表作品OperaPresto是由Opera Software开发的浏览器排版引擎,供Opera 7.0及以上使用。它取代了旧版Opera 4至6版本使用的Elektra排版引擎,包括加入动态功能,例如网页或其部分可随着DOM及Script语法的事件而重新排版。
上述所言只列举四大代表浏览器内核
8、如何优化SPA首屏加载慢的问题
1、模块化开发
2、利用懒加载技术
3、抽取css文件
4、采用预渲染
5、gzip代码压缩