vue2組件懶加載淺析

vue2組件懶加載淺析javascript

1、 什麼是懶加載vue

      懶加載也叫延遲加載,即在須要的時候進行加載,隨用隨載。java

2、爲何須要懶加載webpack

      在單頁應用中,若是沒有應用懶加載,運用webpack打包後的文件將會異常的大,形成進入首頁時,須要加載的內容過多,延時過長,不利於用戶體驗,而運用懶加載則能夠將頁面進行劃分,須要的時候加載頁面,能夠有效的分擔首頁所承擔的加載壓力,減小首頁加載用時web

3、如何與webpack配合實現組件懶加載vue-router

  一、在webpack配置文件中的output路徑配置chunkFilename屬性vuex

output: {
        path: resolve(__dirname, 'dist'),
        filename: options.dev ? '[name].js' : '[name].js?[chunkhash]',
        chunkFilename: 'chunk[id].js?[chunkhash]',
        publicPath: options.dev ? '/assets/' : publicPath
    },

 

  chunkFilename路徑將會做爲組件懶加載的路徑npm

  二、配合webpack支持的異步加載方法編程

  • resolve => require([URL], resolve), 支持性好
  • () => system.import(URL) , webpack2官網上已經聲明將逐漸廢除, 不推薦使用
  • () => import(URL), webpack2官網推薦使用, 屬於es7範疇, 須要配合babel的syntax-dynamic-import插件使用, 具體使用方法以下
    npm install --save-dev babel-core babel-loader babel-plugin-syntax-dynamic-import babel-preset-es2015
    
    use: [{
            loader: 'babel-loader',
            options: {
              presets: [['es2015', {modules: false}]],
              plugins: ['syntax-dynamic-import']
            }
          }]

4、具體實例中實現懶加載瀏覽器

  一、路由中配置異步組件

export default new Router({
    routes: [
        {
            mode: 'history',
            path: '/my',
            name: 'my',
            component:  resolve => require(['../page/my/my.vue'], resolve),//懶加載
        },
    ]
})

  二、實例中配置異步組件

components: {
        historyTab: resolve => {require(['../../component/historyTab/historyTab.vue'], resolve)},//懶加載
        //historyTab: () => import('../../component/historyTab/historyTab.vue')
    },

  三、全局註冊異步組件

Vue.component('mideaHeader', () => {
    System.import('./component/header/header.vue')
})

5、配置異步組件實現懶加載的問題分析

  一、屢次進出同一個異步加載頁面是否會形成屢次加載組件?

  答:否,首次須要用到組件時瀏覽器會發送請求加載組件,加載完將會緩存起來,以供以後再次用到該組件時調用

  二、在多個地方使用同一個異步組件時是否形成屢次加載組件?如:

//a頁面
export default {
    components: {
        historyTab: resolve => {require(['../../component/historyTab/historyTab.vue'], resolve)},//懶加載
    },
}

//b頁面
export default {
    components: {
        historyTab: resolve => {require(['../../component/historyTab/historyTab.vue'], resolve)},//懶加載
    },
}

  答:否,理由同上

  三、若是在兩個異步加載的頁面中分別同步與異步加載同一個組件時是否會形成資源重用? 如:

//a頁面
import historyTab from '../../component/historyTab/historyTab.vue';
export default {
    components: {
        historyTab
    },
}

//b頁面
export default {
    components: {
        historyTab: resolve => {require(['../../component/historyTab/historyTab.vue'], resolve)},//懶加載
    },
}

  答: 會, 將會形成資源重用, 根據打包後輸出的結果來看, a頁面中會嵌入historyTab組件的代碼, b頁面中的historyTab組件仍是採用異步加載的方式, 另外打包chunk;

  解決方案: 組件開發時, 若是根頁面沒有導入組件的狀況下,而是在其餘異步加載頁面中同時用到組件, 那麼爲實現資源的最大利用,在協同開發的時候所有人都使用異步加載組件

  四、在異步加載頁面中載嵌入異步加載的組件時對頁面是否會有渲染延時影響?

  答:會, 異步加載的組件將會比頁面中其餘元素滯後出現, 頁面會有瞬間閃跳影響;

  解決方案:由於在首次加載組件的時候會有加載時間, 出現頁面滯後, 因此須要合理的進行頁面結構設計, 避免首次出現跳閃現象;

