有一说一,上一篇写到关于响应性的问题,该部分内容拿到这边整理难度较大,所以还是遵循顺序,先整理简单地部分,之后再整合起来。
在动态组件上使用keep-alive
来看一个例子:
我们之前曾经在一个多标签的界面中使用 is
attribute 来切换不同的组件:
<component :is="currentTabComponent"></component>
当这些组件在切换的时候,我们有时候会希望能够保存该组件的状态,从而避免因为反复渲染而导致的性能问题。看一下官网的这个例子:
这个例子简单,通过点击上面的按钮切换到不同的组件,大可自行尝试。不难发现,当我们选择Posts按钮后选择了一篇文章,随后点击Archive按钮,再点击Posts回到刚才的页面时,没有展示我们之前选择的文章。
原因很简单,因为每次切换标签的时候,Vue都是创建了一个新的currentTabComponent
实例。
重新创建动态组件的行为通常是非常有用的,可是在上述这种情形,我们希望的是保存刚刚选择的文章界面,也就是希望这个组件实例能够在第一次创建的时候缓存下来,不要再重新创建新的实例。所以这边使用了一个<keep-alive>
元素将动态组件进行包裹。
<!-- 失活的组件将会被缓存!-->
<keep-alive>
<component :is="currentTabComponent"></component>
</keep-alive>
通过这种方法,我们的目的得到实现,Posts标签内容保持了它的状态,也就是被选中的状态。
分析:从个人理解的角度来看,<keep-alive>
这一标签使得我们的动态组件的状态得以保存,还是说缓存下来更为恰当。在某些特殊情形下这个标签可以减少因重复创建组件而造成的性能降低问题。同时在用户体验上也得到了保证。
异步组件
直接来看官网给的例子:
在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 有一个 defineAsyncComponent
方法:
const { createApp, defineAsyncComponent } = Vue
const app = createApp({})
const AsyncComp = defineAsyncComponent(
() =>
new Promise((resolve, reject) => {
resolve({
template: ‘<div>I am async!</div>‘
})
})
)
app.component(‘async-example‘, AsyncComp)
如你所见,此方法接受返回 Promise
的工厂函数。从服务器检索组件定义后,应调用 Promise 的 resolve
回调。你也可以调用 reject(reason)
,来表示加载失败。
你也可以在工厂函数中返回一个 Promise
,把 webpack 2 和 ES2015 语法相结合后,我们就可以这样使用动态地导入:
import { defineAsyncComponent } from ‘vue‘
const AsyncComp = defineAsyncComponent(() =>
import(‘./components/AsyncComponent.vue‘)
)
app.component(‘async-component‘, AsyncComp)
当在局部注册组件时,你也可以使用 defineAsyncComponent
import { createApp, defineAsyncComponent } from ‘vue‘
createApp({
// ...
components: {
AsyncComponent: defineAsyncComponent(() =>
import(‘./components/AsyncComponent.vue‘)
)
}
})
通过这种方法,我们的组件就会被定义成异步组件,也就是在需要加载的时候才去加载这个组件。
参考资料
[1] defineAsyncComponent方法.
[2] 动态组件&异步组件.
[3] Promise.