1. 如何使一个盒子水平垂直居中?
-
定位
-
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -50p
-
-
利用 margin:auto
- 子绝父相结合
-
利用 transform
-
子绝父相结合
-
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
-
-
垂直居中一个img
-
display:table-cell;
text-align:center;
vertical-align:middle;
-
-
利用 display:table-cell
-
利用 display:flex;设置垂直水平都居中
2. 如何清除浮动
-
使用 CSS 中的 clear:both;
- 放一个空的 div,并设置上述 css,属性来清除元素的浮动
-
给父级元素设置双伪元素
-
给父级元素设置 overflow:hidden;或 overflow:auto;本质是构建一个 BFC
-
给父元素添加 clearfix 样式
3. src 和 href 的区别是?
-
src
- 指向外部资源的位置
- 指向的内容将会嵌入到文档中当前标签所在位置
-
href
- 指向网络资源所在位置
- 建立和当前元素(锚点)或当前文档(链接)之间的链接
4. 用css画一个三角形
.box {
/* 宽和高必须为0 */
width: 0;
height: 0;
border: 20px solid transparent;
border-top-color: thistle;
}
1、.box是自己命名的
2、四个边框都先设置px后(transparent)隐藏
3、在单独显示一个边的颜色
5. img 的 alt 与 title 有何异同? strong 与 em 的异同?
- alt(alt text):为不能显示图像用来指定替换文字。
- title(tool tip):该属性为设置该属性的元素提供建议性的信息。
- strong:粗体强调标签,强调,表示内容的重要性
- em:斜体强调标签,更强烈强调,表示内容的强调点
6. CSS 中 link 和@import 的区别是
- Link 属于 html 标签,而@import 是 CSS 中提供的(只能加载 CSS)
- 在页面加载的时候,link 会同时被加载,而@import 引用的 CSS 会在页面加载完成后才会加 载引用的 CSS
- @import 只有在 ie5 以上才可以被识别,而 link 是 html 标签,不存在浏览器兼容性问题
- Link 引入样式的权重大于@import 的引用(@import 是将引用的样式导入到当前的页面中)
7. BFC 是什么?
- BFC(块级格式化上下文),一个创建了新的 BFC 的盒子是独立布局的,盒子内元素的布局 不会影响盒子外面的元素。
- BFC 是指浏览器中创建了一个独立的渲染区域,该区域内所有元素的布局不会影响到区域外 元素的布局,这个渲染区域只对块级元素起作用
8. html 常见兼容性问题?
- 1.双边距 BUG float 引起的使用 display
- 超链接 hover 点击后失效使用正确的书写顺序 link visited hover active
- z-index 问题 给父级添加 position:relative
- IE6 不支持 PNG 透明背景,解决办法: IE6 下使用 gif 图片
9. 浏览器的内核分别是什么?经常遇到的浏览器的兼容性有哪些?原因,解决方法是什么,常用 hack 的技巧 ?
-
IE 浏览器的内核 Trident、Mozilla 的 Gecko、google 的 WebKit、Opera 内核 Presto;
-
png24 为的图片在 iE6 浏览器上出现背景,解决方案是做成 PNG8
-
浏 览 器 默 认 的 margin 和 padding 不 同 。 解 决 方 案 是 加 一 个 全 局 的
*{margin:0;padding:0;}来统一。
10. HTML5有哪些新特性?
- 绘画的 canvas 元素
- 用于媒介回放的 video 和 audio 元素
- 对本地离线存储的更好的支持
- 新的特殊内容元素,比如 article、footer、header、nav、section
- 新的表单控件,比如 calendar、date、time、email、url、search
11. css3有哪些新特性
12. css定位方式有哪几种?
-
relative(相对定位)
- 保留原位置
- 根据自身原来位置移动
-
absolute(绝对定位)
- 子绝父相
- 不保留原来位置
- 根据父级(有定位的父级)来移动(没有父级根据浏览器)
-
fixed(固定定位)
- 不保留原来位置
- 以浏览器为可视窗口移动(和父元素无关)
- 不随滚动条滚动而滚动
-
sticky(粘性定位)
- 以浏览器为可视窗口移动
- 占有原先位置
- 必须有一个属性(top等)
-
inherit定位
- 这种方式规定该元素继承父元素的position属性值。
13. 实现左中右布局的方案
float
- 所有盒子 float: left;
- 左右给固定宽度(150px)
- 中间宽度 width: calc(100% - 300px);
<style>
body {
margin: 0;
}
.container {
height: 100vh;
width: 100vw;
}
.item {
float: left;
height: 100%;
}
.item:nth-child(1),
.item:nth-child(3) {
width: 150px;
}
.item:nth-child(1) {
background: red;
}
.item:nth-child(2) {
/* CSS3:calc 计算属性(必须写空格) */
width: calc(100% - 300px);
background: green;
}
.item:nth-child(3) {
background: blue;
}
</style>
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
position
- 盒子全 position: absolute;
- 左 left:0 给宽度150
- 右 right:0 给宽度150
- 中间 left:150 right:150 不给宽度
<style>
body {
margin: 0;
}
.container {
height: 100vh;
width: 100vw;
position: relative;
}
.item {
position: absolute;
height: 100%;
}
.item:nth-child(1) {
left: 0;
width: 150px;
background: pink;
}
.item:nth-child(3) {
right: 0;
width: 150px;
background: yellow;
}
.item:nth-child(2) {
/* 左右定位 不给宽度 */
left: 150px;
right: 150px;
background: skyblue;
}
</style>
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
display: flex ( 弹性布局 )
- 左右 给宽度
- 中间 flex: 1;
<style>
body {
margin: 0;
}
.container {
height: 100vh;
width: 100vw;
display: flex;
}
.item {
height: 100%;
}
.item:nth-child(1) {
background: slategrey;
width: 150px;
}
.item:nth-child(3) {
background: rebeccapurple;
width: 150px;
}
.item:nth-child(2) {
background: gold;
/* 除了固宽之外 剩余的部分 我占一份 */
flex: 1;
}
</style>
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
js
1. call()和.apply()的含义和区别?
- 区别 : 传参不一样
call()
- 改变this指向
- call方法调用一个函数(其具有一个指定的 this 值和分别地提供的参数(参数的列表))
- 参数: 接受的是若干个参数的列表 call(this,1,2,3)
apply()
- 改变this指向
- 参数: 参数的数组 apply(this,[1,2,3])
- 可以调用函数
bind()
- 只改变this指向,不调用函数
- 传参 fn.bind(this)(1,2,3)
class
- class本质还是function
- 类的所有方法都定义在类的 prototype属性上
- 类创建的实例 里面也有 __ proto __ 指向类的 prototype 原型对象
- 所以 ES6 的类 他的绝大部分功能 es5 都可以做到 新的 calss 写法 只是让对象原型的写法 更加清晰 更像面向对象编程的语法而已
- 所以 ES6 的类 其实就是语法糖
循环 , 迭代 , 遍历 , 递归
- 循环 (loop) 指的是在满足条件的情况下 重复执行同一段代码 比如 while语句
- 迭代 (iterate) 指的是按照某种顺序逐个访问列表中的每一项 比如 for语句
- 遍历 (traversal) 指的是按照一定的规则访问树形结构中的每一个节点 而且每个节点 只访问一次
- 递归 (recursion) 指的是函数不断调用自身的行为
ES5新增方法:
-
数组方法forEach遍历数组(没有return,因为没有返回值)
-
数组方法filter过滤数组 (返回值 新数组)
-
数组方法some
- 查找数组中是否有满足条件的元素
- 返回值是布尔值,只要查找到满足条件的一个元素就立马终止循环
-
map
- 必须return 将返回值取出,组成一个新的数组
some和forEach区别
- 如果查询数组中唯一的元素, 用some方法更合适,在some 里面 遇到 return true 就是终止遍历 迭代效率更高
- 在forEach 里面 return 不会终止迭代
trim方法去除字符串两端的空格
获取对象的属性名
- Object.keys(对象) 获取到当前对象中的属性名 ,返回值是一个数组
2. js入口函数和jQuery入口函数的区别
-
js入口函数
- window.onload = function (){}
- 先执行jQuery再执行js的入口函数
- 但是js的入口函数会图片加载完成后执行,
-
jQuer入口函数
- $ (document).ready(function(){} 加立即执行函数
- js和jQuery的入口函数都是在页面加载完成后才执行
- 但是js的入口函数会图片加载完成后执行,
- 而jQuery的入口函数不需要图片加载完成后再执行
3. 常见的继承有哪些
- 原型链继承
- 借用构造函数继承
- 组合继承(组合原型链继承和借用构造函数继承)(常用)
- 原型式继承
- class类实现继承
- 寄生式继承
4. 原型链
构造函数 constructor
- 用来初始化对象 为对象成员变量赋初始值,与 new 一起使用 把公共的方法封装进来 用于创建某一类对象 首字母大写
new在执行时会做四件事
- 在内存中创建一个新的空对象
- 让this指向这个 新的空对象
- 执行构造函数里面的代码,给这个新对象添加属性和方法
- 返回这个新对象(所以构造函数里面不需要return)
实例成员
- 就是构造函数内部通过this 添加的成员
静态成员
- 就是在构造函数本身添加的成员
实例方法 只能通过实例对象来调用
静态方法 只能通过类名来调用
-
儿子在继承的时候,是可以继承父类的所有属性和方法(包括静态方法),静态方法一样需要使用类名调用
静态方法和实例方法区别:内部的this指向是不一样的
原型对象prototype
- 原型就是一个对象 prototype 为原型对象 原型的作用是共享方法 公共的属性定义到构造函数里面,公共的方法放在原型对象身上
- 构造函数原型对象 prototype 通过原型分配的函数是所有对象共享的,每一个构造函数都有 prototype属性 指向另一个对象
- prototype 就是一个对象,这个对象所有的属性和方法都会被构造函数所拥有 可以把不变的方法定义在 prototype 身上,这样对象实例就可以共享
对象原型__ proto __
- 对象都有 __ proto __ 属性 指向构造函数 prototype 原型对象 , 因为有 __ proto __ 对象原型的存在 才可以使用 构造函数 prototype原型对象的属性和方法
- 对象身上系统自己添加一个 __ proto __ 指向构造函数的原型对象
- 对象原型__ proto __ 和 原型对象prototype 都有 constructor 属性 称为构造函数,指回构造函数本身 主要用于记录该对象用于哪个构造函数 , 可以让原型对象重新指向原来的构造函数、
原型链
- 当访问一个对象的某个属性时,会先在这个对象本身属性上查找
- 如果没有找到,则会去它的proto隐式原型上查找,即它的构造函数的prototype
- 如果还没有找到就会再在构造函数的prototype的_proto__中查找(函数也是对象,也有proto)
- 这样一层一层向上查找就会形成一个链式结构,我们称为 原型链
作用域链
- 内部函数访问外部函数的变量采用的是链式查找的方式(就近原则)
5. 闭包
- 闭包就是能够读取其他函数内部变量的函数。
闭包的用途
- 闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
使用闭包的注意点
- 变量一直保存在内存中,容易内存泄露(在退出函数之前,将不使用的局部变量全部删除。)
- 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
6. 普通函数和箭头函数this指向说明?
箭头函数和普通函数的区别如下
普通函数:根据调用我的人(谁调用我,我的this就指向谁)
箭头函数:根据所在的环境(我再哪个环境中,this就指向谁)
普通函数中的this:
- this总是代表它的直接调用者(js的this是执行上下文), 例如 obj.func ,那么func中的this就是obj
- 在默认情况(非严格模式下,未使用 'use strict'),没找到直接调用者,则this指的是 window (常见的window的属性和方法有: alert, location,document,parseInt,setTimeout,setInterval等)(约定俗成)
- 在严格模式下,没有直接调用者的函数中的this是 undefined
- 使用call,apply,bind绑定的this指的是 绑定的对象
箭头函数中的this
- 箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在 setTimeout ,setInterval中方便的使用this
- 要整明白这些, 我们需要首先了解一下作用域链 : 当在函数中使用一个变量的时候,首先在本函数内部查找该变量,如果找不到则找其父级函数,最后直到window,全局变量默认挂载在window对象下
7. let var const的区别是什么?
let
- 块级作用域
- 暂时性死区
- 不存在变量提升
- 防止循环变量变成全局变量
- 创建的全局变量不在 window 中 ,只存在于script 中
var
- 没有块级作用域
- 可以重复声明
- 容易造成变量污染
- 只要不在函数中定义,在哪里定义都是全局变量
const
- 块级作用域
- 没有变量名提升
- 不能声明同名变量,值不能更改
- 声明必须赋值
- 创建的全局变量不在 window 中 ,只存在于script 中
8. 说一下es6的新特性?
- 不一样的变量声明:const和let
- 模板字符串
- 箭头函数(Arrow Functions)
- 函数的参数默认值
- Spread / Rest 操作符
- 二进制和八进制字面量
- 对象和数组解构
- for...of 和 for...in
- ES6中的类
9. 如何阻止事件冒泡和默认事件
- e. stopPropagation();//标准浏览器
- privent
- event.canceBubble=true;//ie9 之前
- 为了不让 a 点击之后跳转,我们就要给他的点击事件进行阻止return false
10. 事件委托
-
事件委托:利用事件冒泡的原理,将原本绑定给子元素的事件,绑定给父元素,子元素触发的事件冒泡给父元素,让父元素触发事件,执行函数。
-
事件委托好处:1. 效率好;2. 对于新增的子元素事件依然生效
-
第一个参数:click:事件类型 ,第二个参数 :function:处理函数 ,第三个参数 :false或者省略:表示是否处于冒泡阶段
- ul.addEventListener('click', function () {}
11. JavaScript 中什么情况下会返回 undefined 值?
-
访问声明,但是没有初始化的变量
-
var aaa;
console.log(aaa); // undefined
-
-
访问不存在的属性
-
访问函数的参数没有被显式的传递值
-
(function (b){
console.log(b); // undefined
})();
-
-
没有定义 return 的函数隐式返回
-
函数 return 没有显式的返回任何内容
-
function aaa(){
return;
}console.log(aaa()); // undefined
-
12. 什么是函数防抖和函数节流,他们的区别
- 防抖 debounce 如果速度非常快,只算最后一次
- 节流 throttle 如果速度非常快,它会按照一个速度均匀执行
防抖
// 防抖 debounce 如果速度非常快,只算最后一次
<input type="text" name="" id="">
let input = document.querySelector('input')
function search() {
console.log(this, this.value)
}
function debounce(fn) {
let timer
let self
return function () {
self = this
clearTimeout(timer)
timer = setTimeout(function () {
fn.call(self)
}, 1000)
}
}
input.oninput = debounce(search)
节流
// 节流 throttle 如果速度非常快,它会按照一个速度均匀执行
<input type="text" name="" id="">
let input = document.querySelector('input')
function fn() {
console.log(this, this.value);;
}
function debounce(fn) {
let timer = null
return function () {
self = this
if (!timer) { //定时器不存在时
timer = setTimeout(function () {
fn.call(self) //改变this指向
timer = null
}, 1000)
}
}
}
input.oninput = debounce(fn)
13. 简述深拷贝与浅拷贝?,有什么区别?
浅拷贝
- 只拷贝地址
- 重新赋值会改变原来数据
深拷贝
- 相对于一个新的对象(有一个新的地址)
- 重新赋值不会改变原来数据
14. 数组扁平化处理 如:[1,[2,[[3,4],5],6]] = > [1,2,3,4,5,6]。(手写)
-
数组扁平化是将二维甚至多维数组转化为一维数组的过程\
- 将[[1,2,3],4,5,[6,7,[8,9]]]这个多维数组转化为一维数组 转化之后的结果 [1,2,3,4,5,6,7,8,9]
// 在while循环里,会先读入一行输入,把它存入某个变量并且执行循环主体。然后,它再回头去找其他的输入行。
// 在foreach循环中,整行输入操作符会在列表上下文中执行(因为foreach需要逐行处理列表的内容)。在循环开始执行之前,它必须先将输入全部读进来。
// 当输入大容量的文件时,使用foreach会占用大量的内存。两者的差异会十分明显。因此,最好的做法,通常是尽量使用while循环的简写,让它每次处理一行。
// 利用展开运算符
var arr = [[1,2,3],4,5,[6,7,[8,9]]]
function flatten(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
console.log(flatten(arr))
15. JavaScript 的数据类型都有什么
-
基本数据类型:
- String,
- Boolean,
- number,
- undefined,
- object,
- Null
-
引用数据类型:Object
- Array,
- Date
- ,RegExp,
- Function
-
何判断某变量是否为数组数据类型
- slice()方法
- .obj instanceof Array 在某些 IE 版本中不正确
- Array.isArray() 推荐
16. str.substring()和str.substr()的区别
- str.substring( 截取的开始位置, 截取的结束位置 )
- str.substr( 截取的开始位置, 截取的个数/长度 )
17. 判断数组的方法
- arr instanceof Array
- Array.isArray( arr )
移动端
1. 响应式布局怎么实现的?移动端布局要考虑什么问题?
响应式布局
即 Responsive design,在实现不同屏幕分辨率的终端上浏览网页的不同展示方式。通过响应式设计能使网站在手机和平板电脑上有更好的浏览阅读体验。
-
flexible是一个用来适配移动端的javascript框架。
-
使用flex布局
-
用百分比去写元素的宽度,不要写绝对宽度
-
图片大小也用百分比写(流式布局)
-
字体使用相对大小 "em" 或 "rem"
- em: 指当前元素字体的倍数(相对于父元素)
- rem: 指html根元素字体大小的倍数(一般为16px)--->为有继承
- vm: 可视区分为100分(宽)
- vh: 可视区分为100分(高)
-
使用媒体查询 (CSS3 @media 查询)
-
在网页代码的头部,加入一行viewport元标签
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"> width:控制 viewport 的大小,可以指定的一个值,如 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素) height:和 width 相对应,指定高度 initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例,1.0就是占网页的100% maximum-scale:允许用户缩放到的最大比例 minimum-scale:允许用户缩放到的最小比例 user-scalable:用户是否可以手动缩放
-
请求这块
1. 简单介绍一下promise,他解决了什么问题?
Promise
Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息
-
promise有三种状态: pending(等待态),fulfiled(成功态),rejected(失败态) ;
- 状态一旦改变,就不会再变。创造promise实例后,它会立即执行。
-
resolve reject都是函数, resolve用来处理成功的状态,reject用来处理失败的状态
-
如何访问promise实例中的数据
- promise提供了两个方法 .then()处理成功 .catch()处理失败(不会同时存在2中状态)
promise基本概念
- Promise 是一个构造函数
- promise.prototype上包含一个 .then 方法
- .then()方法 可以用来预先指定失败的回调函数
- p.then(成功的回调函数 ,失败的回调函数) p.then(result=>{},error=>{})
- 调用p.then()方法时,成功的函数是必选的 失败的回调函数是可选的
2. 谈谈对async/await的理解?
async和await
- await必须结合async使用,async通常不会单独使用
- async表示这个函数是一个异步函数,它的返回值如果是一个普通数据类型,默认会用Promise将数据包裹
- await 等待?等待什么?等待的是一个异步的结果
- 异步和同步从上往下的顺序执行
相对于promise的优点:
- 更简洁 更容易调试 有更好的错误处理 有条件分支处理
- 处理中间值更简单 更清楚异常堆栈来自哪里
3. 跨越问题如何解决?
-
同源:2个页面的协议/域名/端口均相同为同源
-
同源策略 :A网站的js不允许和非同源的网站进行资源交互
-
跨域 :协议/域名/端口不一致时(会被浏览器拦截)
-
解决方案 :
-
JSONP 和 CORS和代理服务器
-
CORS:出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请求。缺点是不兼容某些低版本的浏览器
- 原理: 设置允许的响应头(需要浏览器和服务器同时支持).后台里面设置
-
JSONP:出现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。
-
原理:根据< script>标签的src属性不受浏览器同源策略的限制
-
动态创建< script>标签,结合它的src属性传递可查询参数
- 参数的值是一个函数名(函数名最好随机生成,防止变量污染)
-
服务器返回的是一段函数执行代码
缺点是只支持 GET 请求,不支持 POST 请求。
- 实现过程:
- script标签里的src属性动态创建和移除
- 在Jsonp请求时,动态向中append(添加)一个
- 在Jsonp请求成功后,动态从中移除刚才append的
由于浏览器同源策略的限制,网页中无法通过 Ajax 请求非同源的接口数据。但是 <script> 标签不受浏览器同 源策略的影响,可以通过 src 属性,请求非同源的 js 脚本。 因此,JSONP 的实现原理,就是通过 <script> 标签的 src 属性,请求跨域的数据接口,并通过函数调用的形式, 接收跨域接口响应回来的数据 -
-
代理服务器
-
原理: 服务器和服务器之前发送请求不受浏览器同源策略的影响
- 在vue.config.js 文件中配置
-
4. 输入网站url地址后发生了什么
-
会向服务器发送一个请求
-
我们会获取服务器的返回回来的数据
-
然后就是渲染页面了
-
输入地址
-
DNS解析,寻找服务器
-
TCP连接,三次握手
- 第一次:浏览器向服务器发送请求(SYN=1),等待服务器确认;
- 第二次:服务器收到请求并确认,回复一个指令(SYN=1,ACK=1);
- 第三次:客户端收到服务器的回复指令,并返回确认(ACK=1);
-
发送http请求,找到相应的资源库
-
返回http响应(返回数据)
-
浏览器解析渲染页面
-
断开连接
5. ajax工作流程以及原理?
-
Ajax的应用的五个步骤:
1、建立XMLHttpRequest对象;
2、设置回调函数;
3、使用open方法与服务器建立连接;
4、向服务器端发送数据;
5、在回调函数针对不同响应状态进行处理;
-
原理:
ajax的工作原理就是通过XmlHttpRequest对象来向服务器发出异步请求,从服务器中获得数据,然后用Javascript来操作DOM从而更新局部页面
6. axios 是什么?怎么使用?描述使用它实现登录功能的流程(登录拦截 权限验证)
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:
- Ajax 是页面无刷新请求数据操作
-
从浏览器中创建 XMLHttpRequest
-
从 node.js 发出 http 请求
-
支持 Promise API
-
拦截请求和响应
-
转换请求和响应数据
-
取消请求
-
自动转换JSON数据
-
客户端支持防止 CSRF/XSRF
axios({ url: 'http://www.baidu.com', method: 'get', // 可以发get和post请求 responseType: 'json', // 默认的 data: { //'a': 1, //'b': 2, } }).then(function (response) { // .then 函数专门用于处理成功的请求数据 console.log(response); console.log(response.data); }).catch(function (error) { // .catch函数用来捕获失败的错误 console.log(error);
7. Localstorage、sessionStorage、cookie 的区别(必会)
共同点: 都是保存在浏览器端、且同源的
区别:
-
请求不同
- cookie 数据始终在同源的 http 请求中携带(即使不需要)
- sessionStorage 和 localStorage不会自动把数据发送给服务器,仅在本地保存
-
存储大小限制不同
- cookie 数据不能超过 4K(只适合保存很小的数据,如会话标识)
- sessionStorage 达到 5M
- localStorage 20M或更大
-
数据有效期不同
- cookie只在设置的cookie 过期时间之前有效,即使窗口关闭或浏览器关闭
- localStorage: 始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据
- sessionStorage : 仅在当前浏览器窗口关闭之前有效
-
作用域不同
- cookie: 所有同源窗口中都是共享的
- localStorage: 在所有同源窗口中都是共享的
- sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面
-
安全性问题
- 如果 cookie 被人拦截了,那人就可以取得所有的 session 信息。即使加密也与事无补,因为拦截者并不需要知道 cookie 的意义,他只要原样转发 cookie 就可以达到目的了
8. 前后端分离不依靠后端接口,前端如何进行开发?
- mock(模拟接口返回的信息)
- 单纯的前端mock可以通过抓包工具Fiddler,Charles实现
- 通过修改代理返回的数据,实现多种场景的测试。这里在抓包工具之中会解释
9. post请求和get请求的区别
-
get 传送的数据长度有限制,post 没有
-
get 通过 url 传递(查询字符串),在浏览器地址栏可见,post 是在请求中传递
-
适用场景
- post 一般用于表单提交
- get 一般用于简单的数据查询,严格要求不是那么高的场景
10. Session,Token,Cookie在身份认证方面的区别?
-
为什么要使用身份认证:
- 因为http协议是无状态性的,每一次http请求都是独立的
- 连续多个请求之间无直接关系,服务器不会主动保存每次http请求状态
-
Session
- session数据放在服务器上。
- session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
- 将登陆信息等重要信息存放为session
-
Cookie
- cookie数据存放在客户端上(所以安全性不高)
- 所以每个域的cookie数量是有限的(比较小4kb)
- 每次发送请求会自动携带Cookie
-
Token
- token是服务端生成用于验证用户登录状态的加密数据,和session验证差不多。
- token验证服务端不需要存储用户会话的配置数据,只是加密的字符串
- 然后用Token设置请求头
- Token的目的是为了减轻服务器的压力,减少频繁的查询数据库
11. 常见的状态码
- 200:请求已成功
- 402: 参数传递错误
- 403:服务器已经理解请求,但是拒绝执行它。
- 404:请求失败,请求所希望得到的资源未被在服务器上发现。(未找到页面)
- 500:服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器端的源代码出现错误时出现。
vue
1. vue是如何实现双向数据绑定的(v-model)?
- 当前变量值修改,会触发Object.definedProperty中的set方法
- 将当前中的变量进行赋值
- (对象劫持--->监听)
- 是采用数据劫持结合发布者-订阅者模式的方式,
- 通过
Object.defineProperty()来劫持各个属性的setter,getter, - 在数据变动时发布消息给订阅者,触发相应的监听回调。
2. 谈谈对vue生命周期的理解?
-
beforeCreate
- 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用
-
created (这时候页面没有渲染,还获取不到数据)
- 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer), 属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
-
beforeMount
- 在挂载开始之前被调用:相关的 render 函数首次被调用。
-
mounted (此时可以获取到了数据)
- el 被新创建的 vm.el 也在文档内。
-
beforeUpdate
- 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行
-
updated
- 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
-
activated
- keep-alive 组件激活时调用。该钩子在服务器端渲染期间不被调用。
-
deactivated
- keep-alive 组件停用时调用。该钩子在服务器端渲染期间不被调用。
-
beforeDestroy
- 实例销毁之前调用。在这一步,实例仍然完全可用。该钩子在服务器端渲染期间不被调用。
-
destroyed
- Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
-
errorCaptured
- 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。
3. 第一次加载页面会触发哪几个钩子函数?
- beforeCreate
- created
- beforeMount
- mounted
4. Vue 组件 data 为什么必须是函数
-
产生块级作用域--->防止变量污染
-
让各个组件实例维护各自的数据
-
如果单纯的写成对象形式
- 就使得所有组件实例共用了一份 data
- 就会造成一个变了全都会变的结果
5. Vue 常用的修饰符都有哪些?
- .prevent: 提交事件不再重载页面;
- .stop: 阻止单击事件冒泡;
- .self: 当事件发生在该元素本 身而不是子元素的时候会触发
- .capture: 事件侦听,事件发生的时候会调用
6. vue组件通信的几种方式?(组件传值)
scoped:作用是让当前组件的样式成为一个局部作用域只在当前组件内生效
单向数据流:
在vue中需要遵循单向数据流原则
1. 父组件的数据发生了改变,子组件会自动跟着变
2. 子组件不能直接修改父组件传递过来的props props是只读的
3. 父组件传给子组件的是一个对象,子组件修改对象的属性,是不会报错的,对象是引用类型, 互相更新
第一种:父向子传值props
- 父组件内:
- 子组件内 props:[]或{}
第二种:子向父$emit
- 父组件内: @自定义事件名=' 父methods的函数名 '
- 子组件内: this.$emit('自定义事件名')
第三个:兄弟之间互传 : 这个不重要!!!! 自己百度去
7. vue路由模式实现原理(vue-router路由模式有几种)?
-
hash
- 有#号(#号后面是路由路径)
- 特点前端访问(#号后面的变化不会经过服务器)
- #后面的变化并不会导致浏览器向服务器发送请求,也就不会刷新页面
-
history
- 无#号,需要后端支持
- 特点后端访问(任何地址的变化都会访问服务器)
8. vue指令有哪些?
vue常用指令有:v-once指令、v-show指令、v-if指令、v-else指令、v-else-if指令、v-for指令、v-html指令、v-text指令、v-bind指令、v-on指令、v-model指令
9. vue中v-if和v-for能不能同时存在?如果不能?怎么处理?
- Vue 处理指令时,v-for 比 v-if 具有更高的优先级,
- 虽然用起来也没报错好使, 但是性能不高,
- 如果你有5个元素被v-for循环, v-if也会分别执行5次.
- (会造成内存浪费)即——先运行v-for 的循环,然后在每一个v-for 的循环中,再进行 v-if 的条件对比。
- 解决方案: v-if改v-show
10. v-if和v-show有什么区别
-
v-if: 对dom元素的创建和销毁
- 不频繁切换状态时
-
v-show: 单纯的隐藏 dispaly:none
- 频繁切换状态时
11. computed 和 watch和methods的区别?
实际得到的数据不能直接放到页面中展示,而是需要进行一些操作处理,就使用computed。
-
watch 适用场景:
- 一个数据影响多个数据
- 支持异步
- 不支持缓存,数据改变会直接触发相应的操作
-
computed适用场景:
- 一个数据受多个数据影响;
- 不支持异步
- 支持缓存,只有依赖数据发生改变,才会重新进行计算
- 和data里面的属性名不能相同
-
methods
- 则必须要有一定的触发条件才能执行(如点击事件)
- 不需要缓存时用 methods
12. 谈谈你对keep-alive的理解?
- 意义: 组件频繁切换,会导致组件被频繁的创建和销毁(性能不高)
- keep-alive是Vue内置的一个组件,可以提高组件的性能, 内部包裹的标签不会被销毁和重新创建
- 一般结合路由和动态组件一起使用,用于缓存组件;
- 对应的两个钩子函数activated和deactivated,当组件被激活时,触发钩子函数activated,当组件被移除时,触发钩子函数deactivated.
13. 什么是mvvm?
MVVM就是一种结构设计模式
- 什么是设计模式 : 设计模式就是对代码分层,引入一种架构的概念
- mvvm的好处 : 减少DOM操作,提高开发效率
- MVVM设计模式 : M-model(数据模型) V-View(视图) VM-viewmodel(连接数据模型和视图的对象,它可以监听数据的变化,将数据变化映射到视图,反过来也成立)
14. vuex 是什么?怎么使用?哪种场景使用它?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
-
应用遇到多个组件共享状态时,使用vuex。
-
state: 存放数据(相当于data)
-
mutations :
- state的数据改变必须经过mutations
- 不支持异步
- 执行这里面的函数--->store.commit
-
actions
- 支持异步
- 要改变state的数据必须先经过mutations
- 执行这里面的函数--->store.dispatch
-
getters
- 相当于计算数据
- 一般用于映射(在vuex模块化时,可以把子模块的数据映射出来,方便取)
-
modules
- 存放子模块的
15. vue首页白屏是什么问题引起的?如何解决呢?
-
打包后文件引用路径不对,导致找不到文件报错白屏
解决办法:修改一下config下面的index.js中bulid模块导出的路径。因为index.html里边的内容都是通过script标签引入的,而你的路径不对,打开肯定是空白的。先看一下默认的路径。
-
第二种,路由模式mode设置影响
解决方法:路由里边router/index.js路由配置里边默认模式是hash,如果你改成了history模式的话,打开也会是一片空白。所以改为hash或者直接把模式配置删除,让它默认的就行 。如果非要使用history模式的话,需要你在服务端加一个覆盖所有的情况的候选资源:如果URL匹配不到任何静态资源,则应该返回一个index.html,这个页面就是你app依赖页面。
所以只要删除mode或者把mode改成hash就OK了。
-
第三种,项目中使用了es6的语法,一些浏览器不支持es6,造成编译错误不能解析而造成白屏
解决方法:
- 安装 npm install --save-dev babel-preset-es2015
- 安装 npm install --save-dev babel-preset-stage-3
- 在项目根目录创建一个.babelrc文件 里面内容 最基本配置是:
{
// 此项指明,转码的规则
"presets": [
// env项是借助插件babel-preset-env,下面这个配置说的是babel对es6,es7,es8进行转码,并且设置amd,commonjs这样的模块化文件,不进行转码
["env", {
"modules": false
}],
// 下面这个是不同阶段出现的es语法,包含不同的转码插件
"stage-2"
],
// 下面这个选项是引用插件来处理代码的转换,transform-runtime用来处理全局函数和优化babel编译
"plugins": ["transform-runtime"],
// 下面指的是在生成的文件中,不产生注释
"comments": false,
// 下面这段是在特定的环境中所执行的转码规则,当环境变量是下面的test就会覆盖上面的设置
"env": {
// test 是提前设置的环境变量,如果没有设置BABEL_ENV则使用NODE_ENV,如果都没有设置默认就是development
"test": {
"presets": ["env", "stage-2"],
// instanbul是一个用来测试转码后代码的工具
"plugins": ["istanbul"]
}
}
}
16. vue中的key 有什么作用?
-
好处: 可以配合虚拟DOM提高更新性能
-
如何没有key时(v-for更新时如何操作DOM)
- 循环出新的虚拟DOM结构,和旧的虚拟DOM结构对比
- 尝试复用标签,就地更新内容(虚拟DOM替换真实DOM)
- 就地更新
-
有key时: (给每一个节点做唯一标识)
- 基于key来比较新旧虚拟DOM,移除key不存在的元素
17. 你对vue项目进行哪些优化?
v-if 和 v-show区分使用场景computed 和 watch区分使用场景- 数据较大时,做分页
v-for 遍历必须为 item 添加 key,且避免同时使用 v-if- 浏览器缓存
- 第三方插件按需引入
- vuex , vue-router模块化,提供开发效率
18. vue有什么缺点?
- 不支持IE8以下
- 社区可能没有Angular和React那么丰富
- Vue 不缺入门教程,可是很缺乏高阶教程与文档。同样的还有书籍
- 因为是单页面应用,不利于seo优化
- 初次加载时耗时多
19. vue-router有哪几种导航钩子?
1.导航钩子的作用
- vue-router提供的导航钩子主要用来拦截导航,让它完成跳转或取消。
三种导航钩子
- 全局守卫(前置守卫) beforeEach
- 后置守卫 afterEach
- 全局解析守卫:beforeResolve
- 路由独享守卫:beforeEnter
Vue-router 的钩子函数都有哪些?
-
to 要跳转到的路由
-
from 从哪里跳转的路由
-
next
- next()才会正常跳转
- next(false)在原地停留
- next('/路径') 强制前往到另一个路由路径上
- next(to.path) 相当于跳转到对应地址
20. 路由之间是怎么跳转的?有哪些方式?
- < router-link to="需要跳转到页面的路径" >
- this.$router.push()
- this.$router.replace()跳转到指定的url
- this.$touter.go(n)向前或者后跳转 n 个页面,n 可以是正数也可以是负数
21. 路由传值的方式有哪几种
-
编程式的导航 router.push
-
查询参数 query
- 接收参数 this.$route.query
-
动态参数 params
- 接收参数 this.$route.params
-
-
声明式的导航
- 查询参数 query
- 动态参数 params
22. route 和router 的区别是什么?
-
route
- 路由信息对象
- 里面可以获取name,path.params.query等
- 每个路由都有一个$route对象 是一个局部对象
-
router
- 是vueRouter的实例,相当于全局的路由对象
- 里面有很多属性和方法,push.replace.go.history 等
23. vue打包成最终的文件有哪些?
- html
- css
- js
- fonts
- img
24. wepack主要起什么作用?
分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。
25. loader 和 plugin 的区别是什么?
-
loader(编译方法)
- webpack自身只能处理js,别的资源需要loader(css.font.img这些)
- webpack只能打包,编译功能是loader来做
- 都是三方的
- loder时webpack 可以处理各种类型文件
-
plugin(优化)
- 提供一些webpack额外的扩展
- 帮助webpack优化代码,提供功能
- 一些是webpack内置的,一些是三方的
26. 对webpack做过哪些优化
-
image-webpack-loader这个
loder可以帮助我们对打包后的图片进行压缩和优化,- 例如降低图片分辨率,压缩图片体积等。
-
一般常用的类库都会发布在
CDN上,因此,我们可以在项目中以CDN的方式加载资源,这样我们就不用对资源进行打包,可以大大减少打包后的文件体积。 -
使用按需加载,将每个路由页面单独打包为一个文件
项目
1. token权限处理
-
表单验证登陆成功后会获取到token
-
把token存在cookie和vuex里面方便取
-
请求拦截器里面做判断
- 有token时,设置请求头
- 无token就再次发送请求
2. token超时处理
一般有三种处理方式: 前端处理 后端处理 双token
-
前端处理
- 前端自己设置一个token有效期
- 在获得token的时候利用cookie-js自带的方法存入一个时间戳
- 在请求拦截器里面做判断现在的时间减去存入token的时间是否超时了
- 超时我的处理的是重新登录(返回登陆页面)
-
后端处理
- 如果token超时,后端会返回一个状态码
- 在响应拦截器error中做判断,看看返回的状态码是否登录后端返回的这个token超时状态码,等于的话就做处理(返回登录页面)
-
双token处理
- 有的时候登陆成功时后端会返回2个token给我们,一个是现在用的,一个是超时过后用的
- 如果开始用的token超时了,那么做处理,调用第二个token设置到请求头里面
- 如果第二个也超时了,做处理(返回登录页面)
3. 路由守卫
-
在beforeEach(前置路由守卫)里面做逻辑
-
先判断有没有token
- 有token时,如果在登录页,则去首页
- 否则在其他页面就next()放行通过
-
没有token时
- 设置一个白名单(登录页,404页面时)
- 如果在白名单,放行通过(不需要权限的页面)
- 如果在需要权限的页面则强制去登录页next('/login')
4. 页面权限和按钮权限
-
页面权限
- 登录成功后,后台会返回一个权限菜单列表
- 用代码在所有动态权限里面去判断这个用户存不存在这个权限
- 存在就用addRoutes里面()
-
按钮权限
- 全局自定义指令
- 混入