以前開發了一個單頁面應用,按照深度,分爲三層:目錄頁、一級子頁(標籤頁、故事頁等)、二級子頁(故事編輯頁)。javascript
這三類頁面都共享一個完整的數據model,從上級頁面進入下一級頁面時,可以加載相應數據;回到上一級時,數據有更新。舉個栗子,從故事頁點擊「編輯」按鈕,進入故事編輯頁則默認填充點擊的「編輯」按鈕所對應的故事數據;而當在故事編輯頁更新數據,返回到故事頁時,剛剛更新的信息也能在故事頁展現。html
對於這項需求,咱們須要解決以下幾個問題:vue
本文後面內容,將對如上問題一一提出解決方案。java
多個路由共享數據,可使用vuex作數據中心,因爲需求對數據處理並不複雜,爲了簡便就使用window全局對象做爲路由間傳遞數據的工具。
核心數據咱們能夠設計爲以下結構,以故事爲例:vue-router
window.profileData = { storyList: [{ content: 'xxx', type: 0, picList: [...], }, ...], description: {...}, // 其餘字段數據 }
注意到,若是須要更新storyList,則應該使用可以被檢測到的方法,如push, splice等。vuex
數據更新與緩存大體有兩種方案:
第一種,利用vue-router的導航守衛(見文檔:https://router.vuejs.org/zh/g...),主要使用路由組件內導航 beforeRouteEnter 和 beforeRouteLeave;
第二種,在路由組件中監聽$route,每次路由變化就會調用其中方法加載數據,須要注意的是第一次進入路由組件$route的監聽不會觸發,咱們須要在mounted方法中調用相同加載數據的方法;緩存
咱們在代碼中使用的是方法一,以故事列表進入到故事編輯頁爲例,從列表傳遞index給編輯頁,利用beforeRouteEnter進入路由時就加載新的數據。
編輯頁中關鍵代碼,即加載數據、更新本地共享數據:ide
export default { // 編輯頁中, 進入路由前加載數據 beforeRouteEnter(to, from, next) { next(vm => { const index = vm.$route.params.storyIndex vm.storyIndex = index vm.storyData = window.profile.storyList[index] }) }, methods: { // 提交成功後,更新本地共享數據 submit() { Adapter.post('...').then(result => { window.profile.storyList.splice(this.storyIndex, 1, result) }) }, }, }
列表頁中關鍵代碼,即返回時更新數據:工具
export default { beforeRouteEnter(to, from, next) { next(vm => { vm.storyList = window.profileData.storyList }) }, }
這部分須要注意的有兩點:post
從故事編輯頁回到故事列表頁,咱們但願能夠保存以前瀏覽的位置。思路也很簡單,進入編輯頁時保存scrollTop,返回時scrollTo便可。並且vue-router對象有屬性能夠實現這個功能,這就簡潔多了。
因爲咱們過渡動畫中間,有將路由組件定位成fixed的操做,因此,動畫結束後再手動滾動到目標位置:
new VueRouter({ routes, scrollBehavior (to, from, savedPosition) { const y = savedPosition && savedPosition.y || 0 setTimeout(() => { window.scrollTo(0, y) }, 300) } })
vue-router咱們在偏B端的場景中常常用到,尤爲是分步驟填寫表單的頁面。前期在使用過程當中老是不太順暢,摸索幾回後,最終找到比較「溫馨」的使用方法,索性就梳理成文。
固然,還有其餘一些特殊場景的用法,這裏暫時不說了,等項目中用事後再另起一文,繼續研究。