console.log(1);
setTimeout(function () {
console.log(2);
}, 0);
new Promise((resolve) => {
console.log(3);
resolve();
}).then(() => {
console.log(4);
});
console.log(5);
1 3 5 4 2
通过 console.log
知道它们的输出顺序:
- 首先,代码执行到
console.log(1)
,输出1
。 - 接着,进入异步事件队列,执行
setTimeout
,将回调函数压到异步事件队列末尾,因为定时器时间是 0,所以其实现是非常快的,不会阻塞线程。回调函数是异步执行的,不会阻塞后续代码的执行。所以,往后的同步代码可以继续执行。 - 然后,遇到
Promise
,输出3
。 - 执行
resolve()
,由于resolve
函数是异步调用的,所以会将then
方法中的回调函数加入到微队列的末尾,等待同步代码执行完后依次执行,这就是Promise
解决回调地狱的本质原因。 - 然后,执行
console.log(5)
,输出5
。 - 此时执行完后续同步任务,先去微任务队列里面查看是否有任务,发现了
Promise.then()
中的回调函数,输出4
。 - 最后,到达异步事件队列的末尾,执行
setTimeout
的回调函数,输出2
。
综上所述,这段代码的输出顺序是 1 -> 3 -> 5 -> 4 -> 2
。
如果没有resolve();的执行结果是什么?
如果没有执行 resolve()
,则 Promise
对象一直处于未决状态,不会将回调函数加入到微队列中。因此,输出结果将不会包含回调函数中的内容,即
1
3
5
2
其中,第 4 个 console.log()
语句不会执行,因为 Promise
的 then()
方法没有被调用。
KeepAlive
KeepAlive
是 Vue.js 内置组件,主要用于优化应用程序的性能和交互体验,它可以将不需要销毁的组件缓存起来,以便下次访问时能够快速呈现,有效减少渲染和加载的时间,提高应用性能。
当 KeepAlive
包裹的组件被缓存时,其生命周期钩子函数将会发生以下变化:
- 当组件被离开时,它的
beforeUnmounted()
钩子函数会被调用,然后它被缓存。 - 如果缓存被激活,缓存的组件会被重新挂载,并且可以通过
activated()
钩子函数被激活。 - 如果缓存被销毁,则
deactivated()
钩子函数会被执行。
<template>
<div>
<KeepAlive>
<router-view />
</KeepAlive>
</div>
</template>
<template>
<div>
<KeepAlive :include="'Home'">
<router-view />
</KeepAlive>
</div>
</template>
vue的组件(页面)有自己的生命周期,比如create创建组件、mounted往组件上挂数据、update更新组件上挂的数据,destroy把组件实例销毁。
// #App.vue中
<template>
<div class="box">
<!-- 路由导航 -->
<div class="nav">
<router-link to="/">去home页面</router-link>
<router-link to="/about">去about页面</router-link>
<router-link to="/detail">去detail页面</router-link>
</div>
<!-- 路由导航对应的内容区 -->
<main>
<router-view></router-view>
</main>
</div>
</template>
// home.vue中,放置一个复选框
<el-checkbox v-model="checked">备选项</el-checkbox>
// about.vue中,放置一个输入框
<el-input v-model="input" placeholder="请输入内容"></el-input>
// detail.vue中方式一个下拉框
<el-select v-model="value" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
<template>
<div class="box">
<!-- 路由导航 -->
<div class="nav">
<router-link to="/">去home页面</router-link>
<router-link to="/about">去about页面</router-link>
<router-link to="/detail">去detail页面</router-link>
</div>
<!-- 路由导航对应的内容区 -->
<main>
<keep-alive> <!-- 使用keep-alive包了一层,就可以缓存啦 -->
<router-view></router-view>
</keep-alive>
</main>
</div>
</template>
使用keep-alive包住以后,我们发现,我们勾选、输入、下拉选择的内容,在路由来回切换的时候,就不会丢失了,即使用keep-alive保存了之前的组件状态
keep-alive的应用场景:如
查看表格某条数据详情页,返回还是之前的状态,比如还是之前的筛选结果,还是之前的页数等
填写的表单的内容路由跳转返回还在,比如input框、下选择拉框、开关切换等用户输入了一大把东西,跳转再回来不能清空啊,不能让用户再写一遍啊,
- 可以使用
exclude
属性为KeepAlive
排除一些不需要缓存的组件,或者使用max
属性控制最大缓存组件数量,默认值为Infinity
。
<template>
<div>
<KeepAlive :include="'Home'" :exclude="'About'" :max="5">
<router-view />
</KeepAlive>
</div>
</template>
- 在缓存的组件中可以通过
activated
和deactivated
钩子函数执行一些特定的逻辑。
<template>
<div>
<h1>Home Component</h1>
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
name: 'Home',
activated() {
console.log('Home Component activated')
},
deactivated() {
console.log('Home Component deactivated')
},
data() {
return {
message: 'Hello World!'
}
}
}
</script>
另外,还有一些需要注意的点:
-
每一个缓存的组件都必须有一个唯一的
name
属性。 -
任何有状态的组件都不能被缓存,因为这些组件内部的数据会因为其内部状态的变化而变化。
-
如果缓存组件与路由共用同一个组件名称,需要在路由的
meta
字段中为缓存和非缓存组件分别设置keepAlive
属性。
const router = new VueRouter({
routes: [
{
path: '/home',
name: 'Home',
component: Home,
meta: {
keepAlive: true // 缓存组件
}
},
{
path: '/about',
name: 'About',
component: About
}
]
})
Teleport
Teleport
是 Vue.js 3.0 新增的一个组件,它可以让开发者在组件树之外的任何地方渲染一个组件,而不需要在组件的父组件中嵌套完整的模板。使用 Teleport
组件可以轻松实现一些复杂的场景,例如弹出框、对话框、下拉菜单等。
Teleport
的主要作用是将指定的内容渲染到指定的出口(即 <Teleport>
的 to
属性),从而实现在 DOM 结构中跨越组件边界的渲染,它可以将内容渲染到 DOM 中任何一个有效的位置,而不必依赖于父组件的位置或者组件层次结构。
使用 Teleport
的示例代码如下:
<template>
<div>
<button @click="showDialog = true">Show Dialog</button>
<Teleport to="body">
<div v-if="showDialog">
<h1>Dialog Title</h1>
<p>Dialog Content</p>
<button @click="showDialog = false">Close</button>
</div>
</Teleport>
</div>
</template>
<script>
export default {
data() {
return {
showDialog: false
}
}
}
</script>
在上述示例中,当用户点击按钮时,条件渲染的 div
元素会被 Teleport 渲染到 body
元素以外的一个容器中,所以不会被原有的 div
容器包含,从而实现了弹出框的功能。
需要注意的是,在使用 Teleport
进行渲染时,目标容器必须存在于 DOM 中,否则渲染将失败。此外,当一个组件被多次渲染到多个位置时,应该通过指定 key
值来确保不同渲染之间的独立性。与 keep-alive
进行缓存相似,Teleport
可以通过使用 disabled
属性来实现临时禁用,或使用 fallback
属性来提供备用的渲染方式,以确保组件使用的安全性和可靠性。