Bootstrap

vue组件懒加载

1 路由懒加载

路由懒加载常用的两种方式是import(官方推荐)和require

Vue官网路由懒加载开发文档

路由懒加载 | Vue Router

1.1 使用import实现懒加载

router

import Vue from 'vue'
import VueRouter from 'vue-router'
​
Vue.use(VueRouter)
​
/*
// 原始加载方式
import Views from "@/views"
import First from "@/views/First"
import Second from "@/views/Second"
import Third from "@/views/Third"
*/
​
// "/* webpackChunkName:'mycomp' */ "的作用是将文件打包在同一个异步块‘mycomp’中
const Views = ()=>import(/* webpackChunkName:'mycomp' */ "@/views")
const First = ()=>import(/* webpackChunkName:'mycomp' */ "@/views/First")
const Second = ()=>import(/* webpackChunkName:'mycomp' */ "@/views/Second")
const Third = ()=>import(/* webpackChunkName:'mycomp' */ "@/views/Third")
​
​
const router = new VueRouter({
    routes:[
        {
            path:'/',
​
            // 一级导航
            component: Views,
            // 二级导航
            children:[
                {
                    // 重定向到主页
                    path:'/',
                    redirect:'/first'
                },
                {
                    path:'/first',
                    name:'first',
                    component: First,
                    meta:{
                        title:"第一个"
                    }
                },
                {
                    path:'/second',
                    name:'second',
                    component: Second,
                    meta:{
                        title:"第二个"
                    }
                },
                {
                    path:'/third',
                    name:'third',
                    component: Third,
                    meta:{
                        title:"第三个"
                    }
                }
​
            ]
        }
    ]
});
​
// 设置页面标题
router.afterEach((to)=>{
    document.title = to.meta.title;
})
​
export default router;

截图

1.2 使用require实现懒加载

import Vue from 'vue'
import VueRouter from 'vue-router'
​
Vue.use(VueRouter)
​
/*
// 原始加载方式
import Views from "@/views"
import First from "@/views/First"
import Second from "@/views/Second"
import Third from "@/views/Third"
*/
​
// ---* 1 import方法 *---
// "/* webpackChunkName:'mycomp' */ "的作用是将文件打包在同一个异步块‘mycomp’中
// const Views = ()=>import(/* webpackChunkName:'mycomp' */ "@/views")
// const First = ()=>import(/* webpackChunkName:'mycomp' */ "@/views/First")
// const Second = ()=>import(/* webpackChunkName:'mycomp' */ "@/views/Second")
// const Third = ()=>import(/* webpackChunkName:'mycomp' */ "@/views/Third")
​
// ---* 2 require方法 *---
const Views = resolve=>(require(["@/views"],resolve))
const First = resolve=>(require(["@/views/First"],resolve))
const Second = resolve=>(require(["@/views/Second"],resolve))
const Third = resolve=>(require(["@/views/Third"],resolve))
​
const router = new VueRouter({
    routes:[
        {
            path:'/',
​
            // 一级导航
            component: Views,
            // 二级导航
            children:[
                {
                    // 重定向到主页
                    path:'/',
                    redirect:'/first'
                },
                {
                    path:'/first',
                    name:'first',
                    component: First,
                    meta:{
                        title:"第一个"
                    }
                },
                {
                    path:'/second',
                    name:'second',
                    component: Second,
                    meta:{
                        title:"第二个"
                    }
                },
                {
                    path:'/third',
                    name:'third',
                    component: Third,
                    meta:{
                        title:"第三个"
                    }
                }
​
            ]
        }
    ]
});
​
// 设置页面标题
router.afterEach((to)=>{
    document.title = to.meta.title;
})
​
export default router;

截图

2 组件懒加载

组件懒加载一般有两种方法,一种使用component的is属性和computed实现,另一种是使用v-if实现。

Vue官网动态加载组件开发文档

动态组件 & 异步组件 — Vue.js

2.1 页面切换懒加载

在单组件注册中并考虑缓存机制,页面切换懒加载主要有两种实现方式,一种是使用computed、component的is属性、import,另一种是使用computed、component的is属性和require。

<template>
  <div id="first">
   
    <div class="fir_title">
      First Page
      河南大学
    </div>
​
    <div class="fir_nav">
      <button v-on:click='switchPage("first")'>FirCom-1</button>
      <button v-on:click='switchPage("second")'>FirCom-2</button>
      <button v-on:click='switchPage("third")'>FirCom-3</button>
    </div>
  
    <div class="fir_con">
      <component v-bind:is='getFirstCom'></component>
    </div>
​
  </div>
