中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何實現基于iview的router常用控制方式

發布時間:2021-08-18 15:28:29 來源:億速云 閱讀:203 作者:小新 欄目:web開發

這篇文章將為大家詳細講解有關如何實現基于iview的router常用控制方式,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

1 iview的router控制需求

最近在使用iview框架寫項目,遇到了一些路由控制上的問題,解決過程中也有一些心得,故在此記錄下來.
每個項目在開發時,對于類似tags(標簽頁)的控制需求都不盡相同,故以下先列出本文所述項目對標簽頁的控制要求(如有不同需求,本文當也可提供一些思路):

  1. 對于同名(name)的路由標簽頁,不能打開多個.譬如說從商品列表中打開商品展示標簽頁,如果已經有在打開的商品編輯頁面,則替換之.新打開的,未保存,已保存的標簽頁,同時只能存在一個(即不同params相同name的route只能有一個);

  2. 替換掉一個新的頁面時,通過切換的方式切換回來(先切到其他標簽頁再切換回來),仍是原來頁面的內容(即實際記錄的params在替換后應變化).類似的情況,還應包含單據從未保存到已保存,以及保存并新增功能;

2 基于vue的router控制

iview是基于vue的框架,故vue本身自帶的router控制方法是必然可行的.

vue變更路由的常用方式參考以下(該方法在官方api中有更詳細的介紹):

//變更當前路由(有歷史記錄,建議使用此方式)
this.$router.push({
  name:'routerName',
  params:routerParam
})
//變更當前路由(無歷史記錄)
this.$router.replace({
  name:'routerName',
  routerParam
})

官方路由變更確實可以正常打開標簽頁,但在實現1中所提到的各種需求的時候,就有些不滿足需求了.為此,需要參考3中,如何基于iview的outer控制.

3 基于iview的router控制

iview在控制路由的時候,使用vuex中的app.js來記錄標簽頁路由信息,如果對vuex還是很了解的話,可以通過這篇博文來先打一下基礎.

3.1 如何實現需求1.1

想要實現不同params相同name的route在iview中只能有一個,關鍵是改變iview對路由相等的判斷方法,即'/src/libs/util.js'里的routeEqual方法:

/**
 * @description 根據name/params/query判斷兩個路由對象是否相等
 * @param {*} route1 路由對象
 * @param {*} route2 路由對象
 */
export const routeEqual = (route1, route2) => {
 return route1.name === route2.name
 // 此處改變相同路由的判斷方式,改為name相同即認為相同
 // 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)
}

這里稍微解釋下(如果不關注原因,可以直接看3.2).當改變路由時,'src\components\main\main.vue'作為近乎頂層的組件控制著近乎所有的全局邏輯,其中就有對路由的監控:

...
<side-menu
accordion
ref="sideMenu"
:active-name="$route.name"
:collapsed="collapsed"
@on-select="turnToPage"
:menu-list="menuList"
>
...
  //此方法隸屬于methods,用以監控side-menu的選擇事件,即平時從左側菜單打開標簽頁的邏輯
  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方法實現打開標簽頁的邏輯,但方法內部并沒有體現便簽頁顯示效果變化(包含內部數據變化,以下同)的邏輯,這是由于顯示效果變化的邏輯,由對$router的監控實現.

這樣,不止從左側菜單打開新標簽頁可以實現顯示變化效果,其他只要使用vue的原版push等方法改變router的方法,均可監測到.

逐步查看下各個方法,其中影響當前標簽頁顯示效果的,是'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])
 }
},

盡管方法內部仍調用了很多,其中一個很重要的判斷,就是routeHasExist(路由是否存在),這個方法也是判斷是否為相同標簽頁的一個關鍵節點(該方法同樣在util.js):

/**
 * 判斷打開的標簽列表里是否已存在這個新添加的路由對象
 */
export const routeHasExist = (tagNavList, routeItem) => {
 let len = tagNavList.length
 let res = false
 doCustomTimes(len, (index) => {
  if (routeEqual(tagNavList[index], routeItem)) res = true
 })
 return res
}

明顯可以看出,這個方法內調用routeEqual,就是用以判斷是否為相同路由的實際方法(當然是通過比較新路由與已有路由進行比較),如此,僅需改變routeEqual即可.

以防萬一,全局搜索下調用這個routeEqual的所有方法,發現所有調用的地方再routeEqual在改變后不會出現新的問題.

3.2 如何實現需求1.2

在進行3.1的操作后,問題得到了部分解決.余下的問題在于需求1.2沒有得到實現和解決.

首先是,如何實現從列表中打開或新建的,替換原來的標簽頁,在來回切換后不會回到原來的標簽頁. 只需在app.js中注冊改變標簽頁參數的方法:

// 變更指定路由的參數
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的監控最后引用即可.

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)
   // 增加路由參數變更環節
   this.changeTagParams(newRoute)
  }
},

其次,如果出現像保存并新增,或者從未保存到已保存,這兩種情況來回切換后不會回到原來的情況.

保存并新增,關鍵是"新增"效果:

// 清空數據,該方法在保存后調用
clearData () {
 //該部分是用來清除當前route的參數
 this.$router.push({
  params: Object.assign(this.$route.params, { id: undefined })
 })
 //這部分代碼是用來清空當前頁面內容,每個模塊都不盡相同,不必模仿
 this.mOtherExpense = JSON.parse(JSON.stringify(this.mOtherExpenseInitial))
 this.tableData = [{}]
 this.loadCode()
 this.mOtherExpense.openingDate = new Date()
},

從未保存到已保存,關鍵同樣是如何讓route記住新的id(或其他參數):

// 設置路由id,該方法在第一次保存后調用
setData (id) {
 //這里的id是保存后從后臺傳來的新id
 this.$router.push({
  params: Object.assign(this.$route.params, { id })
 })
}

關于“如何實現基于iview的router常用控制方式”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

务川| 雷州市| 富源县| 屏东县| 华阴市| 凤庆县| 长丰县| 玉溪市| 南通市| 电白县| 砚山县| 台南市| 集贤县| 博罗县| 耿马| 光泽县| 正安县| 汉中市| 土默特右旗| 凭祥市| 阿鲁科尔沁旗| 兴安县| 神农架林区| 沁水县| 庐江县| 淮阳县| 宣城市| 陵水| 五家渠市| 镇雄县| 莱西市| 丰镇市| 乌拉特后旗| 山西省| 神池县| 波密县| 固镇县| 隆子县| 岳西县| 桃江县| 独山县|