vue路由管理-保留滾動位置功能、按需加載模塊名自定義


路由管理:保留滾動位置

其實現與組件的keep-alive相關,僅設置了keep-aive的頁面,實施保留回退位置能力。

keep-alive介紹

作用

把切換出去的組件保留在內存中,可以保留它的狀態或避免重新渲染,提升切換性能。

相關的生命周期

created() {
    console.log('created')
},
activated() {
    console.log('activated')
},
deactivated() {
    console.log('deactivated')
},
mounted() {
    console.log('mounted')
}

執行結果

  • 首次執行該keep-alive組件:
    • 進入:created-> mounted-> activated
    • 離開:deactivated
  • 第二次執行該keep-alive組件:
    • 進入:activated
    • 離開:deactivated
  • 對於沒有設置keep-alive的組件:
    • 進入:created-> mounted
    • 離開:空

activated和deactivated為keep-alive組件特有的生命周期,有什么作用呢?

由於keep-alive對單頁路由生效,不論是后退操作,還是跳轉操作,當非首次訪問組件時,mounted、created不執行,其中的數據請求也不會發起,所以,其數據不會進行相應更新。這種設定,符合回退操作的數據狀態,但對於大多數的單頁跳轉操作,會出現數據問題。此時,可利用ativated,發起數據請求,更新數據狀態。由於是數據驅動的視圖,所以,在數據請求到達前,組件使用舊的數據狀態,仍然能給用戶不錯的視覺體驗(不會出現白屏之類的)。

保留滾動位置功能的實現方法

vue-router中有提供scrollBehavior方法,設置回退位置。但由於本項目中vue的基礎布局限制,使得scroll在window or document中無效,因此需要自定義方法。

相關條件

僅用戶進行回退操作,且設置了router為keep-alive屬性的方法,才可進行實際的回退。

思路

  • a、確認回退操作:通過判斷scrollBehavior的savedPosition是否存在;
  • b、是否為keep-alive的組件:通過router上的meta.keepAlive屬性判斷;
  • c、獲取頁面離開時的位置:beforeEach鈎子(該鈎子的生命周期:離開前頁面,進入下一頁面前)

實現代碼

// 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提供兩種打包方式

  • a、require():將按照webpack的打包id,進行命名;
  • b、require.ensure():可自定義打包名。

方法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' */可實現自定義包名,如果不需要自定義,可將該注釋刪除。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM