金三银四,又到了每年换工作的黄金时间,正好最近也准备找新工作,顺便将面试过程中的一些题目进行总结。
JS 相关问题
1.js 中事件执行顺序?
先进行事件捕获过程、然后调用目标元素事件,最后执行事件冒泡。
2.事件捕获和事件冒泡之间的区别。
在操作一堆嵌套的元素时,如果目标元素嵌套在第四层,那么当点击目标元素时会从第一层捕获到第四层目标元素上,然后此时执行目标元素绑定的事件,结束后从目标元素开始又一层一层向上冒泡。
通过 obj.addEventListener(event,function(){},bool)
的 bool 属性来确定捕获阶段和冒泡阶段,bool 为 true 时,当前函数捕获阶段触发。反之为冒泡阶段触发。
阻止冒泡 w3c 的方法是 e.stopPropagation(),IE 则是使用 e.cancelBubble = true;
额外知识点: 如果在捕获阶段阻止了事件,那么此流程就会被阻止掉,不会触发后续的操作。
3.什么是闭包? 你有没有在实际开发中使用过?
闭包就是能够读取其他函数内部变量的函数。由于在 Javascript 语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
使用闭包的注意点:
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在 IE 中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
- 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
特别注意
开发中使用的地方,比如我定义了一个函数,这个函数会帮我在页面生成一些 dom,如果不做限制的话,每次 new 函数就会生成一次,如果恶意操作会造成页面卡顿等。
let ProxySingletonDialog = (function () {
let instance, initFlag;
return function (option) {
if (!instance) {
initFlag = false;
instance = new Dialog({ ...option, initFlag });
}
return instance;
};
})();
window.Dialog = ProxySingletonDialog;
4.节流防抖函数。
函数节流:是确保函数特定的时间内至多执行一次。 函数防抖:是函数在特定的时间内不被再调用后执行。
节流函数
let canRun = false;
function throttle() {
if (!canRun) {
canRun = true;
setTimeout(() => {
canRun = false;
console.log('节流函数');
}, 1000);
}
}
window.addEventListener('resize', throttle, false);
防抖函数
function debounce(fn, delay) {
let timer = null;
return (...arg) => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arg);
}, delay);
};
}
function click() {
console.log('防抖函数');
}
document.addEventListener('click', debounce(click, 200), false);
vue 相关问题
1.vue 生命周期是什么?
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
setup --> 代替了 vue2 中的 create 阶段函数
onBeforeMount
onMounted
onBeforeUpdate
onUpdated
onBeforeUnmount
onUnmounted
2.vue 中的$nextTick()是什么?
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。
$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
3.axios 有没有二次封装? 封装了哪些功能?
有过封装,比如在请求拦截器中,给header
中添加 Token,或者通过参数修改请求头格式等。
加载全局请求 Loading 状态。在请求开始前打开,结束后关闭。
在返回拦截器中对返回 code 状态进行判断,无权则跳转无权界面,错误则跳转错误界面,随后将正确请求内容 return 出去。
4.如何处理用户登录逻辑以及获取用户信息的功能?
可以在 vuex 中定义好用户的基本信息,然后在用户登录时将后端返回的信息更新到 vuex 中,并将返回的 Token 信息存放在 cookies 中。登录成功后使用 router 的 push 方法跳转路由到 home 页面。
因为 vuex 里的内容在刷新后就不存在了,所以我使用如下方法:
在路由守卫的钩子函数中查找 vuex 中的某一项用户信息是否存在,如果存在则进行其他的操作,例如权限判断。反之不存在的话,就需要通过另外一个获取用户信息的接口来拿到用户信息,并更新 vuex 中相对应的属性。
通过这一接口在每次刷新页面后就可快速拿到用户数据。
5.你们的项目中是怎么处理权限问题的?
1.前端效验法
在定义路由初期时就定义好一个自定义属性,例如 access
属性,标志好权限内容,将权限内容发给后端,后端给对应的用户添加上当前权限内容。
在路由守卫的钩子函数中,每次路由的跳转都进行权限的效验,如果当前用户登录后的用户信息中并没有当前路由的权限,就跳转无权页面。反之则通过,使用next()
方法进行路由处理。
至于侧边菜单栏的生成,需要在项目运行初期先进行权限比对,生成有权路由信息,交给封装好的侧边栏组件进行渲染。
2.后端返回法
在项目开始初期就先进行路由信息输入页面的处理,将新页面的信息录入到后端,并在权限分配页面进行用户权限的分配。
用户登录后,在路由守卫的钩子函数中,将后端返回的路由表信息进行逻辑处理,将杂乱的信息转化为 vue-router 可识别的对象数据。通过addRoute()
方法将生成的路由表 push 进 router 对象中。
侧边栏就可以直接使用生成的内容进行渲染
6.有没有使用过混入方法?
使用过,混入方法主要用来提取一些页面公共方法,减少代码的冗余。常见业务就是比如在表格中会有排序方法,然后分页中也会有一些关于分页内容的方法,这些方法函数都是一致的,所以可以抽离出来,使得其他页面可以共用。
7.组件传值有哪些?
常见的三个方法在这里 《组件传值》
补充方法:vuex
provide/inject
8.自己封装过组件吗? 如果两个组件中有 80%的共用部分请问如何抽离?
使用
包括匿名插槽、具名插槽等slot插槽使用方法
9.在提交一次表单后,如何快捷的将表单绑定的对象进行重置?
使用 this.$options().data.xxxx
xxxx 代指的就是需要重置的对象。
10.在使用一些第三方 UI 组件时,如果更新他们的默认样式?
1.可以在调用初期使用 UI 组件提供的初始化方法将组件重构成自己需要的样式,比如修改整体颜色之类的。
2.在 vue 文件中,可以通过使用样式穿透方法进行样式调整。.父元素class /deep/ .需要调整元素class
11.vue 双向绑定原理?
在 new Vue() 后传入了基本数据,Vue 会先把 data 的内容通过Object.defineProperty()
劫持。然后调用Observer类
将劫持后数据内部的属性再劫持处理一次。
在这个过程中,会在数据处理的 get 方法中将观察者Dep类
注入,并会在 set 方法中通知所有的订阅者更新视图。在Compiler类
中将页面中的特殊指令和模板解析,然后调用 data 中的对应属性进行替换,并在相应的处理函数中将订阅者绑定。订阅者Watcher类
会先把自身存放进观察者属性中,绑定后订阅者会先触发一次 get 方法,将自己添加进观察者的通知队列中。然后双向绑定的地方需要使用 dom 的属性方法比如 input 的 input 方法将数据改动后告诉 set 方法,那么观察者就会通知队列进行更新。
CSS 相关问题
1.css 中怎样实现垂直居中布局?
1.弹性盒子布局。 2.子绝父相。 3.网格布局。
问题分析。主要就是考一下基础的 css 属性组合,酌情回答两到三种就可以了。垂直居中布局详解
2.css 中弹性盒子使用过没有?使用了什么属性?
具体可查看之前分享的弹性盒子内容,不做赘述。
3.css 一个 div 元素如何实现汉堡包菜单图标?
如左图所示
<div class="box"></div>
<style>
.box {
position: relative;
width: 20px;
height: 3px;
top: 6px;
background: #333;
}
.box::before,
.box::after {
position: absolute;
content: ' ';
width: 20px;
height: 3px;
background: #333;
}
.box::before {
top: -6px;
}
.box::after {
top: 6px;
}
</style>
其他问题
1.假设页面中的侧边栏菜单有 5000 条,需要如何处理才能更好的平衡性能和用户体感?
1.分步渲染,先对侧边栏的数据进行处理,比如先展示 20 条,通过数组的切割方法,将数据剥离渲染。
2.滚动监听,监听侧边栏滚动,如果滚动到底部,展示 loading 状态。并再次切割数据,更新渲染。关闭 loading 展示。
2.ifream 父子页面之间如何通信?
Caleb https://reinness.com/posts/38 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自小陈博客 !
厉害,收藏了