浏览器内多个标签页之间的通信方式
- 方式通过localStorage可实现同源的多个标签页之间的通信
因为同源共享存储空间,可以利用storage方法监听localStorage对象的变化
window.addEventlistener('storage',(e)=>{
console.log('打印最新值',e)
})
- webSocket 没有同源共享策略,可实现跨域共享
A发消息给服务器,服务再将消息传给B
将一个颜色用css颜色变浅
opacity:0.4; 数字越大颜色越深
或者用less内置的函数来让颜色变淡
color: saturate(@base, -5 % ); //将颜色饱和度减少 5%
当前页面和iframe页面之间通信
//给子页面发消息
this.$refs.iframeId.contentWindow.postMessage(
{
cmd: 'setToken',
res: {
token: token
}
},
'*'
)
vue中怎么解绑事件
<button @click="flag && doFunc"></button>
事件绑定后,在事件中添加一个标记位即可清楚事件
项目中如何区分单击和双击做不同的事情
- 分析:在一定范围内点击了两次就是双击,超过这个时间就是单击
判断在不在周期时间范围内,如果在这个周期范围内就是双击,否则就是单击
代码:
export function isSingleClick (fn,times=500){
let timer = null
return function(){
// 双击
if(timer){
// 双击操作
fn.apply(this,arguments)
clearTimeout(timer)
timer = null
return
}
// 单击操作
timer = setTimeout(()=>{
fn.apply(this,arguments)
timer = null
},times)
}
}
判断数据类型
我们常用typeof去判断数据类型,只能区别基本类型string,number,null,undefined,object,boolean
但是数组和null的typeof是'object',
所以我们可以使用Object.prototype.toString.call()去判断具体的类型
Object.prototype.toString.call('asd') //[object String]
Object.prototype.toString.call(123) //[object Number]
Object.prototyper.toString.call([1,2,3]) // [object Array]
let date b= new Date()
Object.prototyper.toString.call(date) // [object Date]
let func = function (){}
Object.prototyper.toString.call(func) // [object Function]
Object.defineProperty
在一个对象上添加一个新的属性 或者是修改现有的属性,并返回这个修改的对象
它有三个参数:
1 需要操作的对象
2 要定义或修改的属性名
3 要定义或修改的属性描述符
let obj = {}
let myName = "我最牛逼"
object.defineProperty(obj,'name',{
get:()=>{
return myName
},
set:(val)=>{
myName = val
}
})
console.log(obj.name) //触发get
obj.name = '哈哈' //触发set
Symbol
symbol是ES7新加的数据类型,代表的是独一无二的值
let a = Symbol('foo') // a: foo
let b = Symbol('foo')
a == b // false
let a = Symbol.for('foo1')
let b = Symbol.for('foo1')
a == b //true
symbol.for 查找上下文有没有使用相同参数创建的Symbol值, 如果没有,则创建一个,有的话,则返回之前的
let d = Symbol.keyFor(a) // 'foo1'
Symbol.keyFor可得到Symbol.for创建的Symbol值的key
使用场景
let tabsName = {
tab1: Symbol(),
tab2:Symbol()
}
type == tabsName.tab1&&<Componet/>
type == tabsName.tab2&&<Componet2/>
less公用设置
在公用的less文件中 可利用@创建变量
#创建css代码块
也可以定义一个带参数的属性函数
像这样
.border-radius (@radius) {
border-radius: @radius;
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
}
rem 的原理
就是讲当前视图等分之后的比例换算成px设置给html font-size。
如果是20px 则代表1rem = 20px
map和set的区别
Map
map和平常的对象类似也是通过键值对的形式存储数据
一般对象是无序的,map是存储的对象是有序的
而且它的key可以是任意类型
默认接受的是一个二维数组,数组的第一个值是key,第二个是value
.get(可获取某个值)
Set
set的值是唯一的值,常用来数组去重
set是一个无序结构
set是一个类数组对象
存储的数据不是键值对的形式,可以存储任何类型的数据
也称为set集合
因为set不是键值对的形式,一般是forEach取里面的值
set的格式
var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}
都有size获取长度的属性
set设置值
has判断是否有这个属性
delete 删除某个数据
Vue页面的首屏优化
从webpack方面:
引入到组件中的js,css等都会打包成vendor文件,如果这个文件过大,就会影响首屏的体验
拆分入口文件chunk,静态文件分离开
修改CommonsChunkPlugin配置
miniChunks:2
这样会把使用两次及以上的包抽离出来,放进公共文件里
生产环境关闭源码映射
使用uglify-webpack-plugin来压缩js文件
使用mini-xss-extract-plugin提取css到单独的文件,并利用optimize-css-assets-webpack-plugin来压缩css文件
静态库按需引入组件,而不是全部引入,比如elementUi
静态文件上传到CDN 实现CDN加速
vue-router懒加载
在路由跳到当前路由页面的时候,再加载当前路由页面的资源
{
name:'index',
path:'/index'
component:()=> import('@/page/index.vue')
开启gizip压缩
http的一种请求优化方式,通过减少文件的体积,来优化加载速度,
html,js,css,json数据都可以用它来压缩,可减少60%的体积
前端配置gizip压缩,
服务端使用nginx开启gizip,减小文件体积,缩短传输时间,减少网络传输的流量大小
页面层面
合理使用v-if v-show
watch 和computed
遍历的元素要加上key
定时器和自定义事件的及时销毁
怎么封装组件
在使用第三方组件二次封装的时候,可在第三方组件上使用v-bind="$attrs",v-on="$listeners"
那么自己封装的组件也就支持第三方组件的所有属性和事件,组件编写更加简写,有时第三方组件也有自己的一个插槽,比如说 ElementUI的prepend,
然后才是在组件内接受定义props,插槽,以及操作之后的触发父组件的方法,
组件的flag显示的开关
利用作用域插槽子组件向父组件传值
子组件
<slot :name="d"/>
父组件
<>
<templete slot-scope="sclopData">
<div>{{sclopData.name}}</div>
</templete>
</>
vue的权限控制,菜单栏控制,按钮权限
1 路由文件中分为静态路由,和动态路由,初始的时候是只初始化了静态
2 在动态路由里面添加meta对象,然后有一个权限数组,这个数组定义元素是哪些用户角色可以访问当前路由
3.拿着登录时获取到的用户角色同动态路由做对比,如果包含在内的利用router.addRoutes添加到路由中去
菜单栏控制
4.导航菜单栏是 根据当前用户角色过滤后的动态路由和静态路由数组合在一起的数组递归遍历渲染导航菜单栏
按钮权限
5.按钮权限的控制利用自定义指令 它的value是一个数组,包含了可操作的角色名称,如果当前用户不满足条件,则删除当前元素
防抖和节流
防抖
debounce(fn, delay) {
let timer = 0
return function () {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = 0
}, delay)
}
},
this.$refs.input.addEventListener(
'keyup',
this.debounce(() => {
console.log('防抖')
})
)
Ajax Fetch Axios的区别
Ajax (Asynchronous javascrpript and XML),一种技术总称
Fetch 一个具体的API
Axios 第三方库
- 浏览器原生API 用于网络请求
和XMLHttpRequest一个级别
Fetch语法更加简洁,易用,支持Promise
通过XMLHttpRequest实现ajax
function ajax (url, sucessFn) {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, false) //false 是异步的方式
xhr.onreadystatechange = function () {
// 这里的函数异步执行
if (xhr.readyState == 4) {
if (xhr.status == 200) {
sucessFn(xhr.responseText)
}
}
}
xhr.send(null)
}
用fetch实现ajax
function ajax2(url){
return fetch(url).then(res=>res.josn)
}
API是原生的函数
库是第三方的工具
节流
在拖拽中使用
<div draggable="true" id="div1"></div>
function throttle(fn,delay=100){
let timer = 0
return function(){
if(timer)return
timer = setTimeout(()=>{
fn.apply(this,arguments)
},delay)
}
}
const div1 = document.getElementById('div1')
div1.addEventListener('drag',throttle((e)=>{
console.log('鼠标的位置',e.offsetX,e.offsetY);
}))
区别
- 节流:限制执行频率,有节奏的执行
- 防抖:限制执行次数,多次密集的触发只执行一次
- 节流关注 “过程”,防抖关注 “结果”
- 实际工作可使用lodash
% rem em vw vh的区别
em 相当于当前元素的font-size
rem 相当于根节点的font-size
vw是屏幕宽度的1%
vh是屏幕高度的百分比
vmin是两者最小值 vmax是两者最大值
不适用箭头函数的场景
- 对象方法
- 对象原型
- 构造函数
- 动态上下文的回调函数
- Vue生命周期method
要熟练应用箭头函数 也要对函数this arguments敏感
传统Vue组件是JS对象 传统React组件是class,两者不同
请描述TCP三次握手和四次挥手
握手是tcp连接的过程,挥手是tcp断开的过程
三次握手
- 先建立连接(确保)双方都有收发消息的能力
- 再传输内容(如发送一个get请求)
- 网络连接是TCP协议,传输内容是Http协议
client发包, server接收。server:有client要找我
Server发包,Client接收。Client:Server已经收到信息了
Client发包,Server接收, server: client要准备发送了
四次挥手
Client发包,Server接收。Server:Client已请求结束后
Server发包,Client接收 Client:Server已收到,我等待它关闭
Server发包,Client接收,Client:Server此时可以关闭连接了
Client发包,Server接收,Server:可以关闭了(然后关闭连接)
for in 和for of的区别
for … in 用于可枚举数据 如对象,数组。字符串 得到key
for…of 用于可迭代数据 如数组、字符串 Map Set 得到value
for wait of 有什么作用
就是promise.all的替代品
offsetHeight scrollHeight clinetHeight区别
offsetHeight offsetWidth: border + padding + content
clientHieght clientWidth: padding + content
scrollHeight scrollWidth: padding + 实际内容尺寸
scrollTop scrollLeft: 需滚动之后获取 滚动之后隐藏的高宽
HTMLCollection 和NodeList区别
Node 和Element
DOM是一棵树 所有节点都是Node
Node是Element的基类
Element是其他HTML元素的基类,如HTMLDivElement
所以
HTMLCollection是Element的集合
NodeList是node的集合
获取Node和Element的返回结果可能不一样
如lelem.childNodes和elem.children不一样
前者会包含Text和Comment节点,后者不会
watch和computed的区别
两者用途不同
computed用于计算产生新的数据
computed有缓存,methods里面没有缓存
watch用于监听现有数据
vue组件通讯的方法
- props和$emit
- 自定义事件
- $attr
- $parent
- $refs
- provide/inject
- Vuex
Vuex中mutation和action之间的区别
mutation:原子操作 必须同步操作
action: 可包含多个mutation 可包含异步代码
js严格模式有什么特点
全局变量必须先声明
禁止使用with
创建eval作用域
禁止this指向window
函数参数不能重名
HTTP跨域请求时为何发送options请求
- 浏览器的同源策略
- 同源策略一般限制Ajax网络请求,不能跨域请求server
- 不会限制
跨域请求之前有可能会发送options请求
我既然要做一个跨域请求,那你这个服务端支不支持delete或者别的请求
别你不支持了,我发过去也没有用,所以我先发一个options请求,看你支持哪些方法
如果options报错,那就要去检查是不是预检查没有通过
- 所以options请求 是跨域请求之前的预检查
- 是浏览器自行发起的,无需我们干预
- 不影响实际的功能
内存泄漏
场景
- 被全局变量,函数引用,组件销毁时未清除
- 被全局事件、定时器引用在、组件销毁时未清除
- 被自定义事件引用 组件销毁时未清除
内存泄漏是非预期的情况
想让它经过积极处理机制回收,却没有回收,称之为内存泄漏
- 被自定义事件引用 组件销毁时未清除
在浏览器中查看可以看到
锯齿状 就是一会上升一会下降
这个是正常的
内存泄漏是上升状
宏任务微任务
- 事件处理机制
同步事件在时间总线中执行,异步事件会放在异步队列中,一旦主线的任务执行完,
浏览器的event loop会把异步队列的事件以先进先出的形式,转移到主线里面。
- 而宏任务在宏任务异步队列中 微任务在微任务异步队列中
宏任务,如setTimeout setInterval 网络请求
微任务 如 promise async/await
微任务在下一轮DOM渲染之前执行 宏任务在之后执行
for和forEach哪个性能好
for更快
forEach每次都要创建一个函数来调用,而for不会创建函数
函数需要独立的作用域,会有额外的开销
越低级的代码 性能往往越好
日常开发别只考虑性能 forEach代码可读性更好
vdom与直接操作dom哪个才是最快的
vdom并不快,JS直接操作DOM才是最快的
但数据驱动视图 要有合适的技术方案,不能全部Dom重建
vdom就是目前最合适的技术方案(并不是因为它快,而是合适)
- data变化
- diff算法 vnode oldVnode (vdom)
- 更新DOM
1 data变化 2.vnode diff 3.更新DOM
vdom是什么
virtualDOM,虚拟DOM
用JS对象模拟DOM节点数据
由React最先推广使用
而Vue React等框架的价值
- 组件化
- 数据视图分离,数据驱动视图 ----这是核心
- 只关注业务数据,而不用再关心DOM变化
浏览器和nodeJs事件循坏(eventLoop)有什么区别
JS是单线程的(无论在浏览器还是nodeJs)
浏览器中JS执行和DOM渲染共用一个线程
异步是单线程的解决方案
宏任务,如setTimeOut setInterval网络请求
微任务,如promise async/await
微任务在下一轮DOM渲染之前执行,宏任务在之后执行
NodeJS宏任务和微任务
NodeJS宏任务优先级
Timers - setTimeout setInterval
I/O callbacks - 处理网络、流 、 TCP的错误回调
Idle,prepare - 闲置状态(nodejs内部使用)
Poll 轮询 -执行poll中的I/O队列
Check检查 -存储setImmediate回调
Close callbacks -关闭回调,如socket.on('close')
微任务类型和优先级
包括:promise,async/await,process.nextTick
注意,process.nextTick优先级最高
nodeJs event loop
执行同步代码
执行微任务(process.nextTick优先级更高)
按顺序执行6个类型的宏任务(每个结束时都执行当前的微任务)
推荐使用setImmediate代替process.nextTick
浏览器和nodejs的event loop流程基本相同
nodejs宏任务和微任务类型有优先级