</template>
​
<script>
​
/*
// ---* 1 使用标签属性is和import *---
const FirstComFirst = ()=>import("./FirstComFirst")
const FirstComSecond = ()=>import("./FirstComSecond")
const FirstComThird = ()=>import("./FirstComThird")
*/
​
// ---* 2 使用标签属性is和require *---
const FirstComFirst = resolve=>(require(["./FirstComFirst"],resolve))
const FirstComSecond = resolve=>(require(["./FirstComSecond"],resolve))
const FirstComThird = resolve=>(require(["./FirstComThird"],resolve))
​
​
export default {
  name: 'First',
  components: {
    
  },
  data: function(){
    return{
      curPage: FirstComFirst
    }
  },
​
  methods:{
    switchPage: function(page){
      switch(page){
        case 'first':{
          this.curPage = FirstComFirst;
          break;
        }
        case 'second':{
          this.curPage = FirstComSecond;
          break;
        }
        case 'third':{
          this.curPage = FirstComThird;
          break;
        }
      }
    }
  },
​
  computed:{
    // 借助计算属性
    getFirstCom: function(){
      return this.curPage;
    }
  }
}
</script>
​
<style scope lang="less">
​
.fir_title{
  font-weight: bold;
}
​
.fir_nav>button{
  margin: 10px 6px;
}
​
.fir_con{
  margin-top: 20px;
}
​
</style>

2.2 使用if实现需要时加载

<template>
  <div id="second">
    <div class="sec_title">
      Second Page
      河南大学
    </div>
    <div class="sec_nav">
      <button v-on:click="showFirst()">显示第一个组件</button>
      <button v-on:click="showSecond()">显示第二个组件</button>
    </div>
    <div class="sec_com">
      <div>第一个组件</div>
      <component v-if="isFirstShow" v-bind:is="SecComFirst"></component>
      <SecComFirstTag v-if="isFirstShow"></SecComFirstTag>
    </div>
    <div>
      <div>第二个组件</div>
      <component v-if="isSecondShow" v-bind:is="SecComSecond"></component>
    </div>
  </div>
</template>
​
<script>
​
// 传统方法导入
import SecComFirstTag from "./SecComFirst.vue"
export default {
  name: 'Second',
  components: {
    SecComFirstTag
  },
  data: function(){
    return{
      // Import方法导入
      SecComFirst: ()=>import("./SecComFirst"),
      SecComSecond: ()=>import("./SecComSecond"),
​
      isFirstShow: false,
      isSecondShow: false
    }
  },
​
  methods:{
    showFirst: function(){
      if(this.isFirstShow){
        this.isFirstShow = false;
      }else{
        this.isFirstShow = true;
      }
    },
    showSecond: function(){
      this.isSecondShow = this.isSecondShow?false:true;
    }
  }
}
</script>
​
<style scope lang="less">
.sec_title{
  font-weight: bold;
}
.sec_nav>button{
  margin: 10px 6px;
}
.sec_com{
  margin: 10px 0px;
}
</style>
​

2.3 两种import导入

两种import方式导入组件。

<template>
  <div id="third">
    <div class="th_title">
      Third page 河南大学
    </div>
    <div class="th_com">
      <component v-bind:is="ThirdComFirst"></component>
      <ThirdComFirstTag></ThirdComFirstTag>
    </div>
​
     <div class="th_com">
      <component v-bind:is="ThirdComSecond"></component>
      <ThirdComSecondTag></ThirdComSecondTag>
    </div>
    
  </div>
</template>
​
<script>
​
// 传统方法导入
import ThirdComFirstTag from "./ThirdComFirst"
import ThirdComSecondTag from "./ThirdComSecond"
​
// 下面的方法和传统的方法相似
​
​
export default {
  name: 'Views',
  components: {
    ThirdComFirstTag,
    ThirdComSecondTag
  },
​
  data: function(){
    return{
      ThirdComFirst: ()=>import("./ThirdComFirst"),
      ThirdComSecond: ()=>import("./ThirdComSecond")
    }
  }
}
</script>
​
<style scope lang="less">
​
.th_title{
  font-weight: bold;
}
​
.th_com{
  margin: 10px 0px;
}
​
</style>
​

3 全部页面代码

3.1 main.js

import Vue from 'vue'
import App from './App.vue'
import router from '@/router'
​
Vue.config.productionTip = false
​
new Vue({
  render: h => h(App),
  router
}).$mount('#app')

3.2 router

