一、项目背景
二、性能优化:防抖和节流
防抖:当你持续触发事情时,一段时间内没有再触发事件,执行一次
节流:当你持续触发事情时,一段时间内调用一次函数(risize、scoll)
三、登录如何实现
四、token过期如何处理
五、项目后台谁写的?
六、cookie、localStorage、sessionStorage三个区别
(1)Cookie
Cookie是最早被提出来的本地存储方式,在此之前,服务端是无法判断网络中的两个请求是否是同一用户发起的,为解决这个问题,Cookie就出现了。Cookie的大小只有4kb,它是一种纯文本文件,每次发起HTTP请求都会携带Cookie。
Cookie的特性:
- Cookie一旦创建成功,名称就无法修改
- Cookie是无法跨域名的,也就是说a域名和b域名下的cookie是无法共享的,这也是由Cookie的隐私安全性决定的,这样就能够阻止非法获取其他网站的Cookie
- 每个域名下Cookie的数量不能超过20个,每个Cookie的大小不能超过4kb
- 有安全问题,如果Cookie被拦截了,那就可获得session的所有信息,即使加密也于事无补,无需知道cookie的意义,只要转发cookie就能达到目的
- Cookie在请求一个新的页面的时候都会被发送过去
如果需要域名之间跨域共享Cookie,有两种方法:
- 使用Nginx反向代理
- 在一个站点登陆之后,往其他网站写Cookie。服务端的Session存储到一个节点,Cookie存储sessionId
2)LocalStorage
LocalStorage是HTML5新引入的特性,由于有的时候我们存储的信息较大,Cookie就不能满足我们的需求,这时候LocalStorage就派上用场了。
LocalStorage的优点:
- 在大小方面,LocalStorage的大小一般为5MB,可以储存更多的信息
- LocalStorage是持久储存,并不会随着页面的关闭而消失,除非主动清理,不然会永久存在
- 仅储存在本地,不像Cookie那样每次HTTP请求都会被携带
LocalStorage的缺点:
- 存在浏览器兼容问题,IE8以下版本的浏览器不支持
- 如果浏览器设置为隐私模式,那我们将无法读取到LocalStorage
- LocalStorage受到同源策略的限制,即端口、协议、主机地址有任何一个不相同,都不会访问
LocalStorage的 常用API:
// 保存数据到 localStorage
localStorage.setItem('key', 'value');
// 从 localStorage 获取数据
let data = localStorage.getItem('key');
// 从 localStorage 删除保存的数据
localStorage.removeItem('key');
// 从 localStorage 删除所有保存的数据
localStorage.clear();
// 获取某个索引的Key
localStorage.key(index)
SessionStorage的 使用场景
- 由于SessionStorage具有时效性,所以可以用来存储一些网站的游客登录的信息,还有临时的浏览记录的信息。当关闭网站之后,这些信息也就随之消除了。
3)SessionStorage
SessionStorage和LocalStorage都是在HTML5才提出来的存储方案,SessionStorage 主要用于临时保存同一窗口(或标签页)的数据,刷新页面时不会删除,关闭窗口或标签页之后将会删除这些数据。
SessionStorage 与LocalStorage对比:
- SessionStorage和LocalStorage都在本地进行数据存储;
- SessionStorage也有同源策略的限制,但是SessionStorage有一条更加严格的限制,SessionStorage只有在同一浏览器的同一窗口下才能够共享;
- LocalStorage和SessionStorage都不能被爬虫爬取;
SessionStorage的 常用API:
// 保存数据到 sessionStorage
sessionStorage.setItem('key', 'value');
// 从 sessionStorage 获取数据
let data = sessionStorage.getItem('key');
// 从 sessionStorage 删除保存的数据
sessionStorage.removeItem('key');
// 从 sessionStorage 删除所有保存的数据
sessionStorage.clear();
// 获取某个索引的Key
sessionStorage.key(index)
七、浏览器有很多标签页,那同一个网站的sessionStorage能访问到吗?
不可以访问
八、什么是跨域、解决跨域有哪些方式?
(1)CORS
①简单请求过程:
在简单请求中,在服务器内,至少需要设置字段: Access-Control-Allow-Origin
②非简单请求过程
至少需要前三个字段
Access-Control-Allow-Origin: http://api.bob.com // 允许跨域的源地址
Access-Control-Allow-Methods: GET, POST, PUT // 服务器支持的所有跨域请求的方法
Access-Control-Allow-Headers: X-Custom-Header // 服务器支持的所有头信息字段
Access-Control-Allow-Credentials: true // 表示是否允许发送Cookie
Access-Control-Max-Age: 1728000 // 用来指定本次预检请求的有效期,单位为秒
(2)JSONP
jsonp的原理就是利用<script>标签没有跨域限制,通过<script>标签src属性,发送带有callback参数的GET请求,服务端将接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从而前端拿到callback函数返回的数据。
1)原生JS实现:
<script>
var script = document.createElement('script');
script.type = 'text/javascript';
// 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
document.head.appendChild(script);
// 回调执行函数
function handleCallback(res) {
alert(JSON.stringify(res));
}
</script>
服务端返回如下(返回时即执行全局函数):
handleCallback({"success": true, "user": "admin"})
2)Vue axios实现:
this.$http = axios;
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
后端node.js代码:
var querystring = require('querystring');
var http = require('http');
var server = http.createServer();
server.on('request', function(req, res) {
var params = querystring.parse(req.url.split('?')[1]);
var fn = params.callback;
// jsonp返回设置
res.writeHead(200, { 'Content-Type': 'text/javascript' });
res.write(fn + '(' + JSON.stringify(params) + ')');
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');
JSONP的缺点:
- 具有局限性, 仅支持get方法
- 不安全,可能会遭受XSS攻击
(3)postMessage 跨域
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个场景的跨域数据传递
用法:postMessage(data,origin)方法接受两个参数:
- data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
- origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
(4)nginx代理跨域
(5)nodejs 中间件代理跨域
(6)WebSocket协议跨域
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。
九、权限管理的实现
权限管理我分成了两个部分、一个权限列表、一个是角色列表
- 权限列表(所有菜单列表) 权限列表展示的是项目所有功能菜单、字段包含菜单名称、路径、菜单等级、菜单之间的依附关系(简单来说就是一个树结构以列表形式展示),我们可以对里面菜单进行增、删、改。
路径:是用来跳转哪个前端路由里面的页面
- 角色列表 角色列表里面包含了每个角色的角色名称、角色描述、以及分配权限按钮
点击分配权限,会展示所有菜单的复选框、点击你想分配的权限
用户登录时、根据该用户登录返回的用户名称、用户对应角色去找他的权限、后台会返回一个树结构的用户对应的菜单(这也就是他的一个权限)这样每个用户进来的页面就会有所不同。
十、get和post区别
十一、压缩文件是怎么实现的
十二、有部署到服务器端吗?
十三、项目build的时候就会压缩、那么你为什么还要进行压缩呢
使用gzip可以减小文件体积,使传输速率更快
可以通过服务端使用Express做gzip压缩,配置如下
//安装相应的包
npm install compression -D
//导入包
const compression=require('compression')
//启动中间件
app.use(compression())
文件大小为74kb,但是传输过程中进行了压缩,变成了24k(减少下载流量)
十四、垂直布局
1.flex
2.绝对定位
十五、父容积高度塌陷、如何处理(待会查一下)
伪类去清除浮动
十六、BFC是什么?
BFC是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并且不会影响其它环境中的物品。如果一个元素符合触发BFC的条件,则BFC中的元素布局不受外部影响。
十七、js里面有哪些数据类型
十八、js里面有哪些作用域?
全局作用域 函数作用域 块级作用域
十九、可以通过什么改变this的指向
bind call apply (apply第二个参数必须是数组)
二十、es6里面你用过哪些新特性
let、const
扩展运算符
二十一、字符串可以用扩展用算符吗?
可以使用
补充:扩展运算符的用法
-
对象的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中(相当于Object.assign()属于浅拷贝)
-
将数组转换为参数序列
-
复制数组
-
合并数组
-
*需要注意:如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。
const [...rest, last] = [1, 2, 3, 4, 5]; // 报错
const [first, ...rest, last] = [1, 2, 3, 4, 5]; // 报错
- 将字符串转为真正的数组
[...'hello'] // [ "h", "e", "l", "l", "o" ]
- 任何 Iterator 接口的对象,都可以用扩展运算符转为真正的数组
比较常见的应用是可以将某些数据结构转为数组:
// arguments对象
function foo() {
const args = [...arguments];
}
- 使用
Math函数获取数组中特定的值
const numbers = [9, 4, 7, 1];
Math.min(...numbers); // 1
Math.max(...numbers); // 9
二十二、说一下什么事promise链式调用
Promise是异步编程的一种解决方案,它是一个对象,可以获取异步操作的消息,他的出现大大改善了异步编程的困境,避免了地狱回调,它比传统的解决方案回调函数和事件更合理和更强大。
Promise的特点:
-
对象的状态不受外界影响
-
一旦状态改变就不会再变,任何时候都可以得到这个结果。
Promise的缺点:
- 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
- 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
- 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
二十三、promise异常怎么捕获
catch去捕获异常
二十四、那么catch之后再catch一次可以捕获到异常吗?
Promise.reject(
new Error("我错了,请原谅俺!!")
).catch((e)=>{
console.log(e)
}).catch((e)=>{
console.log(e)
})
不可以再次捕获
promise有哪些常用方法
then()、catch()、all()、race()、finally
- all()
all方法可以完成并行任务, 它接收一个数组,数组的每一项都是一个promise对象。当数组中所有的promise的状态都达到resolved的时候,all方法的状态就会变成resolved,如果有一个状态变成了rejected,那么all方法的状态就会变成rejected。
- race()
race方法和all一样,接受的参数是一个每项都是promise的数组,但是与all不同的是,当最先执行完的事件执行完之后,就直接返回该promise对象的值。如果第一个promise对象状态变成resolved,那自身的状态变成了resolved;反之第一个promise变成rejected,那自身状态就会变成rejected。
那么race方法有什么实际作用呢?当要做一件事,超过多长时间就不做了,可以用这个方法来解决:
Promise.race([promise1,timeOutPromise(5000)]).then(res=>{})
- finally()
finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
二十五、 async和await异常怎么捕获
async function fn(){
try{
let a = await Promise.reject('error')
}catch(error){
console.log(error)
}
}
二十六、vue-cli脚手架
二十七、webpack怎么样(待会总结)
1.启动打包项目
npm怎么装包吗?
【开发环境】:指的是你的项目尚且在编码阶段时的环境。你在代码可能还有各种console.log()、注释、格式化等。
【生产环境】:指的是你的项目已经完成编码,并发布上线可供用户浏览的阶段时的环境。代码可能经过了压缩、优化等处理
生产依赖和开发依赖有什么区别吗?
生产依赖 dependencies
npm i package-name --save 或 npm i package-name -S
开发依赖 devDependencies
npm i package-name --save-dev 或 npm i package-name -D
二十八、如何发布你自己写的npm的包?
二十九、vue双向绑定的原理?
三十、有了解ts吗?
三十一、html5里面有哪些新的特性?
1.语义化标签
2.音视频标签
3.canvas
4.svg
5.拖拽的api
三十二、原型链
三十三、如何获取一个对象的原型
obj.proto
obj.prototype
三十四、git指令
三十五、如何求一个数的阶层(123...i)
1.for循环
2.递归(跳出循环条件是什么i=1时)