其實現與組件的keep-alive相關,僅設置了keep-aive的頁面,實施保留回退位置能力。vue
做用webpack
把切換出去的組件保留在內存中,能夠保留它的狀態或避免從新渲染,提高切換性能。web
相關的生命週期vue-router
created() { console.log('created') }, activated() { console.log('activated') }, deactivated() { console.log('deactivated') }, mounted() { console.log('mounted') }
執行結果瀏覽器
activated和deactivated爲keep-alive組件特有的生命週期,有什麼做用呢?緩存
因爲keep-alive對單頁路由生效,不管是後退操做,仍是跳轉操做,當非首次訪問組件時,mounted、created不執行,其中的數據請求也不會發起,因此,其數據不會進行相應更新。這種設定,符合回退操做的數據狀態,但對於大多數的單頁跳轉操做,會出現數據問題。此時,可利用ativated,發起數據請求,更新數據狀態。因爲是數據驅動的視圖,因此,在數據請求到達前,組件使用舊的數據狀態,仍然能給用戶不錯的視覺體驗(不會出現白屏之類的)。babel
vue-router中有提供scrollBehavior方法,設置回退位置。但因爲本項目中vue的基礎佈局限制,使得scroll在window or document中無效,所以須要自定義方法。app
相關條件佈局
僅用戶進行回退操做,且設置了router爲keep-alive屬性的方法,纔可進行實際的回退。性能
思路
實現代碼
// app.vue <div class='view-frame'> <keep-alive> <router-view class="view" v-if="$route.meta.keepAlive"></router-view> </keep-alive> <router-view class="view" v-if="!$route.meta.keepAlive"></router-view> </div> // router.js let routerList = [{ ... meta: { keepAlive: true } }] const router = new VueRouter({ mode: 'history', ... // 設置返回對應位置的操做 scrollBehavior(to, from, savedPosition) { if (savedPosition && to.meta.keepAlive) { let scrollTop = store.state.common.scrollPos[to.name] || 0 if (!scrollTop) { return } // 對scroll元素進行設置 setTimeout(() => { let documentElem = document.querySelector('.v-content') if (documentElem) { documentElem.scrollTop = scrollTop } }, 0) } } }) router.beforeEach((to, from, next) => { // 記錄上一個頁面的scroll位置 if (from.name) { let contentElem = document.querySelector('.v-content') let scrollTop = contentElem ? contentElem.scrollTop : '0' store.state.common.scrollPos[from.name] = scrollTop } next( })
瞭解webpack打包配置的童鞋都知道,webpack提供模塊方法,實現按需加載的功能,使得單頁應用的首屏性能更高。但打包的方法,經常會影響瀏覽器緩存,當訪問一個資源時,若是其已經加載過,將緩存下來,再次訪問時,只需從緩存中取,從而省去了再次請求的時間。所以,有效的打包策略應如是:當文件沒有改動時,保持其文件名不變。
webpack提供兩種打包方式
方法1:
方法2:
第二種方式更佳,相關代碼以下:
// webpack.js output: { .... chunkFilename: utils.assetsPath('js/[name].[chunkhash].js') } // router.js const home = r => require.ensure([], () => r(require('src/views/home')), 'home') let routerList = [{ ... component: home }]
如此,會出現包合併的問題,所以須要根據路由模塊,對包名進行管理。
******更新*******
打包名的命名第三種方式,採用ES6的import實現,須要進行對應的設置:
step1:.babelrc文件,刪除「comments」配置;如圖:
step2: 若是有eslint檢測,則須要在eslint中增長配置;如圖:
step3:修改包的加載方式(require.ensure => import):
將 const home = r => require.ensure([], () => r(require('src/views/home')), 'home')
替換成:const home = () => import(/* webpackChunkName: 'home' */ 'src/views/home')
/* webpackChunkName: 'home' */可實現自定義包名,若是不須要自定義,可將該註釋刪除。