写在前面:大前端日益更新、对开发者的要求也越来越高。下面我先列出我能想到的面试题大纲,然后一一解答,给自己做个笔记。
一、基础
1). css部分
- 移动端常用适配方式
px+%
rem
vw
- css 垂直水平居中
已知宽高:
background: red;
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
margin: -50px 0 0 -50px;
已知宽高:
background: red;
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
margin: auto;
不知宽高 用定位+transform
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
flex 布局:
display: flex;
align-items: center;
justify-content: center;
等等..
- rem、em 原理区别
rem 根据根元素html的1font-size字体大小进行适配
em 根据自身的1font-size字体大小进行适配
- 盒模型
box-sizing:content-box 标准盒模型(w3c标准合模型 width:content)
box-sizing:border-box IE盒模型(IE盒模型 width: content + padding + border)
- 清除浮动的几种方式
1.给父元素设置高度
2.伪类
.clearfix:after{
content:"";//设置内容为空
height:0;//高度为0
line-height:0;//行高为0
display:block;//将文本转为块级元素
visibility:hidden;//将元素隐藏
clear:both//清除浮动
}
.clearfix{
zoom:1;为了兼容IE
}
双伪元素清除浮动:
.clearfix:before,.clearfix:after {
content: "";
display: block;
clear: both;
}
.clearfix {
zoom: 1;
}
3.给父盒子设置浮动
4.overflow:hidden;
- css画出一个三角形
宽高都设为0 用border 实现效果
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
- 内联、import 、support 权重优先级
import>内联>Support
import > 内联 > #id > .class(伪类class同级) > 标签
- BFC
- Block Formatting Contexts (块级格式化上下文) 。具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。
- 只要元素满足下面任一条件即可触发 BFC 特性:
body 根元素
浮动元素:float 除 none 以外的值
绝对定位元素:position (absolute、fixed)
overflow 除了 visible 以外的值 (hidden、auto、scroll)的值为 table-cell, table-caption, inline-block, flex, 或者 inline-flex中的其中一个
display:flex/table-cell
3. 同一个 BFC 下外边距会发生折叠
4.BFC 可以包含浮动的元素(清除浮动)
2). html 部分
- h5 新标签
header,footer,main,nav,section 等等.
- 浏览器内核
- IE浏览器内核:Trident内核,也是俗称的IE内核;
- Chrome浏览器内核:统称为Chromium内核或Chrome内核,以前是Webkit内核,现在是Blink内核;
- Firefox浏览器内核:Gecko内核,俗称Firefox内核;
- Safari浏览器内核:Webkit内核;
- Opera浏览器内核:最初是自己的Presto内核,后来是Webkit,现在是Blink内核;
- 360浏览器、猎豹浏览器内核:IE+Chrome双内核;
- 搜狗、遨游、QQ浏览器内核:Trident(兼容模式)+Webkit(高速模式);
- 百度浏览器、世界之窗内核:IE内核;
- 2345浏览器内核:以前是IE内核,现在也是IE+Chrome双内核;
- 浏览器兼容
- css里增加通配符*{margin:0;padding:0}
- 使用float为img布局 解决图片默认间距. 等等
由于浏览器兼容问题比较开放性 面试的时候 可以跟面试官扯一些你在项目中遇到的兼容方式.如果没有经验 可专门百度.
此处放一个参考链接 https://www.jianshu.com/p/6afd596440bb
- dom 渲染
浏览器解析html源码,然后创建一个DOM树。
浏览器解析CSS代码,计算出最终的样式数据。
创建完DOM树并得到最终的样式数据之后,构建一个渲染树。
当渲染树创建完成之后,浏览器就可以根据渲染树直接把页面绘制到屏幕上。
这个可以根据自己的理解解答 不用死记硬背.
3). js
- get和post 区别和相同点。以及还有哪些别的请求方式?
相同点:
都是http 请求方式。都属于TCP连接。
区别:
get 在浏览器是回退时是无害的,而post会再次提交请求。
get 请求会被浏览器主动cache(缓存),而post不会除非手动设置。
get请求只能进行url 编码,post支持多种编码方式。
get请求参数会被完整保留在浏览器历史记录里,post 不会保留
get 请求在url 传送参数有长度限制 ,post 没有
get 请求通过url 传参, post 参数放在request body 中
get 请求因为参数放在url 上的原因 相比较post而言 不安全
get 请求产生有一个TCP数据包 ,post 会产生两个TCP数据包
- 数据类型
ES5六种:
Number、String、Boolean、undefined、object、Null。
其中object为引用类型(Data、function、Array等)。
其余五种为基本类型。
ES6 中新增了一种 Symbol 。
- JavaScript中的作用域与变量声明提升
所有的变量声明都会被提升到作用域的最顶端
同一个变量声明只进行一次 其他声明会被重置掉
函数声明的优先级高于变量声明 且函数声明会连带定义一起提升
这个面试题一般会直接以题的形式考察你的掌握度,看先打印出哪一个值。具体还需自己多理解掌握。
- 数组的方法(不止增删改查)
控制台打印输出一个数组里 _proto_ 里包含的都是数组可以点出来的操作方法。多说几个不常用的会更加分。
- 浏览器渲染
自上而下加载。遇见css和图片异步加载。js代码会先解析js加载完之后再继续渲染(这也是为什么script标签往往会放在body后面的原因)。
1.当用户输入一个url 之后,浏览器会去向服务器发起请求请求url 对应的资源;
2.接收到服务器响应内容之后,浏览器的html 解析器会将HTML文件解析成一个DOM树。 将CSS解析成一个CSS 树;
3.根据DOM树和CSS树来构建 Render Tree(渲染树)。根据渲染树的对应关系 在客户端呈现内容画面。
- 面向对象、闭包、原型、原型链
1. 面向对象的基本特征:封装、继承、多态。把客观的事物封装成抽象的类,或者构造函数。
2. 闭包:能够访问另一个函数作用域变量的函数。顾名思义:函数中的函数。缺点:内存泄漏,this指向问题,引用的变量可能会发生变化。
优点:可以解决递归调用,模仿块级作用域。
3. 原型:每个构造函数都有prototype 属性指向另一个对象。这个对象的所有属性和方法都会被构造函数的实例继承。
我们可以把不变的属性和方法定义在prototype对象上。prototype默认有两个属性,constructor属性和__proto__属性,
_proto_是原型链指向实例化的函数原型,总是指向prototype。hasOwnProperty()来查看是否是自身属性 还是继承属性。
- 事件机制、(冒泡,捕获)
冒泡:事件冒泡是 IE 团队提出的事件流方案,根据名字我们就可以看出,事件冒泡是从最具体的元素开始触发事件,然后向上传播至没有那么具体的元素(文档)。简而言之:由内而外的触发机制。
捕获:事件捕获是 Netscpe 开发团队提出的事件流解决方案。和事件冒泡相反,事件捕获是从最不具体的节点最先接收事件,向下传播至最具体的节点。事件捕获实际上是为了在事件到达最终目标前拦截事件。简而言之:由外而内的触发机制。
preventDefault()
方法用于阻止特点事件的默认行为(比如,a 标签有跳转到 href 链接的默认行为,可以阻止这种导航行为)。
stopPropagation()
方法用于立即阻止事件流在 DOM 结构中的传播,取消后续的事件捕获或冒泡。
- 跨域及解决方式
为什么会跨域?出于浏览器的同源策略限制,浏览器会拒绝跨域请求。
什么叫跨域?非同源请求,均为跨域。名词解释:同源 —— 如果两个页面拥有相同的协议(protocol),端口(port)和主机(host),那么这两个页面就属于同一个源(origin)。
怎么解决跨域?最常用的三种方式:JSONP、CORS、postMessage、webpack proxy(代理配置 仅限于开发环境)、nginx(反向代理)、webpack plugin。
【JSONP的优缺点】
优点:兼容性好(兼容低版本IE)
缺点:1.JSONP只支持GET请求,需要后端支持; 2.XMLHttpRequest相对于JSONP有着更好的错误处理机制
CORS :是W3C 推荐的一种新的官方方案,能使服务器支持 XMLHttpRequest 的跨域请求。CORS 实现起来非常方便,只需要增加一些 HTTP 头,让服务器能声明允许的访问来源。
postMessage: window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。
- Ajax 原理
简言之:异步请求数据。原理结合原生ajax 请求步骤 (即下面代码的大致步骤)更加分。
实现流程:
- 创建一个
XMLHttpRequest
对象 - 创建一个新的
HTTP
请求,并指定该请求的方法、URL
以及是否为异步请求 - 设置响应
HTTP
请求状态变化的函数 - 发送
HTTP
请求 - 对异步返回的数据进行处理
// 创建 XMLHttpRequest 对象
var xhr
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest()
} else if (window.ActiveXObject) {
xhr = new ActiveXObject('Microsoft.XMLHTTP')
}
// 创建一个新的请求
xhr.open('GET', 'http://www.example.com', true)
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 监听 HTTP 请求状态变化
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var res = xhr.responseText
}
}
// 发送 HTTP 请求
xhr.send()
优点:
页面无刷新,用户体验好
使用异步的方式与服务器通信,响应更加迅速
减轻服务器的压力,节约带宽
基于标准化并被广泛支持的技术
缺点:
破坏了浏览器的回退机制
暴露了更多的数据和服务器逻辑
对搜索引擎的支持比较弱
违背了 URL 与资源定位的初衷
- 缓存(session、cookie、localstorage)特点,区别
cookie 特点:
1.不同的浏览器存放的cookie位置不一样,也是不能通用的。
2.cookie的存储是以域名形式进行区分的,不同的域下存储的cookie是独立的。
3.我们可以设置cookie生效的域(当前设置cookie所在域的子域),也就是说,我们能够操作的cookie是当前域以及当前域下的所有子域
4.一个域名下存放的cookie的个数是有限制的,不同的浏览器存放的个数不一样,一般为20个。
5.每个cookie存放的内容大小也是有限制的,不同的浏览器存放大小不一样,一般为4KB。
6.cookie也可以设置过期的时间,默认是会话结束的时候,当时间到期自动销毁
localStorage(本地存储):
1.生命周期:持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。
2.存储的信息在同一域中是共享的。
3.当本页操作(新增、修改、删除)了localStorage的时候,本页面不会触发storage事件,但是别的页面会触发storage事件。
4.大小:据说是5M(跟浏览器厂商有关系)
5.在非IE下的浏览中可以本地打开。IE浏览器要在服务器中打开。
6.localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡
7.localStorage受同源策略的限制
sessionStorage(本地会话存储):
用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。也就是说只要这个浏览器窗口没有关闭,即使刷新页面或进入同源另一页面,数据仍然存在。关闭窗口后,sessionStorage即被销毁,或者在新窗口打开同源的另一个页面,sessionStorage也是没有的。
cookie、localStorage、sessionStorage区别
相同:在本地(浏览器端)存储数据
不同:
localStorage、sessionStorage
localStorage只要在相同的协议、相同的主机名、相同的端口下,就能读取/修改到同一份localStorage数据。
sessionStorage比localStorage更严苛一点,除了协议、主机名、端口外,还要求在同一窗口(也就是浏览器的标签页)下。
localStorage是永久存储,除非手动删除。
sessionStorage当会话结束(当前页面关闭的时候,自动销毁)
cookie的数据会在每一次发送http请求的时候,同时发送给服务器而localStorage、sessionStorage不会。
- jQuery 选择器
id选择器: $( "#id" )
类名选择器: $( ".class" )
标签选择器: $( "div" )
- HTTP 状态码及含义
200 OK ,表明请求已经成功. 默认情况下状态码为200的响应可以被缓存。
302 Found,临时重定向。重定向状态码表明请求的资源被暂时的移动到了由 Location 头部指定的 URL 上。浏览器会重定向到这个URL,但是搜索引擎不会对该资源的链接进行更新。
400 Bad Request,表示由于语法无效,服务器无法理解该请求。客户端不应该在未经修改的情况下重复此请求。
403 Forbidden,指的是服务器端有能力处理该请求,但是拒绝授权访问。进入该状态后,不能再继续进行验证。该访问是永久禁止的,并且与应用逻辑密切相关(例如不正确的密码)
404 Not Found,说明服务器端无法找到所请求的资源。404 不能说明请求的资源是临时还是永久丢失。如果服务器知道该资源是永久丢失,那么应该返回 410 (Gone) 而不是 404 。
500 Internal Server Error,表示所请求的服务器遇到意外的情况并阻止其执行请求。
502 Bad Gateway,表示作为网关或代理角色的服务器,从上游服务器(如tomcat、php-fpm)中接收到的响应是无效的。服务器挂掉了的意思。
503 Serveice Unavailable,表示服务器尚未处于可以接受请求的状态。
- 异步加载和延迟加载
异步async:
async
HTML5里为script
标签里新增了async属性,用于异步加载脚本: 不保证顺序(独立的个体)
<script async src="script.js"></script>
/*或*/
<script type="text/javascript" src="alert.js" async="async"></script>
浏览器解析到HTML里的该行script标签,发现指定为async
,会异步下载解析执行脚本(即加载后续文档元素的过程将和script.js的加载并行进行)。
页面的DOM结构里假设<script>
在img之前,如果你的浏览器支持async
的话,就会异步加载脚本。此时DOM里已经有img了,所以脚本里能顺利取到img的src并弹框。
延迟defer:
defer
<script>
标签里可以设置defer
,表示延迟加载脚本:脚本先不执行,延迟到文档解析和显示后执行,有顺序。
<script defer src="script.js"></script>
/*或*/
<script type="text/javascript" src="alert.js" defer="defer"></script>
浏览器解析到HTML里该行<script>
标签,发现指定为defer
,会暂缓下载解析执行脚本,等到页面文档解析并加载执行完毕后,才会加载该脚本(更精确地说,是在DOM树构建完成后,在DOMContentLoaded
事件触发前,加载defer
的脚本)。
页面的DOM结构里假设script在img图片之前,如果你的浏览器支持defer的话,就会延迟到页面加载完后才下载脚本。此时DOM里已经有img元素了,所以脚本里能顺利取到img的src并弹框。
4). 优化
- 前端性能优化的方法
- 优雅降级和渐进增强
- 节流和防抖
二、进阶
1).vue
- 组件之间传值方式有哪些?
- 父组件向子组件传递数据 通过props
- 子组件像父组件传递事件$emit方法
- eventbus
- vuex
- 缓存机制
- 父子组件 互相调用 方法的方式有哪些?
父组件调用子组件的方法:this.$refs.子组件ref值.子组件event
子组件调用父组件方法:
this.$parent.event
this.$emit.event(与传值方式相同)
父组件把事件传到子组件props 中 子组件调用
- vue生命周期的理解 created和 mounted 之间的区别
创建:初始化事件、进行数据观测
beforeCreate
created(数据已经和data 绑定,改变data里的属性值、视图会发生变化。由于视图未出现,如果请求信息过多,页面会处于长时间白屏)
挂载:判断对象是否有el选项,如果有继续编译,如果没有 生命周期停止。直到vue实例调用vm.$mount(el).
beforeMount (模板编译完成 但未挂载 获取不了DOM)
mounted(组件挂载完成,能成功获取DOM,所有的子组件不一定会被挂载,可以等到整个视图都渲染完毕后 用vm.$nextTick)
更新:vue发现data 数据更新 会重新渲染
beforeUpdate
updated
销毁:常用于组件变更时的状态存储 和 内存释放
beforeDistory
distoryed(不会自动移除dom 节点,可以手动在生命周期里操作)
- vue组件中为什么data 是一个函数 而不是一个对象
因为JavaScript的特性所导致,在component中,data必须以函数的形式存在,不可以是对象。
组建中的data写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,它们只负责各自维护的数据,不会造成混乱。而单纯的写成对象形式,就是所有的组件实例共用了一个data,这样改一个全都改了。
- vue computed 和 watch 的区别 使用场景
computed:
- 有缓存机制、依赖项发生改变重新计算。
- 不支持异步,当computed 内部有异步操作时、无法监听数据变化
- 不需要在data里声明
- 一个属性受多个属性影响时使用
- 使用 场景:购物车结算
watch:
- 没有缓存机制,数据发生变化直接触发
- 支持异步操作
- 必须在data里声明
- 数据变化时执行异步或开销较大的操作(一条数据影响多条数据的时候)
- 使用场景:搜索、滚动锚点定位
- vuex action 和 mutation之间的区别
mutation 定义的方法动态修改Vuex 的 store 中的状态或数据。view 层通过 store.commit来分发,必须同步执行。
action可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action,不能直接操作state。
- v-show和v-if指令的共同点和不同点
都是隐藏不可见元素
v-show 不管条件是否为真 都会渲染 控制元素的display 属性 来控制显示隐藏 有更高的初始渲染开销
v-if 是根据条件来判断是否渲染 频繁的重建和销毁节点 会有更高的切换开销
- vue优点和缺点
优点:轻量级
数据驱动视图 组件化
高效、快速、模块友好
缺点:不利于seo
不支持低版本浏览器
第一次加载首页耗时过长
不能使用浏览器的导航 需要自行实现路由前进后退
- 说出几种vue当中的指令和它的用法
v-model 双向数据绑定
v-for 循环遍历 比v-if 优先级高
v-show、v-if 隐藏
v-once 只绑定一次
- vue-loader是什么?使用它的用途有哪些?
vue 文件加载器, 将style/template/js 转换成js模块。js可以写es6、style样式可以scss或less、template可以加jade等
- 为什么使用key?
需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点。
作用主要是为了高效的更新虚拟DOM。
- $nextTick的使用
当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,
你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功
- vue 双向数据绑定原理?
采用数据劫持和发布者-订阅者模式的方式,通过object.defineProperty劫持各个属性的getter、setter 方法,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
- vue路由实现,hash模式 和 history模式区别
hash: hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。仅hash符号之前的内容会被包含在请求中,因此对后端来说,即使没有做到对路由的全覆盖,也不会返回404错误
history: 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。前端发出的url请求必须和实际像后端发出的请求一致,否则会返回404错误
- keepalive
是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。
- $router 和 $route 区别
$router是VueRouter的实例对象,有push、replace等方法;
$route是路由信息对象、获取页面传递的参数,path、params、hash、query等路由信息参数;
- vue常用修饰符
.prevent 阻止事件默认行为 =event.preventDefault()
.stop 阻止事件冒泡 = event.stopPropagation()
.self 事件仅作用于元素本身,子组件不会触发
.capture 事件侦听,事件捕获
- params和query的区别
query要用path来引入,params要用name来引入,接收参数都是类似的,分别是this.$route.query.name和this.$route.params.name。
url地址显示:query更加类似于我们ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示
注意点:query刷新不会丢失query里面的数据,params刷新 会 丢失 params里面的数据。