6、懶加載的最終實現方案

  一、路由頁面以及路由頁面中的組件全都使用懶加載

  優勢:(1)最大化的實現隨用隨載

     (2)團隊開發不會由於溝通問題形成資源的重複浪費    

  缺點:(1)當一個頁面中嵌套多個組件時將發送屢次的http請求,可能會形成網頁顯示過慢且渲染良莠不齊的問題

  二、路由頁面使用懶加載, 而路由頁面中的組件按需進行懶加載, 即若是組件不大且使用不太頻繁, 直接在路由頁面中導入組件, 若是組件使用較爲頻繁使用懶加載

  優勢:(1)可以減小頁面中的http請求,頁面顯示效果好

  缺點:(2)須要團隊事先交流, 在框架中分別創建懶加載組件與非懶加載組件文件夾

  三、路由頁面使用懶加載,在不特別影響首頁顯示延遲的狀況下,根頁面合理導入複用組件,再結合方案2

  優勢:(1)合理解決首頁延遲顯示問題

     (2)可以最大化的減小http請求, 且作其餘他路由界面的顯示效果最佳

  缺點:(1)仍是須要團隊交流,創建合理區分各類加載方式的組件文件夾

7、採用第三種方案進行目錄結構設計

  

8、具體代碼實現設計

 一、路由設計:

import Router from 'vue-router';
import Vue from 'vue';
Vue.use(Router);

export default new Router({
    routes: [
        {
            mode: 'history',
            path: '/home',
            name: 'home',
            component:  resolve => require([URL], resolve),//懶加載
            children: [
                {
                    mode: 'history',
                    path: '/home/:name',
                    name: 'any',
                    component:  resolve => require(['../page/any/any.vue'], resolve),//懶加載
                },
            ]
        },
        {
            mode: 'history',
            path: '/store',
            name: 'store',
            component:  resolve => require(['../page/store/store.vue'], resolve),//懶加載,
            children: [
                {
                    mode: 'history',
                    path: '/store/:name',
                    name: 'any',
                    component:  resolve => require(['../page/any/any.vue'], resolve),//懶加載
                },
            ]
        },
        {
            mode: 'history',
            path: '/my',
            name: 'my',
            component:  resolve => require(['../page/my/my.vue'], resolve),//懶加載,
            children: [
                {
                    mode: 'history',
                    path: '/my/:name',
                    name: 'any',
                    component:  resolve => require(['../page/any/any.vue'], resolve),//懶加載
                },
            ]
        },
    ]
})

  (1)首層的路由根組件分別對應的tab頁面

  (2)根目錄後跟着各個子路由頁面,子路由採用動態路由配合路由的編程式導航再加上vuex,最優化提升開發效率

  直接貼上代碼:

/**
 * Created by ZHANZF on 2017-3-20.
 */
//vuex配置
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
    state: {
        //路由組件存儲器
        routers: {}
    },
    getters: {
        routers: state => {
            return state.data;
        }
    },
    mutations: {
        //動態增長路由
        addRouter: (state, data) => {
            state.routers = Object.assign({}, state.routers, {
                [data.name]: data.component
            });
        }
    },
    actions: {
        acMethods({commit}) {

        }
    },
})

//根目錄中註冊路由組件
window.midea = {
    registerRouter(name, component) {
        Store.commit('addRouter', {
            name: name,
            component: component
        })
    }
};

//頁面使用路由導航
openAnyPage() {
midea.registerRouter('module', resolve => {require(['../module/module.vue'], resolve)});//懶加載
this.$router.push({path: '/home/module', query: {title: this.title}});
}
//頁面中使用動態組件 <template>   <component :is="currentRouter" :moduleName="title"></component> </template>
<script src="./any.js"> export default { data () { return { routeName: '', currentRouter: '', title: '', } }, created() { this.routeName = this.$route.params.name; this.title = this.$route.query.title; this.currentRouter = this.$store.state.routers[this.routeName]; }, methods: { } } </script>

 

2、動態組件的設計

  直接用即用即加的方式在實例或路由中直接配置異步組件

相關文章
相關標籤/搜索