index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
​
Vue.use(VueRouter)
​
/*
// 原始加载方式
import Views from "@/views"
import First from "@/views/First"
import Second from "@/views/Second"
import Third from "@/views/Third"
*/
​
// ---* 1 import方法 *---
// "/* webpackChunkName:'mycomp' */ "的作用是将文件打包在同一个异步块‘mycomp’中
// const Views = ()=>import(/* webpackChunkName:'mycomp' */ "@/views")
// const First = ()=>import(/* webpackChunkName:'mycomp' */ "@/views/First")
// const Second = ()=>import(/* webpackChunkName:'mycomp' */ "@/views/Second")
// const Third = ()=>import(/* webpackChunkName:'mycomp' */ "@/views/Third")
​
// ---* 2 require方法 *---
const Views = resolve=>(require(["@/views"],resolve))
const First = resolve=>(require(["@/views/First"],resolve))
const Second = resolve=>(require(["@/views/Second"],resolve))
const Third = resolve=>(require(["@/views/Third"],resolve))
​
const router = new VueRouter({
    routes:[
        {
            path:'/',
​
            // 一级导航
            component: Views,
            // 二级导航
            children:[
                {
                    // 重定向到主页
                    path:'/',
                    redirect:'/first'
                },
                {
                    path:'/first',
                    name:'first',
                    component: First,
                    meta:{
                        title:"第一个"
                    }
                },
                {
                    path:'/second',
                    name:'second',
                    component: Second,
                    meta:{
                        title:"第二个"
                    }
                },
                {
                    path:'/third',
                    name:'third',
                    component: Third,
                    meta:{
                        title:"第三个"
                    }
                }
​
            ]
        }
    ]
});
​
// 设置页面标题
router.afterEach((to)=>{
    document.title = to.meta.title;
})
​
export default router;

3.3 App.vue

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>
​
<script>
​
export default {
  name: 'App',
  components: {
  }
}
</script>
​
<style scope lang="less">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
​

3.4 views

index.vue

<template>
  <div id="views">
    <div class="my_nav">
      <router-link to="/first">第一个页面</router-link>
      <router-link to="/second">第二个页面</router-link>
      <router-link to="/third">第三个页面</router-link>
    </div>
    <div class="my_page">
      <router-view></router-view>
    </div>
    
  </div>
</template>
​
<script>
​
export default {
  name: 'Views',
  components: {
    
  }
}
</script>
​
<style scope lang="less">
.my_nav{
  height: 40px;
}
.my_nav>a{
  margin: 0 8px
}
​
.my_page{
  margin-top: 20px;
}
​
</style>
​

3.5 First

index.vue

<template>
  <div id="first">
   
    <div class="fir_title">
      First Page
      河南大学
    </div>
​
    <div class="fir_nav">
      <button v-on:click='switchPage("first")'>FirCom-1</button>
      <button v-on:click='switchPage("second")'>FirCom-2</button>
      <button v-on:click='switchPage("third")'>FirCom-3</button>
    </div>
  
    <div class="fir_con">
      <component v-bind:is='getFirstCom'></component>
    </div>
​
  </div>
</template>
​
<script>
​
/*
// ---* 1 使用标签属性is和import *---
const FirstComFirst = ()=>import("./FirstComFirst")
const FirstComSecond = ()=>import("./FirstComSecond")
const FirstComThird = ()=>import("./FirstComThird")
*/
​
// ---* 2 使用标签属性is和require *---
const FirstComFirst = resolve=>(require(["./FirstComFirst"],resolve))
const FirstComSecond = resolve=>(require(["./FirstComSecond"],resolve))
const FirstComThird = resolve=>(require(["./FirstComThird"],resolve))
​
​
export default {
  name: 'First',
  components: {
    
  },
  data: function(){
    return{
      curPage: FirstComFirst
    }
  },
​
  methods:{
    switchPage: function(page){
      switch(page){
        case 'first':{
          this.curPage = FirstComFirst;
          break;
        }
        case 'second':{
          this.curPage = FirstComSecond;
          break;
        }
        case 'third':{
          this.curPage = FirstComThird;
          break;
        }
      }
    }
  },
​
  computed:{
    // 借助计算属性
    getFirstCom: function(){
      return this.curPage;
    }
  }
}
</script>
​
<style scope lang="less">
​
.fir_title{
  font-weight: bold;
}
​
.fir_nav>button{
  margin: 10px 6px;
}
​
.fir_con{
  margin-top: 20px;
}
​
​
</style>

​

FirstComOne.vue

<template>
  <div>
    First component one
  </div>
</template>
​
<script>
​
export default {
  name: 'FirstComOne',
  components: {
    
  }
}
</script>
​
<style scope lang="less">
​
</style>
​

FirstComSecond.vue

<template>
  <div>
    First component second
  </div>
</template>
​
<script>
​
export default {
  name: 'FirstComSecond',
  components: {
    
  },
​
  created: function(){
    console.log("FirstComSecond");
  }
}
</script>
​
<style scope lang="less">
​
</style>
​

