提交 0b44a92e 编写于 作者: Q q759859479

Tue May 28 12:06:00 CST 2024 inscode

上级 79c5bd79
......@@ -5,10 +5,9 @@ import TheWelcome from './components/TheWelcome.vue'
<template>
<header>
<img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />
<div class="wrapper">
<HelloWorld msg="You did it!" />
<HelloWorld msg="没有人比你更懂Event Loop" />
</div>
</header>
......@@ -27,21 +26,4 @@ header {
margin: 0 auto 2rem;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
}
</style>
文件已添加
......@@ -67,7 +67,7 @@ body {
line-height: 1.6;
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
font-size: 15px;
font-size: 16px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
@import "./base.css";
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
background: #FFEFBA; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, #FFFFFF, #FFEFBA); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #FFFFFF, #FFEFBA); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
a,
......@@ -21,15 +23,112 @@ a,
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
.code {
padding: 6px;
background: rgba(0,0,0,.7);
color: #fff;
border-radius: 6px;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
.tc {
text-align: center;
}
.flex {
display: flex;
}
.flex-vcenter {
display: flex;
align-items: center;
}
.flex-1 {
flex: 1;
}
.flex-column {
display: flex;
flex-direction: column;
}
.text-left {
text-align: left !important;
}
.text-right {
text-align: right !important;
}
.text-justify {
text-align-last: justify !important;
}
.text-center {
text-align: center !important;
}
button {
background: #68caad;
border: none;
padding: 2px 6px;
color: #fff;
border-radius: 4px;
cursor: pointer;
transition: .3s;
border: 1px solid #68caad;
}
button:hover {
box-shadow: 0px 0px 3px 1px rgba(0,0,0,.3);
}
.fs-13 {
font-size: 13px;
}
.fs-12 {
font-size: 12px;
}
.ml-5 {
margin-left: 5px;
}
.default-btn {
background: #fff;
color: #68caad;
border: 1px solid #68caad;
}
p {
padding: 4px 0;
}
.ft-b {
font-weight: bold;
}
.title {
font-weight: bold;
}
table {
border-right: 1px solid #ccc;
border-top: 1px solid #ccc;
}
th {
padding: 0 6px;
border-left: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #eee;
font-weight: bold;
}
td {
padding: 0 6px;
border-left: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
\ No newline at end of file
文件已添加
<svg t="1716865647700" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5715" width="44" height="44"><path d="M510.6 513.8m-409.2 0a409.2 409.2 0 1 0 818.4 0 409.2 409.2 0 1 0-818.4 0Z" fill="#F9C56A" p-id="5716"></path><path d="M533.7 490.7m-386.1 0a386.1 386.1 0 1 0 772.2 0 386.1 386.1 0 1 0-772.2 0Z" fill="#FAE06B" p-id="5717"></path><path d="M511.5 69C265.9 69 66.7 268.1 66.7 513.8s199.2 444.8 444.8 444.8 444.8-199.2 444.8-444.8S757.2 69 511.5 69z m0 854c-226 0-409.2-183.2-409.2-409.2s183.2-409.2 409.2-409.2 409.2 183.2 409.2 409.2S737.5 923 511.5 923z" fill="#793A08" p-id="5718"></path><path d="M672 898l-50-300a76.2 76.2 0 0 0-76-76h-72a76.2 76.2 0 0 0-76 76l-50 299s57 33 162.6 33C619 930 672 898 672 898z" fill="#DF4F29" p-id="5719"></path><path d="M510.6 938c-106.5 0-164.2-32.7-166.6-34l-4.8-2.8L390 597.3a84.1 84.1 0 0 1 84-83.3h72a84.1 84.1 0 0 1 84 83.3L680.8 902l-4.7 2.8c-2.2 1.4-56.1 33.2-165.5 33.2z m-153.7-45.5c15.6 7.5 68.8 29.5 153.7 29.5 87.2 0 137.7-21 152.6-28.3l-49.2-295v-0.7a68.1 68.1 0 0 0-68-68h-72a68.1 68.1 0 0 0-68 68v1.3z" fill="#793A08" p-id="5720"></path><path d="M878.2 560.9a35.6 35.6 0 0 0-71.1 0M216.6 560a35.6 35.6 0 0 0-71.1 0z" fill="#FBA783" p-id="5721"></path><path d="M274 434m-65 0a65 65 0 1 0 130 0 65 65 0 1 0-130 0Z" fill="#FFFFFF" p-id="5722"></path><path d="M274 506a72 72 0 1 1 72-72 72.1 72.1 0 0 1-72 72z m0-130a58 58 0 1 0 58 58 58.1 58.1 0 0 0-58-58z" fill="#793A08" p-id="5723"></path><path d="M755 435m-65 0a65 65 0 1 0 130 0 65 65 0 1 0-130 0Z" fill="#FFFFFF" p-id="5724"></path><path d="M755 507a72 72 0 1 1 72-72 72.1 72.1 0 0 1-72 72z m0-130a58 58 0 1 0 58 58 58.1 58.1 0 0 0-58-58z" fill="#793A08" p-id="5725"></path><path d="M524 240l15 0 0 74-15 0 0-74Z" fill="#5E2B03" p-id="5726"></path><path d="M484 241l15 0 0 45-15 0 0-45Z" fill="#5E2B03" p-id="5727"></path><path d="M142.689991 174.280407l264.798987 108.062465-12.468746 30.55373-264.798987-108.062465 12.468746-30.55373Z" fill="#793A08" p-id="5728"></path><path d="M899.641688 205.132098l-264.798987 108.062465-12.468746-30.55373 264.798987-108.062465 12.468746 30.55373Z" fill="#793A08" p-id="5729"></path></svg>
\ No newline at end of file
......@@ -10,34 +10,16 @@ defineProps({
<template>
<div class="greetings">
<h1 class="green">{{ msg }}</h1>
<h3>
You’ve successfully created a project with
<a target="_blank" href="https://vitejs.dev/">Vite</a> +
<a target="_blank" href="https://vuejs.org/">Vue 3</a>.
</h3>
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
font-size: 3rem;
top: -10px;
}
h3 {
font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
@media (min-width: 1024px) {
.greetings h1,
.greetings h3 {
text-align: left;
}
text-shadow: 5px 5px 4px #666;
letter-spacing: 6px;
}
</style>
<script setup>
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
import {ref} from 'vue'
let log1 = ref([]);
const test1 = () => {
log1.value = []
setTimeout(() => {
log1.value.push('定时器开始啦')
});
new Promise(function(resolve){
log1.value.push('马上执行for循环啦')
for(var i = 0; i < 10000; i++){
i === 99 && resolve();
}
}).then(function(){
log1.value.push('执行then函数啦')
});
log1.value.push('代码执行结束')
}
</script>
<template>
<WelcomeItem>
<template #icon>
<DocumentationIcon />
</template>
<template #heading>Documentation</template>
Vue’s
<a target="_blank" href="https://vuejs.org/">official documentation</a>
provides you with all information you need to get started.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<ToolingIcon />
</template>
<template #heading>Tooling</template>
This project is served and bundled with
<a href="https://vitejs.dev/guide/features.html" target="_blank">Vite</a>. The recommended IDE
setup is <a href="https://code.visualstudio.com/" target="_blank">VSCode</a> +
<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>. If you need to test
your components and web pages, check out
<a href="https://www.cypress.io/" target="_blank">Cypress</a> and
<a href="https://on.cypress.io/component" target="_blank"
>Cypress Component Testing</a
>.
<br />
More instructions are available in <code>README.md</code>.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<EcosystemIcon />
</template>
<template #heading>Ecosystem</template>
Get official tools and libraries for your project:
<a target="_blank" href="https://pinia.vuejs.org/">Pinia</a>,
<a target="_blank" href="https://router.vuejs.org/">Vue Router</a>,
<a target="_blank" href="https://test-utils.vuejs.org/">Vue Test Utils</a>, and
<a target="_blank" href="https://github.com/vuejs/devtools">Vue Dev Tools</a>. If you need more
resources, we suggest paying
<a target="_blank" href="https://github.com/vuejs/awesome-vue">Awesome Vue</a>
a visit.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<CommunityIcon />
</template>
<template #heading>Community</template>
Got stuck? Ask your question on
<a target="_blank" href="https://chat.vuejs.org">Vue Land</a>, our official Discord server, or
<a target="_blank" href="https://stackoverflow.com/questions/tagged/vue.js">StackOverflow</a>.
You should also subscribe to
<a target="_blank" href="https://news.vuejs.org">our mailing list</a> and follow the official
<a target="_blank" href="https://twitter.com/vuejs">@vuejs</a>
twitter account for latest news in the Vue world.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<SupportIcon />
</template>
<template #heading>Support Vue</template>
As an independent project, Vue relies on community backing for its sustainability. You can help
us by
<a target="_blank" href="https://vuejs.org/sponsor/">becoming a sponsor</a>.
</WelcomeItem>
<div>
<p>正常我们了解到:js是一门单线程语言,js是按照语句的顺序从上到下按顺序执行的,比如:</p>
<pre class="code">
let a = '1';
console.log(a);
let b = '2';
console.log(b);
</pre>
<p>打印结果顺序是:1、2</p>
<br>
<p>再看下面一段代码</p>
<pre class="code">
setTimeout(function(){
console.log('定时器开始啦')
});
new Promise(function(resolve){
console.log('马上执行for循环啦');
for(var i = 0; i < 10000; i++){
i === 99 && resolve();
}
}).then(function(){
console.log('执行then函数啦')
});
console.log('代码执行结束');
</pre>
<br>
<p>依照js是按照语句出现的顺序执行这个理念,自信的写下输出结果:</p>
<pre class="code">
定时器开始啦
马上执行for循环啦
执行then函数啦
代码执行结束
</pre>
<br>
<p>实际验证下:
<button class="default-btn" @click="log1 = []">重置 </button>
<button class="ml-5" @click="test1">执行 </button>
<i class="fs-12 ml-5">请狠狠点击执行</i></p>
<p>结果:</p>
<div class="code" v-if="log1.length">
<p v-for="(item, index) of log1" :key="index">{{ item }}</p>
</div>
<p class="flex-vcenter" v-if="log1.length">完全不对啊,瞬间懵了,说好的一行一行执行的呢?<img src="../assets/zj.svg" alt=""></p>
<p>别着急,这背后就涉及到javascript的执行机制了,容我为你一一道来</p>
<br>
<h3 class="title">1.首先,javascript是单线程语言,在最新的HTML5中提出了Web-Worker,但javascript是单线程这一核心仍未改变</h3>
<h3 class="title">2.javascript事件循环</h3>
<div class="content">
既然js是单线程,那就像只有一个窗口的银行,客户需要排队一个一个办理业务,同理js任务也要一个一个顺序执行。如果一个任务耗时过长,那么后一个任务也必须等着。那么问题来了,假如我们想浏览新闻,但是新闻包含的超清图片加载很慢,难道我们的网页要一直卡着直到图片完全显示出来?因此聪明的程序员将任务分为两类:
<p>1、同步任务</p>
<p>2、异步任务</p>
<p>当我们打开网站时,网页的渲染过程就是一大堆同步任务,比如页面骨架和页面元素的渲染。而像加载图片音乐之类占用资源大耗时久的任务,就是异步任务。关于这部分有严格的文字定义,但本文的目的是用最小的学习成本彻底弄懂执行机制,所以我们用导图来说明:</p>
<div>
<img width="800" src="../assets/qqq.awebp" alt="">
</div>
<br>
<div>导图要表达的内容用文字来表述的话:</div>
</div>
<div >
<ul>
<li>同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。</li>
<li>当指定的事情完成时,Event Table会将这个函数移入Event Queue。</li>
<li>主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。</li>
<li>上述过程会不断重复,也就是常说的Event Loop(事件循环)。</li>
</ul>
</div>
<br>
<div class="content">
我们不禁要问了,那怎么知道主线程执行栈为空啊?js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。
<p>说了这么多文字,不如直接一段代码更直白:</p>
</div>
<div>
<pre class="code">
let data = [];
$.ajax({
url:www.javascript.com,
data:data,
success:() => {
console.log('发送成功!');
}
})
console.log('代码执行结束');
</pre>
<div>
上面是一段简易的ajax请求代码:
<ul>
<li>ajax进入Event Table,注册回调函数success。</li>
<li>执行console.log('代码执行结束')。</li>
<li>ajax事件完成,回调函数success进入Event Queue。</li>
<li>主线程从Event Queue读取回调函数success并执行。</li>
</ul>
<p>
相信通过上面的文字和代码,你已经对js的执行顺序有了初步了解。接下来我们来研究进阶话题:setTimeout。</p>
</div>
</div>
<br>
<h3 class="title">3.setTimeout</h3>
<div class="content">
大名鼎鼎的setTimeout无需再多言,大家对他的第一印象就是异步可以延时执行,我们经常这么实现延时3秒执行:
</div>
<pre class="code">
setTimeout(() => {
console.log('延时3秒');
},3000)</pre>
<p>渐渐的setTimeout用的地方多了,问题也出现了,有时候明明写的延时3秒,实际却5,6秒才执行函数,这又咋回事啊?</p>
<p>先看一个例子:</p>
<pre class="code">
setTimeout(() => {
task();
},3000)
console.log('执行console');
</pre>
<p>根据前面我们的结论,setTimeout是异步的,应该先执行console.log这个同步任务,所以我们的结论是:</p>
<pre class="code">
//执行console
//task()
</pre>
<p>去验证一下,结果正确! 然后我们修改一下前面的代码:</p>
<pre class="code">
setTimeout(() => {
task()
},3000)
sleep(10000000)
</pre>
<p>乍一看其实差不多嘛,但我们把这段代码在chrome执行一下,却发现控制台执行task()需要的时间远远超过3秒,说好的延时三秒,为啥现在需要这么长时间啊?</p>
<p>这时候我们需要重新理解setTimeout的定义。我们先说上述代码是怎么执行的:</p>
<ul>
<li>task()进入Event Table并注册,计时开始。</li>
<li>执行sleep函数,很慢,非常慢,计时仍在继续。</li>
<li>3秒到了,计时事件timeout完成,task()进入Event Queue,但是sleep也太慢了吧,还没执行完,只好等着。</li>
<li>sleep终于执行完了,task()终于从Event Queue进入了主线程执行。</li>
</ul>
<p>上述的流程走完,我们知道setTimeout这个函数,是经过指定时间后,把要执行的任务(本例中为task())加入到Event Queue中,又因为是单线程任务要一个一个执行,如果前面的任务需要的时间太久,那么只能等着,导致真正的延迟时间远远大于3秒。</p>
<br>
<p>
我们还经常遇到setTimeout(fn,0)这样的代码,0秒后执行又是什么意思呢?是不是可以立即执行呢?
</p>
<p>
答案是不会的,setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,意思就是不用再等多少秒了,只要主线程执行栈内的同步任务全部执行完成,栈为空就马上执行。举例说明:
</p>
<pre class="code">
//代码1
console.log('先执行这里');
setTimeout(() => {
console.log('执行啦')
},0);
</pre>
<pre class="code">
//代码2
console.log('先执行这里');
setTimeout(() => {
console.log('执行啦')
},3000);
</pre>
<p>代码1的输出结果是:</p>
<pre class="code">
//先执行这里
//执行啦
</pre>
代码2的输出结果是:
<pre class="code">
//先执行这里
// ... 3s later
// 执行啦</pre>
<p>关于setTimeout要补充的是,即便主线程为空,0毫秒实际上也是达不到的。根据HTML的标准,最低是4毫秒。有兴趣的同学可以自行了解。</p>
<br>
<h3 class="title">4.setInterval</h3>
<p>
上面说完了setTimeout,当然不能错过它的孪生兄弟setInterval。他俩差不多,只不过后者是循环的执行。对于执行顺序来说,setInterval会每隔指定的时间将注册的函数置入Event Queue,如果前面的任务耗时太久,那么同样需要等待。
</p>
<p>
唯一需要注意的一点是,对于setInterval(fn,ms)来说,我们已经知道不是每过ms秒会执行一次fn,而是每过ms秒,会有fn进入Event Queue。一旦setInterval的回调函数fn执行时间超过了延迟时间ms,那么就完全看不出来有时间间隔了。这句话请读者仔细品味。
</p>
<br>
<h3 class="title">5.Promise与process.nextTick(callback)</h3>
<p>传统的定时器我们已经研究过了,接着我们探究Promise与process.nextTick(callback)的表现。</p>
<p>Promise的定义和功能本文不再赘述,不了解的读者可以学习一下阮一峰老师的Promise。而process.nextTick(callback)类似node.js版的"setTimeout",在事件循环的下一次循环中调用 callback 回调函数。</p>
<p>我们进入正题,除了广义的同步任务和异步任务,我们对任务有更精细的定义:</p>
<ul>
<li>macro-task(宏任务):包括整体代码script,setTimeout,setInterval</li>
<li>micro-task(微任务):Promise,process.nextTick</li>
</ul>
<p>不同类型的任务会进入对应的Event Queue,比如setTimeout和setInterval会进入相同的Event Queue。</p>
<p>事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。听起来有点绕,我们用文章最开始的一段代码说明:</p>
<pre class="code">
setTimeout(function() {
console.log('setTimeout');
})
new Promise(function(resolve) {
console.log('promise');
}).then(function() {
console.log('then');
})
console.log('console');
</pre>
<ul>
<li>这段代码作为宏任务,进入主线程。</li>
<li>先遇到setTimeout,那么将其回调函数注册后分发到宏任务Event Queue。(注册过程与上同,下文不再描述)</li>
<li>接下来遇到了Promise,new Promise立即执行,then函数分发到微任务Event Queue。</li>
<li>遇到console.log(),立即执行。</li>
<li>好啦,整体代码script作为第一个宏任务执行结束,看看有哪些微任务?我们发现了then在微任务Event Queue里面,执行。</li>
<li>ok,第一轮事件循环结束了,我们开始第二轮循环,当然要从宏任务Event Queue开始。我们发现了宏任务Event Queue中setTimeout对应的回调函数,立即执行。</li>
<li>结束。</li>
</ul>
<br>
<p>事件循环,宏任务,微任务的关系如图所示:</p>
<div>
<img src="../assets/222.awebp" width="800" alt="">
</div>
<br>
<p>我们来分析一段较复杂的代码,看看你是否真的掌握了js的执行机制:</p>
<pre class="code">
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
</pre>
<br>
<p>第一轮事件循环流程分析如下:</p>
<ul>
<li>整体script作为第一个宏任务进入主线程,遇到console.log,输出1。</li>
<li>遇到setTimeout,其回调函数被分发到宏任务Event Queue中。我们暂且记为setTimeout1。</li>
<li>遇到process.nextTick(),其回调函数被分发到微任务Event Queue中。我们记为process1。</li>
<li>遇到Promise,new Promise直接执行,输出7。then被分发到微任务Event Queue中。我们记为then1。</li>
<li>又遇到了setTimeout,其回调函数被分发到宏任务Event Queue中,我们记为setTimeout2。</li>
</ul>
<br>
<table>
<thead>
<th>宏任务Event Queue</th>
<th>微任务Event Queue</th>
</thead>
<tbody>
<tr>
<td>setTimeout1</td>
<td>process1</td>
</tr>
<tr>
<td>setTimeout2</td>
<td>then1</td>
</tr>
</tbody>
</table>
<br>
<ul>
<li>上表是第一轮事件循环宏任务结束时各Event Queue的情况,此时已经输出了1和7。</li>
<li>我们发现了process1和then1两个微任务。</li>
<li>执行process1,输出6。</li>
<li>执行then1,输出8。</li>
</ul>
<p>好了,第一轮事件循环正式结束,这一轮的结果是输出1,7,6,8。那么第二轮时间循环从setTimeout1宏任务开始:</p>
<ul>
<li>首先输出2。接下来遇到了process.nextTick(),同样将其分发到微任务Event Queue中,记为process2。new Promise立即执行输出4,then也分发到微任务Event Queue中,记为then2。</li>
</ul>
<br>
<table>
<thead>
<th>宏任务Event Queue</th>
<th>微任务Event Queue</th>
</thead>
<tbody>
<tr>
<td>setTimeout2</td>
<td>process2</td>
</tr>
<tr>
<td></td>
<td>then2</td>
</tr>
</tbody>
</table>
<br>
<ul>
<li>第二轮事件循环宏任务结束,我们发现有process2和then2两个微任务可以执行。</li>
<li>输出3。</li>
<li>输出5</li>
<li>第二轮事件循环结束,第二轮输出2,4,3,5。</li>
<li>第三轮事件循环开始,此时只剩setTimeout2了,执行。</li>
<li>直接输出9。</li>
<li>将process.nextTick()分发到微任务Event Queue中。记为process3。
</li>
<li>直接执行new Promise,输出11。</li>
<li>将then分发到微任务Event Queue中,记为then3。</li>
<li>
<table>
<thead>
<th>宏任务Event Queue</th>
<th>微任务Event Queue</th>
</thead>
<tbody>
<tr>
<td></td>
<td>process3</td>
</tr>
<tr>
<td></td>
<td>then3</td>
</tr>
</tbody>
</table>
</li>
<li>第三轮事件循环宏任务执行结束,执行两个微任务process3和then3。</li>
<li>输出10</li>
<li>输出12。</li>
<li>第三轮事件循环结束,第三轮输出9,11,10,12。</li>
</ul>
<p>整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。 (请注意,node环境下的事件监听依赖libuv与前端环境不完全相同,输出顺序可能会有误差)</p>
<br>
<h3 class="title">6.写在最后</h3>
<p>从event loop规范探究javaScript异步及浏览器更新渲染时机 </p>
<ul>
<li>在一轮event loop中多次修改同一dom,只有最后一次会进行绘制。</li>
<li>渲染更新(Update the rendering)会在event loop中的tasks和microtasks完成后进行,但并不是每轮event loop都会更新渲染,这取决于是否修改了dom和浏览器觉得是否有必要在此时立即将新状态呈现给用户。如果在一帧的时间内(时间并不确定,因为浏览器每秒的帧数总在波动,16.7ms只是估算并不准确)修改了多处dom,浏览器可能将变动积攒起来,只进行一次绘制,这是合理的。</li>
<li>如果希望在每轮event loop都即时呈现变动,可以使用requestAnimationFrame。</li>
</ul>
<p class="title">拓展思考, Vue.nextTick原理</p>
</div>
</template>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册