基于iview的router常用控制方式
1 iview的router控制需求
最近在使用iview框架寫項目,遇到了一些路由控制上的問題,解決過程中也有一些心得,故在此記錄下來.
每個項目在開發(fā)時,對于類似tags(標(biāo)簽頁)的控制需求都不盡相同,故以下先列出本文所述項目對標(biāo)簽頁的控制要求(如有不同需求,本文當(dāng)也可提供一些思路):
- 對于同名(name)的路由標(biāo)簽頁,不能打開多個.譬如說從商品列表中打開商品展示標(biāo)簽頁,如果已經(jīng)有在打開的商品編輯頁面,則替換之.新打開的,未保存,已保存的標(biāo)簽頁,同時只能存在一個(即不同params相同name的route只能有一個);
- 替換掉一個新的頁面時,通過切換的方式切換回來(先切到其他標(biāo)簽頁再切換回來),仍是原來頁面的內(nèi)容(即實際記錄的params在替換后應(yīng)變化).類似的情況,還應(yīng)包含單據(jù)從未保存到已保存,以及保存并新增功能;
2 基于vue的router控制
iview是基于vue的框架,故vue本身自帶的router控制方法是必然可行的.
vue變更路由的常用方式參考以下(該方法在官方api中有更詳細(xì)的介紹):
//變更當(dāng)前路由(有歷史記錄,建議使用此方式) this.$router.push({ name:'routerName', params:routerParam }) //變更當(dāng)前路由(無歷史記錄) this.$router.replace({ name:'routerName', routerParam })
官方路由變更確實可以正常打開標(biāo)簽頁,但在實現(xiàn)1中所提到的各種需求的時候,就有些不滿足需求了.為此,需要參考3中,如何基于iview的outer控制.
3 基于iview的router控制
iview在控制路由的時候,使用vuex中的app.js來記錄標(biāo)簽頁路由信息,如果對vuex還是很了解的話,可以通過這篇博文來先打一下基礎(chǔ).
3.1 如何實現(xiàn)需求1.1
想要實現(xiàn)不同params相同name的route在iview中只能有一個,關(guān)鍵是改變iview對路由相等的判斷方法,即'/src/libs/util.js'里的routeEqual方法:
/** * @description 根據(jù)name/params/query判斷兩個路由對象是否相等 * @param {*} route1 路由對象 * @param {*} route2 路由對象 */ export const routeEqual = (route1, route2) => { return route1.name === route2.name // 此處改變相同路由的判斷方式,改為name相同即認(rèn)為相同 // const params1 = route1.params || {} // const params2 = route2.params || {} // const query1 = route1.query || {} // const query2 = route2.query || {} // return (route1.name === route2.name) && objEqual(params1, params2) && objEqual(query1, query2) }
這里稍微解釋下(如果不關(guān)注原因,可以直接看3.2).當(dāng)改變路由時,'src\components\main\main.vue'作為近乎頂層的組件控制著近乎所有的全局邏輯,其中就有對路由的監(jiān)控:
... <side-menu accordion ref="sideMenu" :active-name="$route.name" :collapsed="collapsed" @on-select="turnToPage" :menu-list="menuList" > ... //此方法隸屬于methods,用以監(jiān)控side-menu的選擇事件,即平時從左側(cè)菜單打開標(biāo)簽頁的邏輯 turnToPage (route) { let { name, params, query } = {} if (typeof route === 'string') name = route else { name = route.name params = route.params query = route.query } if (name.indexOf('isTurnByHref_') > -1) { window.open(name.split('_')[1]) return } this.$router.push({ name, params, query }) }, ... watch: { // 檢測route的變化 $route (newRoute) { const { name, query, params, meta } = newRoute this.addTag({ route: { name, query, params, meta }, type: 'push' }) this.setBreadCrumb(newRoute) this.setTagNavList(getNewTagList(this.tagNavList, newRoute)) this.$refs.sideMenu.updateOpenName(newRoute.name) } }, ...
從以上代碼可推測出,main.vue通過turnToPage方法實現(xiàn)打開標(biāo)簽頁的邏輯,但方法內(nèi)部并沒有體現(xiàn)便簽頁顯示效果變化(包含內(nèi)部數(shù)據(jù)變化,以下同)的邏輯,這是由于顯示效果變化的邏輯,由對$router的監(jiān)控實現(xiàn).
這樣,不止從左側(cè)菜單打開新標(biāo)簽頁可以實現(xiàn)顯示變化效果,其他只要使用vue的原版push等方法改變router的方法,均可監(jiān)測到.
逐步查看下各個方法,其中影響當(dāng)前標(biāo)簽頁顯示效果的,是'src/store/module/app.js'的addTag方法.
addTag (state, { route, type = 'unshift' }) { let router = getRouteTitleHandled(route) if (!routeHasExist(state.tagNavList, router)) { if (type === 'push') state.tagNavList.push(router) else { if (router.name === homeName) state.tagNavList.unshift(router) else state.tagNavList.splice(1, 0, router) } setTagNavListInLocalstorage([...state.tagNavList]) } },
盡管方法內(nèi)部仍調(diào)用了很多,其中一個很重要的判斷,就是routeHasExist(路由是否存在),這個方法也是判斷是否為相同標(biāo)簽頁的一個關(guān)鍵節(jié)點(該方法同樣在util.js):
/** * 判斷打開的標(biāo)簽列表里是否已存在這個新添加的路由對象 */ export const routeHasExist = (tagNavList, routeItem) => { let len = tagNavList.length let res = false doCustomTimes(len, (index) => { if (routeEqual(tagNavList[index], routeItem)) res = true }) return res }
明顯可以看出,這個方法內(nèi)調(diào)用routeEqual,就是用以判斷是否為相同路由的實際方法(當(dāng)然是通過比較新路由與已有路由進(jìn)行比較),如此,僅需改變routeEqual即可.
以防萬一,全局搜索下調(diào)用這個routeEqual的所有方法,發(fā)現(xiàn)所有調(diào)用的地方再routeEqual在改變后不會出現(xiàn)新的問題.
3.2 如何實現(xiàn)需求1.2
在進(jìn)行3.1的操作后,問題得到了部分解決.余下的問題在于需求1.2沒有得到實現(xiàn)和解決.
首先是,如何實現(xiàn)從列表中打開或新建的,替換原來的標(biāo)簽頁,在來回切換后不會回到原來的標(biāo)簽頁. 只需在app.js中注冊改變標(biāo)簽頁參數(shù)的方法:
// 變更指定路由的參數(shù) changeTagParams (state, route) { let routeOldIndex = state.tagNavList.findIndex(m => routeEqual(m, route)) if (routeOldIndex !== -1) { let routeOld = state.tagNavList[routeOldIndex] routeOld.params = route.params state.tagNavList.splice(routeOldIndex, 1, routeOld) setTagNavListInLocalstorage([...state.tagNavList]) } },
然后在main.vue中對$route的監(jiān)控最后引用即可.
watch: { // 檢測route的變化 $route (newRoute) { const { name, query, params, meta } = newRoute this.addTag({ route: { name, query, params, meta }, type: 'push' }) this.setBreadCrumb(newRoute) this.setTagNavList(getNewTagList(this.tagNavList, newRoute)) this.$refs.sideMenu.updateOpenName(newRoute.name) // 增加路由參數(shù)變更環(huán)節(jié) this.changeTagParams(newRoute) } },
其次,如果出現(xiàn)像保存并新增,或者從未保存到已保存,這兩種情況來回切換后不會回到原來的情況.
保存并新增,關(guān)鍵是"新增"效果:
// 清空數(shù)據(jù),該方法在保存后調(diào)用 clearData () { //該部分是用來清除當(dāng)前route的參數(shù) this.$router.push({ params: Object.assign(this.$route.params, { id: undefined }) }) //這部分代碼是用來清空當(dāng)前頁面內(nèi)容,每個模塊都不盡相同,不必模仿 this.mOtherExpense = JSON.parse(JSON.stringify(this.mOtherExpenseInitial)) this.tableData = [{}] this.loadCode() this.mOtherExpense.openingDate = new Date() },
從未保存到已保存,關(guān)鍵同樣是如何讓route記住新的id(或其他參數(shù)):
// 設(shè)置路由id,該方法在第一次保存后調(diào)用 setData (id) { //這里的id是保存后從后臺傳來的新id this.$router.push({ params: Object.assign(this.$route.params, { id }) }) }
4 其他
文中已將本人常用的iview router控制方式提出,或有未涉及者,根據(jù)以下了解大概也可解決:
app.js中的state.tagNavList是標(biāo)簽頁中顯示的標(biāo)簽集合;
如果要改變一些內(nèi)容,main.vue中對$route的監(jiān)控是事件發(fā)起的開端,可考慮從這里修改;
- 淺談vue的iview列表table render函數(shù)設(shè)置DOM屬性值的方法
- vue iview組件表格 render函數(shù)的使用方法詳解
- vue中使用iview自定義驗證關(guān)鍵詞輸入框問題及解決方法
- iview給radio按鈕組件加點擊事件的實例
- iview table高度動態(tài)設(shè)置方法
- vue+iview 實現(xiàn)可編輯表格的示例代碼
- 在uiview 的tableView中點擊cell進(jìn)入跳轉(zhuǎn)到另一個界面的實現(xiàn)方法
- 完美解決iview 的select下拉框選項錯位的問題
- iview日期控件,雙向綁定日期格式的方法
相關(guān)文章
Vue+Element UI實現(xiàn)概要小彈窗的全過程
彈窗效果是我們?nèi)粘i_發(fā)中經(jīng)常遇到的一個功能,下面這篇文章主要給大家介紹了關(guān)于Vue+Element UI實現(xiàn)概要小彈窗的相關(guān)資料,需要的朋友可以參考下2021-05-05vue子組件封裝彈框只能執(zhí)行一次的mounted問題及解決
這篇文章主要介紹了vue子組件封裝彈框只能執(zhí)行一次的mounted問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03淺談vue中$event理解和框架中在包含默認(rèn)值外傳參
這篇文章主要介紹了淺談vue中$event理解和框架中在包含默認(rèn)值外傳參,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08vue相同路由跳轉(zhuǎn)強(qiáng)制刷新該路由組件操作
這篇文章主要介紹了vue相同路由跳轉(zhuǎn)強(qiáng)制刷新該路由組件操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08vue3 el-form-item如何自定義label標(biāo)簽內(nèi)容
這篇文章主要介紹了vue3 el-form-item如何自定義label標(biāo)簽內(nèi)容問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10