vue2动态加载组件的实现

886 阅读1分钟

动态加载是web应用的优化首屏加载的手段之一,webpack是支持import用于动态加载模块的。import作为函数调用时参数为文件路径,返回一个primise实例。

window.addEventListener('click', ()=>{
    import(/* webpackChunkName: "test-module"*/"./test.js")
    .then(module =>{
        ...
    })
});

动态加载组件的实现手段是一样的,在合适的生命周期去调用import函数,并在返回后将组件挂到全局或父组件里(一般喜欢放入父组件里),修改父组件的数据导致视图更新,让未被渲染出来的动态组件显示。

import("./test.vue")
.then(component => {
    //挂到全局
    Vue.component('asyncComponent', component.default);
    
    //挂到父组件
    this.$options.components.asyncComponent = Vue.extend(component.default);
}

我一般喜欢抽离成一个组件去修饰一下,使之可公用并更优雅。

// asyncLoad.vue
<template>
  <div>
    <asyncComponent v-if="ready" v-bind="$attrs" v-on="$listeners"></asyncComponent>
    <div v-else>
       <span v-if="fail">组件加载失败,请刷新页面。</span> 
       <span v-else>加载中...</span>
    </div>
  </div>
</template>
<script>
import Vue from 'vue';
export default {
  props: {
    importFunction: {
      require: true,
      type: Function
    }
  },
  data() {
    return {
      ready: false,
      fail: false,
    }
  },
  mounted() {
    this.importFunction()
    .then(com => {
       this.$options.components.asyncComponent = Vue.extend(com.default);
       this.ready = true;
    })
    .catch(err => {
       this.fail = true;
    })
  },
}
</script>
// 动态加载使用者
<template>
  <div>
    <asynLoad :importFunction="loadComponent" />
  </div>
</template>
<script>
import asynLoad from '../asyncLoad.vue';

const loadComponent =  () => import("./test.vue");

export default {
  data() {
    return {
      loadComponent,
    }
  },
  components: {
    asynLoad
  },
}
</script>