1.请先自我介绍一下
2.从你所做的项目中,说说你遇到的难点
3.有没有封装过axios,怎么封装的
4.什么是拦截器?拦截器的实现原理是什么
对请求的拦截,Axios的拦截器有两种,请求拦截器
和响应拦截器
,只要为axios实例添加拦截器每个api请求都会执行拦截器。执行顺序: 请求拦截器 -> api请求 -> 响应拦截器
。 使用方式如下
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
// 取消拦截器
const interceptorId = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(interceptorId);
拦截器的源码分析
// 请求拦截器和响应拦截器使用的都是 InterceptorManager构造函数
function Axios(instanceConfig) {
this.defaults = instanceConfig;
// 请求拦截器和响应拦截器使用的都是 InterceptorManager构造函数
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
InterceptorManager构造函数有handlers数组,保存所有的拦截函数, 并且在它的原型上添加三个方法, use用于添加拦截函数
, 返回一个id, eject用于取消拦截器
, forEach遍历所有拦截器。
// 拦截器构造函数
function InterceptorManager() {
// 保存拦截器的数组,axios.interceptors.use的拦截函数会被push到handlers,可以添加多个拦截器
this.handlers = [];
}
// 向拦截器原型上挂载 use方法, 向handler数组中push一个对象, 返回一个id
// 这样就可以通过eject(id) 取消拦截函数了。
InterceptorManager.prototype.use = function use(fulfilled, rejected)
{
this.handlers.push({ fulfilled: fulfilled, rejected: rejected });
return this.handlers.length - 1;
};
// 移除拦截器
InterceptorManager.prototype.eject = function eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null;
}
};
// 遍历执行所有拦截器
InterceptorManager.prototype.forEach = function forEach(fn) {
utils.forEach(this.handlers, function forEachHandler(h) {
if (h !== null) {
fn(h);
}
});
};
理解拦截器思想
其实就是简单的数组,请求拦截器发生在api请求之前, 响应拦截器发生在api请求之后,仔细思考🤔一下,其实它们本质上只是一个执行顺序的关系
。 这其实就是一个数组chain能实现的,把请求拦截器的函数推到数组前面, api请求放在中间, 响应拦截器放在数组后面,遍历执行数组chain就实现了拦截器的执行顺序关系,是不是很简单
达到实现,请求拦截器 -> api请求 -> 响应拦截器 执行顺序的目的。
// dispatchRequest是api请求
var chain = [dispatchRequest, undefined];
// 把请求拦截器数组this.interceptors.request 用unshift放在 chain 数组的前面
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});
// 把响应拦截器this.interceptors.response 用push放在chain数组的后面
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
chain.push(interceptor.fulfilled, interceptor.rejected);
});
5.map的原理是什么,平时怎么用
Array.prototype.map = function(fn) {
let newArr = [];
for (let i = 0; i < this.length; i++) {
newArr.push(fn(this[i]))
};
return newArr;
}
// 用 map 映射,map()方法返回一个新数组
案例:forEach用es5一步步拆解
var a = [1,2,3,4]
Array.prototype.forEach= function(fn) {
let newArr = []
console.log(fn, 'fn') // ƒ (item) {return item>2 } 'fn'
for(let i=0;i<this.length;i++) {
console.log(this[i]) // 1,2,3,4
console.log(fn(this[i]), 'fn(this[i])') // false false true true
if(fn(this[i])){
newArr.push(this[i])
}
}
console.log(newArr, 'newArr') // [3, 4] 'newArr'
return newArr
}
实现
// 写一个fn方法
var fn = function(item) {
return item>2
}
var result = a.forEach(fn)
console.log(result, 'result') // [3, 4] 'result'
6.reduce的原理是什么,它有几个值,举个平时的使用例子说说
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值案例
var arr=[2,4,6,8];
let result=arr.reduce(function (val,item,index,origin) {
return val+item
},0);
console.log(result) //20
实现原理
Array.prototype.reduce = function (reducer,initVal) {
for(let i=0;i<this.length;i++){
initVal =reducer(initVal,this[i],i,this);
}
return initVal
}
7.有没有做过下载,下载是怎么实现的,在下载过程中,下载中断了,进度条怎么继续
8.http和axios的区别,从url输入访问请求,和发起请求有什么不同
9.管理系统的菜单,路由是怎么实现的
10.数组怎么去重,如果是json数组,怎么去重?空间复杂度为多少?
11.做开发平台菜单的时候,你说用到算法,减轻了30%的服务器请求,你是怎么实现的?
12.css3常用吗,一般用到哪些
13堆和栈是什么
14.MVVM是什么,具体描述一下
简写Model-View-ViewModel
在前端页面中,把Model用纯JavaScript对象表示,View负责显示,两者做到了分离。
把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。
MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。关注Model的变化,让MVVM框架去自动更新DOM的状态
15.watch和computed的实现原理是什么,区别是什么
16.props为什么可以直接用this调用
(1) initState > initProps > defineReactive(props, key, value)
通过 this
直接访问到 props
里面的数据的原因是:props里的属性最终会存储到new Vue
的实例(vm
)上的 _props 对象中,访问 this.xxx
,是访问Object.defineProperty
代理后的 this._props.xxx
。
(2) initState > initMethods> bind(methods[key], vm)
通过this
直接访问到methods
里面的函数的原因是:因为methods
里的方法通过 bind
指定了this
为 new Vue的实例(vm
)。
(3) initState > initData> observe(vm._data = {}, true)
通过 this
直接访问到 data
里面的数据的原因是:data里的属性最终会存储到new Vue
的实例(vm
)上的 _data
对象中,访问 this.xxx
,是访问Object.defineProperty
代理后的 this._data.xxx
。
17.vue搭建项目的命令
npm install -g vue-cli
vue init webpack my-project
cd my-project
npm install
npm run dev