最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • ⒓ Vue的动态组件 & 异步组件

    正文概述 掘金(CRMEB技术团队)   2021-01-12   372

    什么是动态组件?

    还是发挥一下语文阅读理解能力,动态组件,应该指的就是动态变化的组件,而不是固定写死的,不知道我的理解准不准确,来想看看官方的解释!

    这段话有点抽象,但是我们可以大胆的猜测一下,应该意思是通过 <component :is="componentId"></component> 提前定义一个区块,然后注册组件的时候动态注册绑定,到底是不是这样呢?

    我们还是老规矩,翠花上代码!

        <div id="app">
            <button @click="onChangeComponentClick(1)">To ComponentA</button>
            <button @click="onChangeComponentClick(2)">To ComponentB</button>
            <button @click="onChangeComponentClick(3)">To ComponentC</button>
            <!-- 声明的区域 -->
            <component :is="componentId"></component>
        </div>
        
        <!-- 定义组件模板内容 -->
        <template id="component-a">
          <div>component-a</div>
        </template>
        
        <template id="component-b">
          <div>component-b</div>
        </template>
        
        <template id="component-c">
          <div>component-c</div>
        </template>
        
        <script type="text/javascript">
          // 注册组件A/B/C
          var commponentA = {
            template: "#component-a"
          }
          
          var commponentB = {
            template: "#component-b"
          }
          
          var commponentC = {
            template: "#component-c"
          }
          
          var vm = new Vue({
            el: "#app",
            data:function(){
              return {
                componentId: commponentA
              }
            },
            
            methods:{
              // 通过一个点击事件传入不同的值,判断动态区块要挂载的组件
              onChangeComponentClick: function(type){
                switch (type) {
                  case 1:
                    this.componentId = commponentA;
                  break;
                  case 2:
                    this.componentId = commponentB;
                  break;
                  case 3:
                    this.componentId = commponentC;
                  break;
                  
                }
              },
            }
          });
          
        </script>
    

    我们看上面的这段代码,首先声明了三个变量 componentAcomponentBcomponentC 并为它们指定了 template,在 new Vue 里面指定了 componentId 初始值为 componentA。然后在 html 里面通过 <component> 声明了一块区域,并通过 :is="componentId" 绑定了 componentId,意为当前的 <component> 将会被 componentId 渲染。此时代码运行之后的结果为:

    <div id="app">
        <div>component-a</div>
    </div>
    

    componentAtemplate 替换掉了通过 <component> 声明的区域。然后通过 onChangeComponentClick 方法来变更 componentId 的指向,当 componentId 的指向发生改变的时候,渲染的内容也随之发生改变。

    这样一种通过 <component> 来声明区域,通过v-bind:is来绑定组件(componentId),然后通过改变组件(componentId)指向来更改展示内容的方式就可以称为动态组件。

    如果亲自运行一下上面的代码,就会发现一个问题,那就是在我们每次去切换 component 的时候,在浏览器的控制台中总会去弹出这么一些内容:

    ⒓ Vue的动态组件 & 异步组件

    这表示当我们每次去切换 component 的时候,模板(component 中的 template)总会去重新渲染,而我们知道每次的 DOM 渲染其实是很消耗性能的操作,那么如果想要避免这样反复渲染的话可以通过 <keep-alive> 标签来告诉 Vue,去缓存已经被渲染过的 component

    <keep-alive> 的使用非常简单,只需要使用 <keep-alive> 来包裹住 <component :is="componentId"></component> 就可以了。代码如下:

    <keep-alive>
        <component :is="componentId"></component>
    </keep-alive>
    

    什么是异步组件?

    举个生活中常见的现象来看什么是异步: 你烧水,不等水烧开就去刷牙了,水烧开了会发出声音告诉你,然后你再处理水烧开之后的事情!看完这个再去理解官方的解释有点豁然开朗了!

    所以,由此可以看出,异步加载最重要的一个功能就是可以加快页面访问速度,比如我们可以把一些非首屏的页面做成异步加载

    定义异步组件

    老规矩翠花,上代码:

      <div id="app">
        <async-example></async-example>
      </div>
      
      <template id="async-example">
        <div>
          我是一个异步组件
        </div>
      </template>
       
      <script type="text/javascript">
        // 注册组件
        var resCom = {
          template: "#async-example"
        }
        
        Vue.component('async-example', function(resolve, reject){
          setTimeout(function(){
            // 向resolve回调传递组件定义
            resolve(resCom);
          }, 1000);
        });
        
        var vm = new Vue({
          el: "#app"
        })
      </script>
        
    

    在上面的这段代码中,首先声明了一个变量 resCom,并给它指定了一个 template 指向 async-example,这和声明局部组件时所进行的操作是一致的。

    然后通过 Vue.component('async-example', function (resolve, reject){} 来创建了一个工厂函数,这个函数包含 resolvereject 两个参数。这两个参数表示两个回调方法,我们可以通过 resolve(resCom) 使程序去异步加载定义的 resCom 组件,也可以使用 reject('加载失败描述内容'); 来表示加载失败。这里的 setTimeout 仅作为模拟异步操作使用的。当然上面的代码也可以通过局部组件的方式使用:

    var vm = new Vue({
        el: '#app',
        components: {
            'async-example': function (resolve, reject) {
                setTimeout(function () {
                    resolve(resCom);
                    // reject('加载失败描述内容');
                }, 1000);
            }
        }
    });
    

    如果大家对 Promise 比较熟悉的话,可以发现这种写法 function (resolve, reject){...} 像极了一个 Promise 的定义(点击这里来查看 Promise 的详细信息)。在 Vue 中一样也可以通过 Promise 的方式来定义异步组件,这也是定义异步组件的第二种方式 Promise。

    把上面的代码略作修改来看:

    // 注册组件
        var resCom = {
          template: "#async-example"
        };
        
        var promise = new Promise(function(resolve, reject){
          setTimeout(function(){
            resolve(resCom)
          }, 1000);
        });
        
        // Vue.component('async-example', function(resolve, reject){
        //   setTimeout(function(){
        //     // 向resolve回调传递组件定义
        //     resolve(resCom);
        //   }, 1000);
        // });
        
        var vm = new Vue({
          el: "#app",
          components:{
            'async-example':function(){
              return promise
            }
          }
        })
    

    在上面的代码中我们声明了一个 Promise,具体的写法与标准方式相同,然后在注册这个异步组件时,直接 return 回这个 Promise 即可。

    我们在前面说过Webpack + Vue-CLI是 Vue 所推崇的一种构建方式,同时 Webpack 也直接内建支持这种 Promise 的异步组件注册方式。当使用 Webpack 来构建正式项目时,我们也可以直接通过 import('./my-async-component') 来注册一个异步组件,import('./my-async-component') 会直接返回一个 Promise。

    // 全局注册
    Vue.component(
      'async-webpack-example',
      // 这个 `import` 函数会返回一个 `Promise` 对象。
      () => import('./my-async-component')
    )
    
    // 局部注册
    new Vue({
      // ...
      components: {
        'my-component': () => import('./my-async-component')
      }
    })  
    

    最后一种异步注册的方式,我们称它为高级异步组件,这种方式是在 Vue2.3.0 新增的一种异步组件注册方式。看一下高级异步组件应该如何定义:

      <script type="text/javascript">
        // 注册组件
        var resCom = {
          template: "#async-example"
        };
        
        var promise = new Promise(function(resolve, reject){
          setTimeout(function(){
            resolve(resCom)
          }, 2000);
        });
        
        var LoadingComponent = {
          template: '<div>加载中显示的组件</div>'
        };
        var ErrorComponent = {
          template: '<div>异步组件加载失败</div>'
        };
        // Vue.component('async-example', function(resolve, reject){
        //   setTimeout(function(){
        //     // 向resolve回调传递组件定义
        //     resolve(resCom);
        //   }, 1000);
        // });
        
        const AsyncComponent = function(){
          return {
            // 需要加载的组件 (应该是一个 `Promise` 对象)
            component: promise,
            // 异步组件加载时使用的组件
            loading: LoadingComponent,
            // 加载失败时使用的组件
            error: ErrorComponent,
            // 展示加载时组件的延时时间。默认值是 200 (毫秒)
            delay: 200,
            // 如果提供了超时时间且组件加载也超时了,
            // 则使用加载失败时使用的组件。默认值是:`Infinity`
            // PS: 组件加载超时时间,超时表示加载失败,会展示ErrorComponent。
            // 比如在这里当我们把 Promise 中的 setTimeout 改为 4000的时候,则会展示 ErrorComponent
            timeout: 3000
          }
        }
        
        var vm = new Vue({
          el: "#app",
          // 注意这里与之前的写法不同之处,是因为我们把这个方法提出去赋值给了AsyncComponent的变量
          components:{
            'async-example': AsyncComponent
          }
        })
      </script> 
    

    可以看到高级异步组件的配置更加全面,在逻辑上反而会比前两种异步组件的配置方式更加简单,所以在实际的项目使用中,我们也更加推崇使用高级异步组件的方式来定义异步组件。


    起源地下载网 » ⒓ Vue的动态组件 & 异步组件

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元