一、CSS相关面试题?
1.1 flex布局---微信小程序[常用flex:水平垂直居中、左右对称]
学习地址:www.runoob.com/w3cnote/fle…
1.2 移动端适配方案
1. viewport适配
- 为什么做viewport适配
- 手机厂商在生产手机的时候大部分手机默认页面宽度为980px
- 手机实际视口宽度都要小于980px,如: iphone6为375px
- 开发需求: 需要将980的页面完全显示在手机屏幕上且没有滚动条
- 实现:
2 .rem适配
- 为什么做rem适配
- 机型太多,不同的机型屏幕大小不一样
- 需求: 一套设计稿的内容在不同的机型上呈现的效果一致,根据屏幕大小不同的变化,页面中的内容也相应变化
- 实现:
function remRefresh() {
let clientWidth = document.documentElement.clientWidth;
// 将屏幕等分10份
let rem = clientWidth / 10;
document.documentElement.style.fontSize = rem + 'px';
document.body.style.fontSize = '12px';
}
window.addEventListener('pageshow', () => {
remRefresh()
})
// 函数防抖
let timeoutId;
window.addEventListener('resize', () => {
timeoutId && clearTimeout(timeoutId);
timeoutId = setTimeout(() =>{
remRefresh()
}, 300)
})
- 第三方库实现
lib-flexible + px2rem-loader
1.3 link与@import区别
blog.csdn.net/weixin_4434…
本质上,这两种方式都是为了加载css文件,但还是存在细微的差别。
- 差别1:老祖宗的差别,link属于XHTML标签,而@import完全是css提供的一种方式。 link标签除了可以加载css外,还可以做很多其他的事情,比如定义RSS,定义rel连接属性等,@import只能加载CSS。
- 差别2:加载顺序的差别:当一个页面被加载的时候(就是被浏览者浏览的时候),link引用的CSS会同时被加载,而@import引用的CSS会等到页面全部被下载完再加载。所以有时候浏览@import加载CSS的页面 时会没有样式(就是闪烁),网速慢的时候还挺明显。
- 差别3:兼容性的差别。由于@import是CSS2.1提出的所以老的浏览器不支持,@import只有在IE5以上的才能识别,而link标签无此问题,完全兼容。
- 差别4:使用dom控制样式时的差别。当使用JavaScript控制dom去改变样式的时候,只能使用link标签,因为@import不是dom可以控制的(不支持)。
- 差别5(不推荐):@import可以在css中再次引入其他样式表,比如创建一个主样式表,在主样式表中再引入其他的样式表
二、业务面试
2.1 防抖节流面试:基本改变、原理[闭包+延迟器]
相同:在不影响客户体验的前提下,将频繁的回调函数,进行次数缩减.避免大量计算导致的页面卡顿.
不同:防抖是将多次执行变为最后一次执行,节流是将多次执行变为在规定时间内只执行一次.
//防抖函数
function debounce(func, wait) {
var timeout;
return function () {
var context = this;
var args = arguments;
clearTimeout(timeout)
timeout = setTimeout(function () {
func.apply(context, args)
}, wait);
};
};
//节流函数
function throttle(func, wait){
var context, args, timeout;
return function() {
context = this;
args = arguments;
if(!timeout) {
timeout = setTimeout(function(){
func.apply(context, args);
timeout = null;
}, wait);
}
}
}
开发的时候防抖与节流功能使用lodash
2.2 路由传递参数?
问题:vue-router路由传递参数有几种形式?
答:params|query
问题:如何通过代码获取query|params参数?
答:this.route.query.xxxx
问题:params参数可有可无?
答:在路由配置文件中,在占位符后面加一个问号
问题:route区别?
答:route:路由,可以获取路由相关的参数:path、query、params、meta等等
路由传递参数:传递基本类型数据没有问题,但是不能传递引用类型数据
2.3 组件通信手段有哪些?
props 自定义事件 全局事件总线 vuex v-model ref lisenters children sync 插槽
2.4 图片懒加载实现原理是啥?
2.5 工作的时候,是否自己封装过通过的组件?
我的工作时候自己封装过一些通用的组件:分页器(实现的)、按钮等等
2.6 项目优化手段有哪些?
防抖与节流 路由懒加载 事件委派 按需引入 v-if|v-show ***** 请求次数的优化->三级分类发请求App.vue
2.7 项目持久化你们用什么?有什么缺点?
locaStore|sessionStroage:存储数据上限5M
2.8 vuex相关?
vuex核心概念有哪些, state mutations actions getters modules
v-model能否直接修改vuex仓库数据:不能走流程
vuex是不是持久存储数据
2.9 购物车如何实现?说说原理?
通过请求头携带功能参数:token|userTempId,服务器会通过标识的表示返回相应的数据!!!!
2.10 Promise相关面试?
手写Promise
//声明函数 执行器 『同步回调』
function Promise(executor) {
//设置实例对象的属性
this.PromiseState = 'pending';
this.PromiseResult = undefined;
this.callbacks = [];
//声明函数
const success = (value) => {
if (this.PromiseState !== 'pending') return;
//修改状态为成功 PromiseState
this.PromiseState = 'fulfilled';
//设置成功的结果值 PromiseResult
this.PromiseResult = value;
//调用回调
if (this.callbacks.length > 0) {
this.callbacks.forEach(cbObj => {
//执行成功的回调
cbObj.ok();
})
}
}
const fail = (reason) => {
if (this.PromiseState !== 'pending') return;
//修改状态为失败 PromiseState
this.PromiseState = 'rejected';
//设置成功的结果值 PromiseResult
this.PromiseResult = reason;
//调用回调
if (this.callbacks.length > 0) {
this.callbacks.forEach(cbObj => {
//执行成功的回调
cbObj.ng();
})
}
}
try {
//调用执行器函数
executor(success, fail);
} catch (e) {
//调用 fail 函数
fail(e);
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
//判断 异常穿透
if(typeof onRejected !== 'function'){
onRejected = reason => {throw reason};
}
//值传递
if(typeof onFulfilled !== 'function'){
onFulfilled = value => value;
}
return new Promise((resolve, reject) => {
//封装函数简化代码
let callback = (type) => {
try {
let res = type(this.PromiseResult);
//判断
if (res instanceof Promise) {
res.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
resolve(res);
}
} catch (e) {
reject(e);
}
}
//判断 成功
if (this.PromiseState === 'fulfilled') {
setTimeout(() => {
callback(onFulfilled);//
})
}
//失败
if (this.PromiseState === 'rejected') {
setTimeout(() => {
callback(onRejected);
})
}
//pending
if (this.PromiseState === 'pending') {
//保存回调
this.callbacks.push({
ok: function () {
//成功
callback(onFulfilled);
},
ng: function () {
callback(onRejected);
}
})
}
});
}
Promise.prototype.catch = function(onRejected){
return this.then(undefined, onRejected);
}
Promise.resolve = function(value){
return new Promise((resolve,reject) => {
//判断
if(value instanceof Promise){
//value.then(resolve, reject); 这行代码和下面5行代码功能一样
value.then(v=>{
resolve(v);
}, r => {
reject(r);
});
}else{
resolve(value);
}
})
}
Promise.reject = function(reason){
return new Promise((resolve, reject) => {
reject(reason);
})
}
Promise.all = function (promiseArr) {
return new Promise((resolve, reject) => {
let count = 0;
let arr = [];
for (let i = 0; i < promiseArr.length; i++) {
promiseArr[i].then(v => {
count++;
arr[i] = v;
if (count === promiseArr.length) {
resolve(arr);
}
}, r => {
reject(r);
});
}
});
}
Promise.race = function (promiseArr) {
return new Promise((resolve, reject) => {
promiseArr.forEach(item => {
item.then(v => {
resolve(v);
}, r => {
reject(r);
});
});
});
}
2.11 token相关面试?
token:token是令牌,是用户唯一身份标识,当用户登录成功以后获取相应的token!!
token用途:可以利用token获取用户信息!!!
token过期怎么处理:清空本地数据、发请求通知服务器清空数据、让用户重新登录获取新的token!!!
2.12 守卫?
守卫有几种:三种 全局守卫:beforeEach、afterEach 路由独享守卫:beforeEnter 组件内守卫:beforeRouteEnter beforeRouteUpdate (2.2 新增) beforeRouteLeave
2.13 axios自己是否封装过?封装作用是什么?
答:axios我曾经自己封装过,主要为了添加请求、响应拦截器!!!
请求响应拦截器有啥功能:进度条、请求拦截器携带公共参数!!!
2.14 数组去重|深拷贝|浅拷贝|
数组去重:indexOf
递归实现深拷贝
//老对象
let obj = {
name : 'atguigu',
pos : ['北京','上海','深圳','武汉','西安'],
founder : {
name : '刚哥',
age : 35
},
test:function(){
console.log('测试')
console.log(this)
}
}
//封装深拷贝函数
function deepClone(oldObj){
//1.准备一个容器(对象 数组)
let wrapper;
//2.根据老对象判断数据类型,决定容器是 {} 还是 []
let type = getDataType(oldObj)
if(type === 'Array'){
wrapper = [];
}
if(type === 'Object'){
wrapper = {}
}
//3.给容器添加新属性
//枚举老对象的属性
for(let item in oldObj){
//item 是对象的每一个属性
// wrapper[item] = '123'
//根据属性值的数据类型去添加
let typeItem = getDataType(oldObj[item])
if(typeItem === 'Object' || typeItem === 'Array'){
//如果是对象或者数组,
wrapper[item] = deepClone(oldObj[item]);
}else if(typeItem === 'Function'){
//如果是函数,通过 bind()去添加
wrapper[item] = oldObj[item].bind(wrapper)
}else{
//如果是普通的数据类型,直接添加
wrapper[item] = oldObj[item];
}
}
//返回值:是新对象
return wrapper;
}
//新对象
let newObj = deepClone(obj)
console.log(newObj)
//封装函数:判断数据类型的
function getDataType(data) {
if(typeof data === 'object'){
if(data instanceof Array){
//数组
return 'Array';
}else {
//对象
return 'Object';
}
}else if(typeof data === 'function'){
//函数
return 'Function';
}else {
//num str bool (基本数据类型)
return false;
}
}
2.15 跨域
JSONP,百度预搜索 CROS 代理跨域
2.16 后台项目一般架子用的是element-UI!!!![element-ui版本问题:不同版本写法不一样]
form、button、table、pagination、card等等
2.17 scoped作用?底层原理是啥那?
scoped作用:局部样式[子组件只有根节点可能受到影响] 当前VC加上scoped属性后:DOM节点和子组件根节点,添加上相同的data-v-xxxx,通过属性选择器实现的!!!
2.19 功能时候用element-ui插件如何调试样式?深度选择器
>>> /deep/ ::v-deep
2.20 菜单|按钮权限原理你说说? ******
第一步:将项目的路由进行拆分:常量路由、异步路由、任意路由
第二步:根据用户的信息筛选出用户全部路由!!!
2.21 你用过echarts吗?echarts是啥?
数据可视化的插件,底层用什么写的
2.22 HTML5中新增了特性?
语义化标签:nav、footer、main、canvas CSS3 动画、2D、3D 多媒体:视频、音频 本地存储 canvas
2.23 ES6新增那些特性?
let const 箭头函数、数组迭代方法、set、map 、symbol等等
2.24 数组的迭代方法你知道那些>
forEach\filter\map\reduce
2.25 reduce引用的场景!!! 购物车计算综合
2.26 闭包的应用场景?
闭包面试:可以访问外层作用于变量的函数,称之为闭包。 闭包的缺点,对于外部引用一致存在,耗内存!!! 防抖与节流