背景:
在公式做ms管理系統。然后老大看事情做差不錯了,想要優化一下用戶體驗。要我在每次用戶切換頁面后創建一個類似瀏覽器多頁面tag的導航。這樣用戶在使用時方便做數據比較。
最后長這樣

分析:
這個放在以前那就是多開一個頁面的事兒,讓瀏覽器幫我們保存數據和結構。放到vue里面,因為我們的結構是根據數據決定的,那就是保存一下數據的概念。保存數據的方式瞬間想到sessionstorage、localstorage,但是顯然這兩個是瀏覽器級別的,我們是有權限控制的所以pass掉。那就只能放在我們頁面的數據里面了。
因為是全局的,你需要在所有頁面都可以讀取、刪除。那就放在vuex這個狀態機里面。
然后狀態機里面你需要做幾件事:
1、添加這個tag(你可能需要判斷是否數量會太多,太多的話會影響性能)
2、更新這個tag(更新根據數組的鍵,就可以了)
3、銷毀這個tag
數據
export default { state: { tags: [],//訪問過的頁面集合 deepCopy: function(initalObject, finalObject) { var finalObject = finalObject || {} for (var key in initalObject) { var tempProperty = initalObject[key] if (tempProperty === initalObject) { continue //當自身屬性引用自己的時候,跳過執行,不拷貝,避免相互引用導致內存溢出的情況 } if (typeof initalObject[key] === "object" && initalObject[key] !== null) { finalObject[key] = (initalObject[key].constructor === Array) ? [] : {} //區分構造函數 this.deepCopy(initalObject[key], finalObject[key]) //調用自身函數方法 } else { finalObject[key] = initalObject[key] } } return finalObject } }, getters: { tags(state) { return state.tags; } }, mutations: { //將tag放進tags addTags(state, tag) { let index = state.tags.length; if (index > 8) { state.tags.splice(index > 0 ? index - 1 : 0, 1, state.deepCopy(tag)); } else { state.tags.splice(index > 0 ? index : 0, 0, state.deepCopy(tag)); } }, /* *tag.index和state.tags[tag.index]判斷key值是否正確以及是否存在數據 *state.tags[tag.index].name == tag.name 確定修改的路徑是否一致,防止刪除時修改 */ updateTags(state, tag) { if (tag.index !== null && state.tags[tag.index] && state.tags[tag.index].name == tag.name) { let data = { name: state.tags[tag.index].name, data: state.deepCopy(tag.data) } state.tags.splice(tag.index, 1, data); } }, delTags(state, index) { state.tags.splice(index, 1) }, //從tag進入時,由緩存初始化數據 cacheDataInit(state, { that, datashow }) { let datas = that.$data; Object.keys(datas).forEach((val) => { that[val] = datashow[val] }) } }, actions: { /* *在模塊復用的時候調用的時候更新數據 *that 頁面this參數 *to route中的to參數 */ beforeRouteUpdate({ commit, state }, { that, to }) { let status = that.$route.query.status; if (status === 'cache') { let index = that.$route.query.key;//該tag在tags數組中的鍵 let data = { index, data: that.$data, name: that.$route.path } commit('updateTags', data); } }, /* *在路由跳轉之前更新數據 *that 頁面this參數 */ beforeRouteLeave({ commit, state }, that) { if (that.$route.query.status === 'cache') { let index = that.$route.query.key; let data = { index,//所處的鍵,方便定位到tag data: that.$data,//頁面數據 name: that.$route.path//路由名 } commit('updateTags', data) } else { let data = { name: that.$route.path, data: that.$data } commit('addTags', data) } }, /* *從vuex更新頁面的數據 *that 頁面this */ cacheDataInit({ commit, state }, that) { let key = that.$route.query.key; let datashow = state.tags[key].data; commit('cacheDataInit', { that, datashow }) } } }
調用
調用剛開始想在全局直接調用,這樣就不用每一個單獨去寫了啊。然后發現route的全局守衛里面,beforeEach和afterEach這兩個內部都沒辦法使用this。我們內部是一定會調用this來賦值的。所以只能使用組件內守護。beforeRouteEnter(不能讀取this排除)、beforeRouteLeave、beforeRouteUpdate。
beforeRouteLeave:在路由離開之前觸發。那就可以在這個時候添加我們的tag了。
beforeRouteUpdate:在路由更新時觸發。這個時候是不是就可以讀取我們的緩存呢??完美
created() { let status = this.$route.query.status;//根據status狀態來確認是正常的導航還是緩存導航 if (status === 'cache') { this.cacheDataInit(this) } else { this.getData();//正常獲取數據 } }, beforeRouteLeave(to, from, next) {//離開之前調用添加tag方法 this.beforeRouteLeave(this) next() }, beforeRouteUpdate(to, from, next) {//路由更新時傳入進入和離開路由進行判斷 if (!this.$route.query.status && to.query) { this.$route.query.key = to.query.key; this.cacheDataInit(this) } else { this.beforeRouteUpdate({ that: this, to }) } next(); }
tag導航
<div id="scrollNav" v-if='tags.length'> <router-link :to="{path:tag.name,query:{status:'cache',key:key}}" v-for='(tag,key) in tags' :key='key' tag="span"> {{_navName(tag.name)}}/*_navName是根據tag.name返回導航中文的方法*/ <i class="el-icon-error" @click.stop="delTags(key)"></i> </router-link> </div>
寫完能跑起來了,就放心了。。。這都是什么鬼啊
