iviewベースのrouter常用制御方式


1 iviewのrouter制御需要
最近はiviewフレームワークを使ってプロジェクトを書いていますが、ルートコントロール上の問題に遭遇しました。解決過程にも心得があります。ここに記録します。
各項目は開発時、tags(ラベルページ)のような制御要求は全部同じではないので、ここに記載した項目のラベルページに対する制御要求を先にリストします。
  • は同名のルートラベルページに対して複数のページを開けてはいけません。例えば商品リストから商品の展示ラベルページを開けて、すでに開いている商品編集ページがあれば、代替します。新しく開けたものは保存されていません。保存されているラベルページは一つしかありません。
  • 新しいページを置き換えるときは、切り換えて元のページの内容(つまり、実際に記録されたparamsは差し替え後に変化すべき)に切り替えます。同様の場合は、保存済みのデータがまだ保存されていないこと、保存及び機能が追加されていることも含まれます。
  • 2 vueによるrouter制御
    iviewはvueのフレームワークに基づいていますので、vue自身が持つrouter制御方法は必ず実行できます。
    vue変更ルートの常用方法は以下の通りです。
    
    //      (     ,       )
    this.$router.push({
      name:'routerName',
      params:routerParam
    })
    //      (     )
    this.$router.replace({
      name:'routerName',
      routerParam
    })
    
    公式ルートの変更は確かに正常にタブページを開くことができますが、1で述べた様々なニーズを実現するには、いくつかの需要が満たされていません。そのためには、3の中で、どのようにiviewのouter制御に基づいているかを参照してください。
    3 iviewによるrouter制御
    iviewはルートを制御する時、vuexのap.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法によりタブページを開くロジックを実現していますが、メソッド内部にはメモページの表示効果の変化(内部データの変化を含む、以下同じ)を反映していません。
    このように、左メニューから新しいタブを開くだけでなく、変化を表示する効果が得られます。他には、vueのオリジナルプッシュなどを使ってrouterを変更する方法があれば、監視できます。
    現在のタブの表示効果に影響を与えるのは'src/store/module/ap.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(ルートが存在するかどうか)です。この方法も同じタブページかどうかを判断する鍵となるノードです。
    
    /**
     *                          
     */
    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に変わります。
    3.2どうやって需要を実現しますか?
    3.1の操作を行った後、問題は部分的に解決されました。残りの問題は需要1.2が実現されて解決されていないことです。
    まず、どのようにリストから開くか、または新規作成するかを実現するには、元のタブページを置き換えると、元のタブページに戻りません。タブページのパラメータを変更する方法をap.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)
      }
    },
    
    その次に、もし像が保存して新たに増加することがあるならば、あるいは保存してすでに保存したことがなくて、この2種類の情況は往復して切り替えた後にもとの情況に戻りません。
    保存と追加、鍵は「追加」効果です。
    
    //     ,         
    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 })
     })
    }
    
    4その他
    本文ではすでに本人がよく使うiview router制御方式を提出しました。または未関係者がいます。以下の理解によっても解決できます。
    app.jsのstate.tagNavListはラベルページに表示されているラベルのセットです。
    もしいくつかの内容を変えるならば、main.vueの中で$routeに対する監視は事件の開始のきっかけで、ここから改正することを考慮することができます。