一严蓖、?什么是懶加載
? ? ? 懶加載也叫延遲加載,即在需要的時(shí)候進(jìn)行加載饥努,隨用隨載捡鱼。
二、為什么需要懶加載
? ? ? 在單頁(yè)應(yīng)用中酷愧,如果沒有應(yīng)用懶加載驾诈,運(yùn)用webpack打包后的文件將會(huì)異常的大,造成進(jìn)入首頁(yè)時(shí)伟墙,需要加載的內(nèi)容過多翘鸭,延時(shí)過長(zhǎng),不利于用戶體驗(yàn)戳葵,而運(yùn)用懶加載則可以將頁(yè)面進(jìn)行劃分就乓,需要的時(shí)候加載頁(yè)面,可以有效的分擔(dān)首頁(yè)所承擔(dān)的加載壓力拱烁,減少首頁(yè)加載用時(shí)
三生蚁、如何與webpack配合實(shí)現(xiàn)組件懶加載
1、在webpack配置文件中的output路徑配置chunkFilename屬性
output: {
????????path: resolve(__dirname,?'dist'),
????????filename: options.dev ??'[name].js':?'[name].js?[chunkhash]',
????????chunkFilename:?'chunk[id].js?[chunkhash]',
????????publicPath: options.dev ??'/assets/': publicPath
????},
chunkFilename路徑將會(huì)作為組件懶加載的路徑
2戏自、配合webpack支持的異步加載方法
resolve => require([URL], resolve), 支持性好
() => system.import(URL) , webpack2官網(wǎng)上已經(jīng)聲明將逐漸廢除, 不推薦使用
() => import(URL), webpack2官網(wǎng)推薦使用, 屬于es7范疇, 需要配合babel的syntax-dynamic-import插件使用, 具體使用方法如下
npm install --save-dev babel-core babel-loader babel-plugin-syntax-dynamic-importbabel-preset-es2015
use: [{
????????loader:?'babel-loader',
????????options: {
??????????presets: [['es2015', {modules:?false}]],
??????????plugins: ['syntax-dynamic-import']
????????}
??????}]
四邦投、具體實(shí)例中實(shí)現(xiàn)懶加載
1、路由中配置異步組件
exportdefaultnewRouter({
????routes: [
????????{
????????????mode:?'history',
????????????path:?'/my',
????????????name:?'my',
????????????component:? resolve => require(['../page/my/my.vue'], resolve),//懶加載
????????},
????]
})
2擅笔、實(shí)例中配置異步組件
components: {
????????historyTab: resolve => {require(['../../component/historyTab/historyTab.vue'], resolve)},//懶加載
????????//historyTab: () => import('../../component/historyTab/historyTab.vue')
????},
3志衣、全局注冊(cè)異步組件
Vue.component('mideaHeader', () => {
????System.import('./component/header/header.vue')
})
五屯援、配置異步組件實(shí)現(xiàn)懶加載的問題分析
1、多次進(jìn)出同一個(gè)異步加載頁(yè)面是否會(huì)造成多次加載組件念脯?
答:否狞洋,首次需要用到組件時(shí)瀏覽器會(huì)發(fā)送請(qǐng)求加載組件,加載完將會(huì)緩存起來(lái)绿店,以供之后再次用到該組件時(shí)調(diào)用
2吉懊、在多個(gè)地方使用同一個(gè)異步組件時(shí)是否造成多次加載組件?如:
//a頁(yè)面
exportdefault{
????components: {
????????historyTab: resolve => {require(['../../component/historyTab/historyTab.vue'], resolve)},//懶加載
????},
}
//b頁(yè)面
exportdefault{
????components: {
????????historyTab: resolve => {require(['../../component/historyTab/historyTab.vue'], resolve)},//懶加載
????},
}
答:否假勿,理由同上
3借嗽、如果在兩個(gè)異步加載的頁(yè)面中分別同步與異步加載同一個(gè)組件時(shí)是否會(huì)造成資源重用? 如:
//a頁(yè)面import historyTab from '../../component/historyTab/historyTab.vue';
export default {
? ? components: {
? ? ? ? historyTab
? ? },
}//b頁(yè)面exportdefault {
? ? components: {
? ? ? ? historyTab: resolve => {require(['../../component/historyTab/historyTab.vue'], resolve)},//懶加載? ? },
}
答: 會(huì), 將會(huì)造成資源重用, 根據(jù)打包后輸出的結(jié)果來(lái)看, a頁(yè)面中會(huì)嵌入historyTab組件的代碼, b頁(yè)面中的historyTab組件還是采用異步加載的方式, 另外打包c(diǎn)hunk转培;
解決方案: 組件開發(fā)時(shí)恶导, 如果根頁(yè)面沒有導(dǎo)入組件的情況下,而是在其他異步加載頁(yè)面中同時(shí)用到組件浸须, 那么為實(shí)現(xiàn)資源的最大利用甲锡,在協(xié)同開發(fā)的時(shí)候全部人都使用異步加載組件
4、在異步加載頁(yè)面中載嵌入異步加載的組件時(shí)對(duì)頁(yè)面是否會(huì)有渲染延時(shí)影響羽戒?
答:會(huì)缤沦, 異步加載的組件將會(huì)比頁(yè)面中其他元素滯后出現(xiàn), 頁(yè)面會(huì)有瞬間閃跳影響易稠;
解決方案:因?yàn)樵谑状渭虞d組件的時(shí)候會(huì)有加載時(shí)間缸废, 出現(xiàn)頁(yè)面滯后, 所以需要合理的進(jìn)行頁(yè)面結(jié)構(gòu)設(shè)計(jì)驶社, 避免首次出現(xiàn)跳閃現(xiàn)象企量;
六、懶加載的最終實(shí)現(xiàn)方案
1亡电、路由頁(yè)面以及路由頁(yè)面中的組件全都使用懶加載
優(yōu)點(diǎn):(1)最大化的實(shí)現(xiàn)隨用隨載
〗旃(2)團(tuán)隊(duì)開發(fā)不會(huì)因?yàn)闇贤▎栴}造成資源的重復(fù)浪費(fèi)
缺點(diǎn):(1)當(dāng)一個(gè)頁(yè)面中嵌套多個(gè)組件時(shí)將發(fā)送多次的http請(qǐng)求,可能會(huì)造成網(wǎng)頁(yè)顯示過慢且渲染參差不齊的問題
2份乒、路由頁(yè)面使用懶加載恕汇, 而路由頁(yè)面中的組件按需進(jìn)行懶加載, 即如果組件不大且使用不太頻繁, 直接在路由頁(yè)面中導(dǎo)入組件, 如果組件使用較為頻繁使用懶加載
優(yōu)點(diǎn):(1)能夠減少頁(yè)面中的http請(qǐng)求,頁(yè)面顯示效果好
缺點(diǎn):(2)需要團(tuán)隊(duì)事先交流或辖, 在框架中分別建立懶加載組件與非懶加載組件文件夾
3瘾英、路由頁(yè)面使用懶加載,在不特別影響首頁(yè)顯示延遲的情況下颂暇,根頁(yè)面合理導(dǎo)入復(fù)用組件缺谴,再結(jié)合方案2
優(yōu)點(diǎn):(1)合理解決首頁(yè)延遲顯示問題
(2)能夠最大化的減少http請(qǐng)求耳鸯, 且做其他他路由界面的顯示效果最佳
缺點(diǎn):(1)還是需要團(tuán)隊(duì)交流湿蛔,建立合理區(qū)分各種加載方式的組件文件夾
七膀曾、采用第三種方案進(jìn)行目錄結(jié)構(gòu)設(shè)計(jì)
八、具體代碼實(shí)現(xiàn)設(shè)計(jì)
1阳啥、路由設(shè)計(jì):
import Router from 'vue-router';
import Vue from 'vue';
Vue.use(Router);
export defaultnew 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)首層的路由根組件分別對(duì)應(yīng)的tab頁(yè)面
〖酥(2)根目錄后跟著各個(gè)子路由頁(yè)面,子路由采用動(dòng)態(tài)路由配合路由的編程式導(dǎo)航再加上vuex苫纤,最優(yōu)化提高開發(fā)效率
直接貼上代碼:
//vuex配置
importVue from?'vue';
importVuex from?'vuex';
Vue.use(Vuex);
exportdefaultnewVuex.Store({
????state: {
????????//路由組件存儲(chǔ)器
????????routers: {}
????},
????getters: {
????????routers: state => {
????????????returnstate.data;
????????}
????},
????mutations: {
????????//動(dòng)態(tài)增加路由
????????addRouter: (state, data) => {
????????????state.routers = Object.assign({}, state.routers, {
????????????????[data.name]: data.component
????????????});
????????}
????},
????actions: {
????????acMethods({commit}) {
????????}
????},
})
//根目錄中注冊(cè)路由組件
window.midea = {
????registerRouter(name, component) {
????????Store.commit('addRouter', {
????????????name: name,
????????????component: component
????????})
????}
};
//頁(yè)面使用路由導(dǎo)航openAnyPage() {
? ? midea.registerRouter('module', resolve => {require(['../module/module.vue'], resolve)});//懶加載
? ? this.$router.push({path: '/home/module', query: {title: this.title}});
//頁(yè)面中使用動(dòng)態(tài)組件
exportdefault{
????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: {
????}
}
二、動(dòng)態(tài)組件的設(shè)計(jì)
直接用即用即加的方式在實(shí)例或路由中直接配置異步組件