# 动态组件、异步组件  
小常识:

**动态组件** 之前在个多标签的界面中我们通过 is attribute 来切换不同的组件: ```javascript ``` 当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重新渲染导致的性能问题。 重新创建动态组件的行为通常是非常有用的,在一些案例中,我们更希望那些标签的组件实例能够被在它们第一次被创建的时候缓存下来。为了解决这个问题,我们可以用一个 `` 元素将其动态组件包裹起来。 ```javascript ``` 注意这个 `` 要求被切换到的组件都有自己的名字,不论是通过组件的 name 选项还是局部/全局注册。 **异步组件** 在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。例如: ```javascript Vue.component('async-example', function (resolve, reject) { setTimeout(function () { // 向 `resolve` 回调传递组件定义 resolve({ template: '
I am async!
' }) }, 1000) }) ``` 如你所见,这个工厂函数会收到一个 resolve 回调,这个回调函数会在你从服务器得到组件定义的时候被调用。你也可以调用 reject(reason) 来表示加载失败。这里的 setTimeout 是为了演示用的,如何获取组件取决于你自己。一个推荐的做法是将异步组件和 webpack 的 code-splitting 功能一起配合使用: ```javascript Vue.component('async-webpack-example', function (resolve) { // 这个特殊的 `require` 语法将会告诉 webpack // 自动将你的构建代码切割成多个包,这些包 // 会通过 Ajax 请求加载 require(['./my-async-component'], resolve) }) ``` 你也可以在工厂函数中返回一个 Promise,所以把 webpack 2 和 ES2015 语法加在一起,我们可以这样使用动态导入: ```javascript Vue.component( 'async-webpack-example', // 这个动态导入会返回一个 `Promise` 对象。 () => import('./my-async-component') ) 当 ``` 使用局部注册的时候,你也可以直接提供一个返回 Promise 的函数: ```javascript new Vue({ // ... components: { 'my-component': () => import('./my-async-component') } }) ``` 如果你是一个 Browserify 用户同时喜欢使用异步组件,很不幸这个工具的作者明确表示异步加载“并不会被 Browserify 支持”,至少官方不会。Browserify 社区已经找到了一些变通方案,这些方案可能会对已存在的复杂应用有帮助。对于其它的场景,我们推荐直接使用 webpack,以拥有内置的头等异步支持。
小测试:
以下关于动态组件和异步组件的说法不正确的是?

## 答案 Vue 允许我们以一个工厂函数的方式定义组件只能收到一个 resolve 回调,这个回调函数会在你从服务器得到组件定义的时候被调用 ## 选项 ### A 使用动态组件标签的组件实例能够被在它们第一次被创建的时候缓存下来 ### B 动态组件可以保持这些组件的状态,以避免反复重渲染导致的性能问题 ### C 可以在工厂函数中返回一个 Promise