FirstComThird.vue

<template>
  <div>
    First component third
  </div>
</template>
​
<script>
​
export default {
  name: 'FirstComThird',
  components: {
    
  },
​
  created: function(){
    console.log("FirstComThird");
  }
}
</script>
​
<style scope lang="less">
​
</style>
​

3.6 Second

index.vue

<template>
  <div id="second">
    <div class="sec_title">
      Second Page
      河南大学
    </div>
    <div class="sec_nav">
      <button v-on:click="showFirst()">显示第一个组件</button>
      <button v-on:click="showSecond()">显示第二个组件</button>
    </div>
    <div class="sec_com">
      <div>第一个组件</div>
      <component v-if="isFirstShow" v-bind:is="SecComFirst"></component>
      <SecComFirstTag v-if="isFirstShow"></SecComFirstTag>
    </div>
    <div>
      <div>第二个组件</div>
      <component v-if="isSecondShow" v-bind:is="SecComSecond"></component>
    </div>
  </div>
</template>
​
<script>
​
// 传统方法导入
import SecComFirstTag from "./SecComFirst.vue"
export default {
  name: 'Second',
  components: {
    SecComFirstTag
  },
  data: function(){
    return{
      // Import方法导入
      SecComFirst: ()=>import("./SecComFirst"),
      SecComSecond: ()=>import("./SecComSecond"),
​
      isFirstShow: false,
      isSecondShow: false
    }
  },
​
  methods:{
    showFirst: function(){
      if(this.isFirstShow){
        this.isFirstShow = false;
      }else{
        this.isFirstShow = true;
      }
    },
    showSecond: function(){
      this.isSecondShow = this.isSecondShow?false:true;
    }
  }
}
</script>
​
<style scope lang="less">
.sec_title{
  font-weight: bold;
}
.sec_nav>button{
  margin: 10px 6px;
}
.sec_com{
  margin: 10px 0px;
}
</style>

截图

SecComFirst.vue

<template>
  <div>
   Second component First
  </div>
</template>
​
<script>
​
export default {
  name: 'SecComFirst',
  components: {
    
  },
​
  created: function(){
    console.log("Second component Frist !")
  }
}
</script>
​
<style scope lang="less">
​
</style>
​

SecComSecond.vue

<template>
  <div>
    Second component Second
  </div>
</template>
​
<script>
​
export default {
  name: 'SecComSecond',
  components: {
    
  },
​
  created: function(){
    console.log("Second component second !")
  }
}
</script>
​
<style scope lang="less">
​
</style>
​

3.7 Third

index.vue

<template>
  <div id="third">
    <div class="th_title">
      Third page 河南大学
    </div>
    <div class="th_com">
      <component v-bind:is="ThirdComFirst"></component>
      <ThirdComFirstTag></ThirdComFirstTag>
    </div>
​
     <div class="th_com">
      <component v-bind:is="ThirdComSecond"></component>
      <ThirdComSecondTag></ThirdComSecondTag>
    </div>
    
  </div>
</template>
​
<script>
​
// 传统方法导入
import ThirdComFirstTag from "./ThirdComFirst"
import ThirdComSecondTag from "./ThirdComSecond"
​
// 下面的方法和传统的方法相似
​
​
export default {
  name: 'Views',
  components: {
    ThirdComFirstTag,
    ThirdComSecondTag
  },
​
  data: function(){
    return{
      ThirdComFirst: ()=>import("./ThirdComFirst"),
      ThirdComSecond: ()=>import("./ThirdComSecond")
    }
  }
}
</script>
​
<style scope lang="less">
​
.th_title{
  font-weight: bold;
}
​
.th_com{
  margin: 10px 0px;
}
​
</style>
​

ThirdComFirst.vue

<template>
  <div>
   Third component First
  </div>
</template>
​
<script>
​
export default {
  name: 'ThirdComFirst',
  components: {
    
  },
​
  created: function(){
    console.log("Third component Frist !")
  }
}
</script>
​
<style scope lang="less">
​
</style>
​

ThirdComSecond.vue

<template>
  <div>
    Third component Second
  </div>
</template>
​
<script>
​
export default {
  name: 'ThirdComSecond',
  components: {
    
  },
​
  created: function(){
    console.log("Third component second !")
  }
}
</script>
​
<style scope lang="less">
​
</style>
​

4 import和require的区别

4.1 import/export

来源于ECMAScript2015(ES6),node支持,部分高版本的原生浏览器支持import/export(需要加type="module" 属性),脚本静态编译。

4.2 require/exports

来源于CommonJS,node支持,原生浏览器不支持 require/exports,脚本运行时动态加载对象。

;