一、Event Loop
1、Event Loop概念
Event Loop 即事件循环, 是JavaScript或Node为解决单线程代码执行不阻塞主进程一种机制,也就是我们所说的异步原理。
2、JavaScript特点
JavaScript语言的一大特点就是单线程。(原因:JavaScript的单线程,与它的’用途’有关。作为’浏览器脚本语言’,JavaScript的主要用途是与’用户互动’,以及’操作DOM’。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?)。这就决定了JavaScript语言必须是单线程。
3、同步任务,异步任务
JavaScript中任务分为同步任务,异步任务。'同步任务’指的是,在’主线程’上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;'异步任务’指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
4、执行步骤:
1)整体的script(作为第一个宏任务)开始执行的时候,会把所有代码分为两部分:“同步任务”、“异步任务”;
2)同步任务会直接进入主线程依次执行;
3)异步任务会再分为宏任务(进入宏任务队列) 和 微任务(进入微任务队列)。
4)当主线程内的任务执行完毕(主线程为空时),会检查微任务的任务队列,如果有任务,就进入主线程全部执行,如果没有就从宏任务队列读取下一个宏任务执行;
5)每执行完一个宏任务就清空一次微任务队列,此过程会不断重复,这就是Event Loop;
5、宏任务和微任务
宏任务:setInterval(),setTimeout(),setImmediate(),ajax,事件绑定,Promise构造函数
微任务:new Promise()后的.then与.catch函数,new MutaionObserver(),process.nextTick(Nodejs)
6、Promise构造函数
Promise构造函数是宏任务。在执行new Promise()时,会立即创建一个新的Promise对象,并执行传入的函数,这个函数中的代码属于’宏任务’。而Promise.then()方法中注册的回调函数是微任务。当Promise对象状态发生改变时,会将对应的微任务加入到微任务队列中,等待宏任务执行完毕后优先执行微任务队列中的任务。因此,Promise构造函数中的代码和Promise.then()方法中注册的回调函数的执行顺序是宏任务先执行,微任务后执行。
二、nextTick()
1.定义及理解:
在下次 DOM 更新循环结束之后执行延迟回调(this.$nextTick()中的回调函数)。nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数。
2.$nextTick(callback) 使用原理:
Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 当中观察到数据变化的 watcher 推送进这个队列。如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和DOm操作。而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。
当你设置 改变了一个新数据data,DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的DOM更新。如果此时你想要根据更新的 DOM 状态去做某些事情,就会出现问题。。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
三、防抖、节流、高阶组件
1、防抖
// 防抖?
// 核心:触发一次创建一个定时器,但是在创建前要进行判断
export function high(fn, time) {//参数一个是函数,一个是定时器的时间;这是高阶函数的特点
var timer = null
return function () {
if (timer) {//触发事件处理函数后,进行判断,是否有定时器打开,如果有定时器就先关闭掉上一次的定时器,然后在重新创建一个定时器
clearTimeout(timer)
}
timer = setTimeout(() => {
fn()
}, time)
}
}
2、节流
// 节流?
// 核心:在规定时间内,只创建一个定时器
export function high(fn, time) {
var timer = null
return function () {
if (!timer) {//创建定时器前进行判断,看是否需要进行创建,当timer=null时,就创建,如果不为空,就不执行任何操作,等待定时器执行完毕后,将定时器关掉,并将timer重新设置为null
timer = setTimeout(() => {
fn()
clearTimeout(timer)
timer = null
}, time)
}
}
}
3、高阶组件(多个div自由拖拽)
// 高阶组件
// 核心:封装一个函数,return出一个class组件
export function highcom(Com) {
return class highcom extends Component {
constructor(props) {
super(props)
this.state = {
top: 30, left: 30
}
}
mousedown() {
document.onmousemove = (e) => {
this.setState({ top: e.clientY, left: e.clientX })
}
document.onmouseup = () => {
document.onmousemove = null
}
}
render() {
return (
<div style={{ position: 'absolute', top: this.state.top + 'px', left: this.state.left + 'px' }} onMouseDown={() => {
this.mousedown()
}}>
<Com />
</div>
);
}
}
}