文章目录
一面
html+css+js
1.盒子怎么垂直居中
- inline元素: line-height的值等于height值
- absolute元素: top:50% + margin-top负值
- absolute元素:transform: translate(-50%, -50%)
- absolute元素:top, left, bottom, right = 0 + margin: auto
- flex:(display: flex; flex-direction: column; justify-content: center;)
2.响应式布局的方式
- 媒体查询(media-query),根据不同的屏幕宽度设置根元素font-size
- flex 布局
- 百分比布局
3.怎么将一个dom节点删除?删除的时候要考虑哪些问题
-
obj. removeChild(oldChild) —— 需要注意的是,该方法是在要删除节点的父节点上调用,要删除的节点作为该方法的参数。
-
拓展:如果是在vue环境下,要怎么删除?
可利用v-if
4.浏览器的缓存是怎么实现的?
当Web缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。
http缓存策略(强制缓存+协商缓存) ☆
①强制缓存
缓存有效
缓存过期(还是会经过服务器)
Cache-Control
- Response Headers中,控制强制缓存的逻辑
- 例如Cache-Control: max-age=31536000(单位是秒) 在客户端缓存的时间
- 值
max-age=xxx
:缓存的内容将在 xxx 秒后失效
no-cache
:跳过设置强缓存,但是不妨碍设置协商缓存
no-store:不缓存,这个会让客户端、服务器都不缓存,也就没有强缓存、协商缓存了
private: 只让客户端可以缓存该资源;代理服务器不缓存
public:客户端和代理服务器都可以缓存该资源
关于Expires
- 同在Response Headers中,同为控制缓存过期
- 已被Cache-Control代替
②协商缓存(对比缓存)
- 是服务器端缓存策略
服务端来判断资源是不是可以被缓存,不是指资源缓存在服务端 - 服务器判断客户端资源,是否和服务端资源一样
- 一致则返回304,否则返回200和最新的资源
资源标识
-
在Response Headers中,有两种
-
Last-Modified 资源的最后修改时间
-
Etag 资源的唯一标识(一个字符串,类似人类的指纹)
-
Last-Modified 和 Etag
可以共存,会优先使用Etag
Last-Modified 只能精确到秒级
如果资源被重复生成,而内容不变,则Etag更精确
完整流程图(要求能默画)
缓存是存在客户端,不是服务端!
5.描述事件循环机制
①JS是单线程运行的,异步要基于回调来实现,event loop就是异步回调的实现原理
②JS如何执行
- 同步代码,一行一行放在Call Stack 执行
- 遇到异步,会先“记录”下,等待时机(定时、网络请求等)
- 时机到了,就移动到Callback Queue
- 如Call Stack为空(即同步代码执行完)Event Loop开始工作
- 轮询查找Callback Queue ,如有则移动到Call Stack 执行
- 然后继续轮询查找(永动机一样)
③event loop过程
由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( event loop)。
6.微任务和宏任务分别是哪些,有什么区别?
- 宏任务: setTimeout , setInterval , Ajax ,DOM事件
- 微任务:Promise async/await
- 微任务执行时机比宏任务要早
- 微任务是ES6语法规定的,宏任务是由浏览器规定的
7.值类型和引用类型的区别
8.怎么实现触发同一元素同一事件,执行多个方法
使用addEventListener方法,可以为同一个元素 同一个事件注册多个处理函数
(function () {
window.onload = function() {
var openBtn = document.getElementById("open");
var closeBtn = document.getElementById("close");
var open = function() {
document.body.className = "on";
};
var close = function() {
document.body.className = "off";
};
//第三个参数设置成false,表示允许事件冒泡
openBtn.addEventListener("click", open, false);
openBtn.addEventListener("click", function() { alert('hello'); }, false);
};
}());
9.怎么实现网页的前进、后退
参考自实现一个前端路由,如何实现浏览器的前进与后退?
利用栈的 后进者先出,先进者后出 原理
用两个栈实现浏览器的前进、后退功能
我们使用两个栈,X 和 Y,我们把首次浏览的页面依次压入栈 X,当点击后退按钮时,再依次从栈 X 中出栈,并将出栈的数据依次放入栈 Y。当我们点击前进按钮时,我们依次从栈 Y 中取出数据,放入栈 X 中。当栈 X 中没有数据时,那就说明没有页面可以继续后退浏览了。当栈 Y 中没有数据,那就说明没有页面可以点击前进按钮浏览了。
比如你顺序查看了 a,b,c 三个页面,我们就依次把 a,b,c 压入栈,这个时候,两个栈的数据如下:
当你通过浏览器的后退按钮,从页面 c 后退到页面 a 之后,我们就依次把 c 和 b 从栈 X 中弹出,并且依次放入到栈 Y。这个时候,两个栈的数据就是这个样子:
这个时候你又想看页面 b,于是你又点击前进按钮回到 b 页面,我们就把 b 再从栈 Y 中出栈,放入栈 X 中。此时两个栈的数据是这个样子:
这个时候,你通过页面 b 又跳转到新的页面 d 了,页面 c 就无法再通过前进、后退按钮重复查看了,所以需要清空栈 Y。此时两个栈的数据这个样子:
Vue
1.怎么实现组件间的通讯?
父传子
通过props传递
父组件: <child value = ‘传递的数据’ />
子组件: props[‘value’],接收数据,接受之后使用和data中定义数据使用方式一样
子传父
在父组件中给子组件绑定一个自定义的事件,子组件通过$emit()触发该事件并传值。
父组件: <child @receive = ‘receive’ />
子组件: this.$emit(‘receive’,‘传递的数据’)
兄弟组件传值
通过中央通信 let bus = new Vue()
A:methods :{ 函数{bus.$emit(‘自定义事件名’,数据)} 发送
B:created (){bus.$on(‘A发送过来的自定义事件名’,函数)} 进行数据接收
通过vuex
2.登录功能的实现
-
登录业务流程
① 在登录页面输入用户名和密码
② 调用后台接口进行验证
③ 通过验证之后,根据后台的响应状态跳转到项目主页 -
记录用户的登录状态
通过 cookie在客户端记录状态
通过 session 在服务器端记录状态
通过token方式维持状态
在跨域的情况下,推荐使用token方式。 -
token原理分析
JWT认证
:服务器不保存 session 数据,所有数据都保存在客户端,每次请求都发回服务器。
3.怎么控制页面访问权限(没登录的用户无法访问相关页面)
用路由导航守卫(beforeEach)
也就是如果用户没有登录,但是直接通过URL
访问特定页面,需要重新跳转到登录页面,进行登录。登录以后才能访问。
// 为路由对象,添加`beforeEach`导航守卫
router.beforeEach((to,from,next)=>{
//如果用户访问的是登录页,直接放行
if(to.path==='/login') return next()
const tokenStr=window.sessionStorage.getItem('token')
// 没有token,强制跳转到登录页
if(!tokenStr) return next('/login')
next()
})
4.怎么实现不同权限的用户,显示不同的界面
可参考2Vue动态菜单(路由)的实现方案(beforeEach+addRoutes+elementUI)
方法一:后端动态返回
用户登录成功之后,可以查询到用户的角色,再根据用户角色去查询出来用户可以操作的菜单(资源),然后把这些可以操作的资源,组织成一个 JSON 数据,返回给前端,前端再根据这个 JSON 渲染出相应的菜单。
方法二:前端动态渲染
直接在前端把所有页面都在路由表里边定义好,然后在 meta 属性中定义每一个页面需要哪些角色才能访问
开放题
如果要做一个下五子棋的游戏,会从哪方面入手(各个方向都可以,不局限于技术,产品定位、拥有的功能、应用端…)
二面(主要为人事面)
1.冒泡排序的时间复杂度
O(n²)
2.tcp和udp的区别
TCP是面向连接的可靠的传输层协议。
UDP是无连接的不可靠的传输层协议。
TCP的优点:
- 可靠,稳定。
- TCP的可靠体现在TCP在传输数据之前会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。
TCP的缺点:
- 慢,效率低,占用资源高,易被攻击;TCP在传递数据之前要先建立连接,这会消耗时间,而且在数据传递时,确认机制,重传机制,拥塞控制机制等都会消耗大量的实践,而且要在每台设备上维护所有的传输连接。事实上每个连接都会占用系统的CPU、内存等硬件资源。
- 因为TCP有确认机制、三次握手机制,这些优点在成了缺陷,导致TCP容易被人利用,实现DOS、DDOS、CC、猜测攻击等。
UDP的优点:
- 快,比TCP稍安全。
- UDP没有TCP的握手、确认、窗口、重传、拥塞控制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。
- 没有TCP的这些机制(如:三次握手),攻击者利用UDP的漏洞就要少一些。但是UDP也是无法避免攻击的,比如:UDPFlood等。
UDP的缺点:
- 不可靠,不稳定。
- 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。