Close
升级到 Vue 3 | Vue 2 EOL

动态与异步组件

本页假设您已阅读 组件基础。如果您是组件新手,请先阅读它。

keep-alive 与动态组件

之前,我们使用 is 属性在选项卡界面中切换组件

<component v-bind:is="currentTabComponent"></component>

但是,在这些组件之间切换时,您有时可能希望保持它们的状态或出于性能原因避免重新渲染。例如,当我们稍微扩展选项卡界面时

您会注意到,如果您选择了一篇文章,切换到“存档”选项卡,然后切换回“文章”,它不再显示您选择的文章。这是因为每次您切换到新选项卡时,Vue 都会创建一个新的 currentTabComponent 实例。

重新创建动态组件通常是有用的行为,但在这种情况下,我们确实希望这些选项卡组件实例在首次创建后被缓存。为了解决这个问题,我们可以用 <keep-alive> 元素包装我们的动态组件

<!-- Inactive components will be cached! -->
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>

查看下面的结果

现在,“文章”选项卡即使在未渲染时也能保持其状态(所选文章)。查看 此示例以获取完整代码。

请注意,<keep-alive> 要求要切换的组件都具有名称,无论是使用组件上的 name 选项,还是通过本地/全局注册。

API 参考 中查看有关 <keep-alive> 的更多详细信息。

异步组件

在大型应用程序中,我们可能需要将应用程序划分为更小的块,并且仅在需要时从服务器加载组件。为了使这更容易,Vue 允许您将组件定义为异步解析组件定义的工厂函数。Vue 仅在需要渲染组件时才会触发工厂函数,并且会缓存结果以供将来重新渲染。例如

Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// Pass the component definition to the resolve callback
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})

如您所见,工厂函数接收一个 resolve 回调函数,当您从服务器检索到组件定义时应调用该函数。您还可以调用 reject(reason) 来指示加载失败。这里的 setTimeout 用于演示;如何检索组件取决于您。一种推荐的方法是将异步组件与 Webpack 的代码拆分功能 结合使用

Vue.component('async-webpack-example', function (resolve) {
// This special require syntax will instruct Webpack to
// automatically split your built code into bundles which
// are loaded over Ajax requests.
require(['./my-async-component'], resolve)
})

您也可以在工厂函数中返回一个 Promise,因此使用 Webpack 2 和 ES2015 语法,您可以利用动态导入

Vue.component(
'async-webpack-example',
// A dynamic import returns a Promise.
() => import('./my-async-component')
)

当使用 本地注册 时,您也可以直接提供一个返回 Promise 的函数

new Vue({
// ...
components: {
'my-component': () => import('./my-async-component')
}
})

如果您是希望使用异步组件的 Browserify 用户,它的创建者不幸地 明确表示 异步加载“不是 Browserify 将永远支持的东西”。至少在官方上是这样。Browserify 社区已经找到了 一些解决方法,这可能对现有和复杂的应用程序有所帮助。对于所有其他场景,我们建议使用 Webpack 来获得内置的一流异步支持。

处理加载状态

2.3.0+ 中的新功能

异步组件工厂还可以返回以下格式的对象

const AsyncComponent = () => ({
// The component to load (should be a Promise)
component: import('./MyComponent.vue'),
// A component to use while the async component is loading
loading: LoadingComponent,
// A component to use if the load fails
error: ErrorComponent,
// Delay before showing the loading component. Default: 200ms.
delay: 200,
// The error component will be displayed if a timeout is
// provided and exceeded. Default: Infinity.
timeout: 3000
})

请注意,如果您希望对路由组件使用上述语法,则必须使用 Vue Router 2.4.0+。