小米前端实习电话面试题目整理
-
- 自我介绍
- 说一下css的优先级
- 盒子水平居中和垂直居中
-
- 1. 定位
- 2. CSS3
- 3.flex
- 4.display: table-cell
- 说一下防抖和节流
- JS的事件循环机制
- 页面的重排和重绘
- 跨域
- 浏览器的缓存策略
-
-
- 强缓存
- 协商缓存
-
- 浏览器的渲染过程
- 说一下ES6
- Promise
- git的基本用法
- URL从输入到页面展示的过程
- vue的生命周期
- v-if和v-show的区别
- key的作用是什么
- 说一下package.json配置文件中的配置
自学前端的菜鸟一个,这次面其实是属于比较基础的,自我感觉已经废了,问题都只答出了一半说的一知半解,第一次面试还是太紧张了。下次一定要准备的充分一点。
自我介绍
说一下css的优先级
css优先级规则:
1.css选择规则的权值不同时,权值高的优先;
2.css选择规则的权值相同时,后定义的规则优先;
3. css属性后面加 !important 时,无条件绝对优先;
权值等级划分:
-
第一等级:内联样式,如 style="",权值为 1,0,0,0;
-
第二等级: ID选择器,如 #id="", 权值为 0,1,0,0;
-
第三等级:calss | 伪类 | 属性 选择器,如 .class | :hover,:link,:target | [type],
权值 0,0,1,0; -
第四等级:标签 | 伪元素 选择器,如 p | ::after, ::before, ::first-inline, ::selection, 权值 0,0,0,1;
此外,通用选择器(*),子选择器(>), 相邻同胞选择器(+)等选择器不在4等级之内,所以它们的权值都为 0,0,0,0;
总结:
1.先从高等级进行比较,高等级相同时,再比较低等级的,以此类推;
2.完全相同的话,就采用 后者优先原则(也就是样式覆盖);
3.css属性后面加 !important 时,无条件绝对优先(比内联样式还要优先);
盒子水平居中和垂直居中
1. 定位
宽高已知
position:absolute;
top:50%;
left:50%;
margin-left:-w/2;
margin-top:-h/2
盒子要设置宽高
div{position: absolute;margin: auto;width: 100px;height: 100px;top:0;left: 0;bottom: 0;right: 0;}
2. CSS3
top left 50%, transform: translate(-50%, -50%);
3.flex
设置display flex , justify-content center, align-item center
4.display: table-cell
父级 固定宽高 display: table-cell vertical-align: middle, text-align: center , 子级 display: inline-block
说一下防抖和节流
函数防抖:就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。简单的说,当一个动作连续触发,则只执行最后一次。
应用场景:
搜索框搜索输入。只需用户最后一次输入完,再发送请求
手机号、邮箱验证输入检测
窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
简单实现:
函数防抖在执行目标方法时,会等待一段时间。当又执行相同方法时,若前一个定时任务未执行完,则 clear 掉定时任务,重新定时。
function debounce(delay, callback) {// 闭包会保存变量let timer=nullreturn function(){clearTimeout(timer)timer=setTimeout(function(){callback()},delay)}}
函数节流:限制一个函数在一定时间内只能执行一次。
应用场景:
滚动加载,加载更多或滚到底部监听
高频点击提交,表单重复提交
简单实现:
函数节流的目的,是为了限制函数一段时间内只能执行一次。因此,通过使用定时任务,延时方法执行。在延时的时间内,方法若被触发,则直接退出方法。从而,实现函数一段时间内只执行一次。
function throttle(delay, callback) {let timer = nullreturn function () {// 如果定时器不存在就执行回调函数if (!timer) {timer = setTimeout(function () {callback()// 当本次事件结束后,将定时器清空来进行下一次事件timer = null}, delay)}}}
JS的事件循环机制
转载
页面的重排和重绘
重排:当涉及到DOM节点的布局属性发生变化时,就会重新计算该属性,浏览器会重新描绘相应的元素,此过程也叫 回流(Reflow)。
实际上是根据Render tree中每个渲染对象的信息,计算出各自渲染对象的几何信息(DOM对象的位置和尺寸大小),并将其安置在界面中的正确位置
浏览器渲染界面是基于流式布局模型的,也就是某一个DOM节点信息更改了,就需要对DOM结构进行重新计算,重新布局界面,再次引发重排;只是这个结构更改程度会决定周边DOM更改范围,即全局范围和局部范围。全局范围就是从根节点html开始对整个渲染树进行重新布局,例如当我们改变了窗口尺寸或方向或者是修改了根元素的尺寸或者字体大小等;而局部范围可以是对渲染树的某部分或某一个渲染对象进行重新布局。
重排是一个递归的过程。它从根(对应于 HTML 文档的 元素)开始,然后递归遍历部分或所有的框架层次结构,为每一个需要计算的呈现器计算几何信息
(HTML 采用基于流的布局模型,这意味着大多数情况下只要一次遍历就能计算出几何信息。处于流中靠后位置元素通常不会影响靠前位置元素的几何特征,因此布局可以按从左至右、从上至下的顺序遍历文档。但是也有例外情况,比如 HTML 表格的计算就需要不止一次的遍历。)
引起重排的操作:
页面首次渲染。
浏览器窗口大小发生改变。
元素尺寸或位置发生改变。
元素内容变化(文字数量或图片大小等等)。
元素字体大小变化。
添加或者删除可见的DOM元素。
激活CSS伪类(例如::hover)。
设置style属性
查询某些属性或调用某些方法。
常见引起重排属性和方法 | |||
---|---|---|---|
width | height | margin | padding |
display | border | position | overflow |
clientWidth | clientHeight | clientTop | clientLeft |
offsetWidth | offsetHeight | offsetTop | offsetLeft |
scrollWidth | scrollHeight | scrollTop | scrollLeft |
scrollIntoView() | scrollTo() | getComputedStyle() | |
getBoundingClientRect() | scrollIntoViewIfNeeded() |
减少重排:
- 避免设置大量的style属性,因为通过设置style属性改变结点样式的话,每一次设置都会触发一次reflow,所以最好是使用class属性
- 实现元素的动画,它的position属性,最好是设为absoulte或fixed,这样不会影响其他元素的布局,还可以让动画处于更高的图层(即:z-index的值更大)这也是从图层的角度进行优化的。
- 动画实现的速度的选择。比如实现一个动画,以1个像素为单位移动这样最平滑,但是reflow就会过于频繁,大量消耗CPU资源,如果以3个像素为单位移动则会好很多。
- 不要使用table布局,因为table中某个元素旦触发了reflow,那么整个table的元素都会触发reflow。那么在不得已使用table的场合,可以设置table-layout:auto;或者是table-layout:fixed这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围
重绘:当影响DOM元素可见性的属性发生变化 (如 color) 时, 浏览器会重新描绘相应的元素, 此过程称为 重绘(Repaint)。因此重排必然会引起重绘。
引起重绘的属性 | |||
---|---|---|---|
color | border-style | visibility | background |
text-decoration | background-image | background-position | background-repeat |
outline-color | outline | outline-style | border-radius |
outline-width | box-shadow | background-size |
跨域
跨域
浏览器的缓存策略
浏览器缓存其实就是浏览器保存通过HTTP获取的所有资源,是浏览器将网络资源存储在本地的一种行为。浏览器的缓存机制是根据HTTP报文的缓存标识进行的。
通常浏览器缓存策略分为两种:强缓存(Expires,cache-control)和协商缓存(Last-modified ,Etag),并且缓存策略都是通过设置 HTTP Header 来实现的
强缓存
强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。
相关字段:
Expires
response header里的过期时间,浏览器再次加载资源时,如果在这个过期时间内,则命中强制缓存。
Cache-Control
当值设为max-age=300时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。
Expires和Cache-Control的区别
Expires 是http1.0的产物,Cache-Control是http1.1的产物,两者同时存在的话,Cache-Control优先级高于Expires;在某些不支持HTTP1.1的环境下,Expires就会发挥用处。所以Expires其实是过时的产物,现阶段它的存在只是一种兼容性的写法
Expires是一个具体的服务器时间,这就导致一个问题,如果客户端时间和服务器时间相差较大,缓存命中与否就不是开发者所期望的。Cache-Control是一个时间段,控制就比较容易
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
ETag和If-None-Match
Etag是上一次加载资源时,服务器返回的response header,是对该资源的一种唯一标识,只要资源有变化,Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器接受到If-None-Match的值后,会拿来跟该资源文件的Etag值做比较,如果相同,则表示资源文件没有发生改变,命中协商缓存。
Last-Modified和If-Modified-Since
Last-Modified是该资源文件最后一次更改时间,服务器会在response header里返回,同时浏览器会将这个值保存起来,在下一次发送请求时,放到request header里的If-Modified-Since里,服务器在接收到后也会做比对,如果相同则命中协商缓存。
ETag和Last-Modified区别
在方式上,Etag是对资源的一种唯一标识,而Last-Modified是该资源文件最后一次更改时间
在精确度上,Etag要优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。
在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
在优先级上,服务器校验优先考虑Etag。
浏览器缓存看这个
浏览器的渲染过程
- 解析HTML文档,构建DOM树
- 解析CSS属性,构建CSSOM树
- 结合DOM树和CSSOM树,构建render树
- 在render树的基础上进行布局, 计算每个节点的几何结构
- 把每个节点绘制在屏幕上
Render tree是由 DOM 和 CSSOM 组合构建而成的。也是页面可视化元素按照其显示顺序而组成的树。它的作用是让浏览器按照正确的顺序绘制内容。非可视化的 DOM 元素并不会全部插入Render tree中,像header元素和设置了display:none的元素 就不在渲染树中(但是 设置了visibility :hidden 的元素仍会显示在其中)。
每一次的dom更改或者css几何属性更改,都会引起一次浏览器的重排/重绘过程,而如果是css的非几何属性更改,则只会引起重绘过程。所以说重排一定会引起重绘,而重绘不一定会引起重排。
因为有时JS也参与DOM Tree的构建,因而会先执行js再开始构建渲染树。所以说:JS脚本会阻塞Render tree的构建,即阻塞了页面的渲染。可以在把script脚本放于body后面,来解决上面的问题。
说一下ES6
可以看这篇文章
Promise
理解promise可以看这个
git的基本用法
Git 的工作就是创建和保存你项目的快照及与之后的快照进行对比
命令 | 说明 |
---|---|
git init |
初始化仓库 |
git clone |
拷贝一份远程仓库,也就是下载一个项目。 |
git add |
添加文件到仓库 |
git status |
查看仓库当前的状态,显示有变更的文件。 |
git diff |
比较文件的不同,即暂存区和工作区的差异。 |
git commit |
提交暂存区到本地仓库。 |
git reset |
回退版本。 |
git rm |
删除工作区文件。 |
git mv |
移动或重命名工作区文件。 |
git remote |
远程仓库操作 |
git fetch |
从远程获取代码库 |
git pull |
下载远程代码并合并 |
git push |
上传远程代码并合并 |
git分支管理、
git branch <name> //创建分支
git checkout -b <branch name> //创建一个新分支并切换到新分支
git checkout <name>//切换分支
git branch -r //查看远程分支
git branch -a //查看本地和远程的所有分支git branch -d <name> //删除分支,会提示未合并的内容
git branch -D <name> //删除分支,无提示强制删除
git push origin :<name> //删除远程分支//先切换到要合并的分支,再进行分支的合并
git merge <branch name> //合并此分支到当前分支
URL从输入到页面展示的过程
- 用户在浏览器的地址栏输入访问的URL地址。浏览器会先根据这个URL查看浏览器缓存-系统缓存-路由器缓存,若缓存中有,直接跳到第6步操作,若没有,则按照下面的步骤进行操作。
- 浏览器根据输入的URL地址解析出主机名。
- 浏览器将主机名转换成服务器ip地址。浏览器先查找本地DNS缓存列表,看缓存里面是否存在这个ip,如果有则进入第4步,如果缓存中不存在这个ip地址,就再向浏览器默认的DNS服务器发送查询请求,同时缓存当前这个ip到DNS缓存列表中。更详细步骤参考DNS查找域名的过程。
- 拿到ip地址后,浏览器再从URL中解析出端口号。
- 拿到ip和端口后,浏览器会建立一条与目标Web服务器的TCP连接,也就是传说中的三次握手。
- 浏览器向服务器发送一条HTTP请求报文。
- 服务器向浏览器返回一条HTTP响应报文。
- 关闭连接 浏览器解析文档。
- 如果文档中有资源则重复6、7、8动作,直至资源全部加载完毕。
vue的生命周期
Vue 的生命周期总共分为8个阶段:创建前/后,载入前/后,更新前/后,销毁前/后。
1、beforeCreate(创建前)
表示实例完全被创建出来之前,vue 实例的挂载元素$el和数据对象 data 都为 undefined,还未初始化。
2、created(创建后)
数据对象 data 已存在,可以调用 methods 中的方法,操作 data 中的数据,但 dom 未生成,$el 未存在 。
3、beforeMount(挂载前)
vue 实例的 $el 和 data 都已初始化,挂载之前为虚拟的 dom节点,模板已经在内存中编辑完成了,但是尚未把模板渲染到页面中。data.message 未替换。
4、mounted(挂载后)
vue 实例挂载完成,data.message 成功渲染。内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了。实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,DOM 渲染在 mounted 中就已经完成了。
5、beforeUpdate(更新前)
当 data 变化时,会触发beforeUpdate方法 。data 数据尚未和最新的数据保持同步。
6、updated(更新后)
当 data 变化时,会触发 updated 方法。页面和 data 数据已经保持同步了。
7、beforeDestory(销毁前)
组件销毁之前调用 ,在这一步,实例仍然完全可用。
8、destoryed(销毁后)
组件销毁之后调用,对 data 的改变不会再触发周期函数,vue 实例已解除事件监听和 dom绑定,但 dom 结构依然存在。
v-if和v-show的区别
1.手段:v-if是通过控制dom节点的存在与否来控制元素的显隐;v-show是通过设置DOM元素的display样式,block为显示,none为隐藏;
2.编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;
3.编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译(编译被缓存?编译被缓存后,然后再切换的时候进行局部卸载); v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素保留;
4.性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;
key的作用是什么
看这个
说一下package.json配置文件中的配置
讲解看这个
本篇文章内的答案参考了许多网上的回答和博客,在此就不一 一列出了。