vue-admin-template 動的ルーティング実装例

vue-admin-template 動的ルーティング実装例

ログインを提供し、ユーザー情報データインターフェースを取得する

api/user.js内

'@/utils/request' からリクエストをインポートします
定数API = {
  テイクアウト: '/student/students/takeOut/',
  ログイン: '/student/students/loginIn/',
  学生情報:'/student/students/studentInfo/',
}
エクスポート関数ログイン(パラメータ) {
  リクエストを返す({
    url: Api.LoginIn、
    メソッド: 'get'、
    パラメータ: パラメータ
  })
}

エクスポート関数 getInfo(トークン) {
  リクエストを返す({
    url: Api.StudentInfo、
    メソッド: 'get'、
    パラメータ: {'トークン':トークン}
  })
}

エクスポート関数logout() {
  リクエストを返す({
    url: Api.TakeOut、
    メソッド: 'get'
  })
}

ログインインターフェースデータ

{'code': 200、'data': {'token': 'X-admin'}、'message': "操作は成功しました"}

終了インターフェースデータ

{'code': 200、'data': 'success'、'message': "操作は成功しました"}

詳細なインターフェースデータ

{
    「コード」: 200,
    "データ": {
        「アバター」: 「https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif」、
        "名前": "黄暁国",
        「役割」: [
            "エディタ"
        ]
    }
}

router/index.js を変更する

'vue' から Vue をインポートします
'vue-router' から Router をインポートします。

Vue.use(ルーター)

/* レイアウト */
'@/layout' からレイアウトをインポートします

// 基本的なルーティング export const constantRoutes = [
  {
    パス: '/login',
    コンポーネント: () => import('@/views/login/index'),
    非表示: true
  },

  {
    パス: '/404',
    コンポーネント: () => import('@/views/404'),
    非表示: true
  },

  {
    パス: '/'、
    コンポーネント: レイアウト、
    リダイレクト: '/dashboard',
    子供たち: [{
      パス: 'ダッシュボード',
      名前: 'ダッシュボード'、
      コンポーネント: () => import('@/views/dashboard/index'),
      meta: { title: 'ホーム', icon: 'el-icon-menu' }
    }]
  },
]

/**
 * 動的ルーティング */
エクスポートconst asyncRoutes = [
  {
    パス: '/studentinformation',
    コンポーネント: レイアウト、
    子供たち: [
      {
        パス: 'インデックス',
        コンポーネント: () => import('@/views/studentinformation/index'),
        meta: { title: '学生情報', icon: 'el-icon-s-check' }
      }
    ]
  },
  {
    パス: '/lecturerinformation',
    コンポーネント: レイアウト、
    子供たち: [
      {
        パス: 'インデックス',
        コンポーネント: () => import('@/views/lecturerinformation/index'),
        meta: { title: '講師情報', icon: 'el-icon-s-custom', roles: ['編集者'] }
      }
    ]
  },
  {
    パス: '/coursemanage',
    コンポーネント: レイアウト、
    メタ: { ロール: ['admin'] },
    子供たち: [
      {
        パス: 'インデックス',
        コンポーネント: () => import('@/views/coursemanage/index'),
        meta: { title: 'コース管理', icon: 'el-icon-s-platform'}
      }
    ]
  },
  // 404 ページは最後のページに配置する必要があります { path: '*', redirect: '/404', hidden: true }
]

const createRouter = () => 新しいルーター({
  // モード: 'history'、// サービスサポートが必要
  スクロール動作: () => ({ y: 0 }),
  ルート: 定数ルート
})

定数ルーター = createRouter()

// 詳細については、https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465 を参照してください。
エクスポート関数resetRouter() {
  定数 newRouter = createRouter()
  router.matcher = newRouter.matcher // ルーターをリセットする
}

デフォルトルーターをエクスポートする

動的に表示されるルートをasyncRoutesに記述し、ロールを追加します。例:meta: { roles: ['admin'] },

store/modulesディレクトリにpermission.jsを追加します。

'@/router' から { asyncRoutes, constantRoutes } をインポートします。

/**
 * meta.roleを使用して、現在のユーザーに権限があるかどうかを判断します
 * @param ロール
 * @param ルート
 */
関数hasPermission(ロール、ルート) {
  ルートメタとルートメタロールの場合{
    roles.some(role => route.meta.roles.includes(role)) を返します
  } それ以外 {
    真を返す
  }
}

/**
 * 再帰による非同期ルーティングテーブルをフィルタリングする
 * @param ルート asyncRoutes
 * @param ロール
 */
関数 filterAsyncRoutes(ルート、ロール) をエクスポートします。
  定数res = []

  ルート.forEach(ルート => {
    const tmp = { ...ルート }
    権限がある場合(ロール、tmp){
      tmp.children の場合 {
        tmp.children = filterAsyncRoutes(tmp.children, ロール)
      }
      res.push(tmp)
    }
  })

  戻り値
}

定数状態 = {
  ルート: [],
  ルートを追加: []
}

const 変異 = {
  SET_ROUTES: (状態、ルート) => {
    state.addRoutes = ルート
    state.routes = constantRoutes.concat(routes)
  }
}

定数アクション = {
  ルートを生成する({コミット}, ロール) {
    新しいPromiseを返します(resolve => {
      const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      commit('SET_ROUTES', アクセスされたルート)
      解決(アクセスされたルート)
    })
  }
}

エクスポートデフォルト{
  名前空間: true、
  州、
  突然変異、
  アクション
}

store/modulds/user.js を変更する

'@/api/user' から { login, logout, getInfo } をインポートします。
'@/utils/auth' から { getToken、setToken、removeToken } をインポートします。
'@/router' から { resetRouter } をインポートします

定数 getDefaultState = () => {
  戻る {
    トークン: getToken(),
    名前: ''、
    アバター: ''、
    役割: []
  }
}

定数状態 = getDefaultState()

const 変異 = {
  RESET_STATE: (状態) => {
    オブジェクトに状態を割り当て、デフォルトの状態を取得します。
  },
  SET_TOKEN: (状態、トークン) => {
    state.token = トークン
  },
  SET_NAME: (状態、名前) => {
    状態.name = 名前
  },
  SET_AVATAR: (状態、アバター) => {
    state.avatar = アバター
  },
  SET_ROLES: (状態、ロール) => {
    state.roles = 役割
  }
}

定数アクション = {
  // ユーザーログイン
  ログイン({コミット}, ユーザー情報) {
    const { ユーザー名, パスワード } = userInfo
    新しい Promise を返します ((resolve, reject) => {
      login({ ユーザー名: username.trim(), パスワード: password }).then(レスポンス => {
        const { データ } = レスポンス
        コミット('SET_TOKEN'、データ.token)
        setToken(データトークン)
        解決する()
      }).catch(エラー => {
        拒否(エラー)
      })
    })
  },

  // ユーザー情報を取得する
  getInfo({ コミット、状態 }) {
    新しい Promise を返します ((resolve, reject) => {
      getInfo(state.token).then(レスポンス => {
        const { データ } = レスポンス

        if (!データ) {
          拒否を返します('認証に失敗しました。再度ログインしてください')
        }

        const { ロール、名前、アバター } = データ
        コミット('SET_ROLES', ロール)
        コミット('SET_NAME', 名前)
        コミット('SET_AVATAR', アバター)
        解決(データ)
      }).catch(エラー => {
        拒否(エラー)
      })
    })
  },

  // ユーザーログアウト
  ログアウト({コミット、状態}) {
    新しい Promise を返します ((resolve, reject) => {
      logout(state.token).then(() => {
        removeToken() // 最初にトークンを削除する必要があります
        ルータをリセットする()
        コミット('RESET_STATE')
        コミット('SET_ROLES', [])
        解決する()
      }).catch(エラー => {
        拒否(エラー)
      })
    })
  },

  // トークンを削除
  resetToken({コミット}) {
    新しいPromiseを返します(resolve => {
      removeToken() // 最初にトークンを削除する必要があります
      コミット('RESET_STATE')
      コミット('SET_ROLES', [])
      解決する()
    })
  }
}

エクスポートデフォルト{
  名前空間: true、
  州、
  突然変異、
  アクション
}

ロールの追加: [] 権限リストを保存するには、次の内容を追加します

定数 getDefaultState = () => {
  戻る {
    ...
    役割: []
  }
}

const 変異 = {
  ...
  SET_ROLES: (状態、ロール) => {
    state.roles = 役割
  }
}

  // ユーザー情報を取得する
  getInfo({ コミット、状態 }) {
    新しい Promise を返します ((resolve, reject) => {
      getInfo(state.token).then(レスポンス => {
        ...
        const { ロール、名前、アバター } = データ
        コミット('SET_ROLES', ロール)
        ...
      }).catch(エラー => {
        拒否(エラー)
      })
    })
  },

  // ユーザーログアウト
  ログアウト({コミット、状態}) {
    新しい Promise を返します ((resolve, reject) => {
      logout(state.token).then(() => {
        ...
        コミット('SET_ROLES', [])
        ...
      }).catch(エラー => {
        拒否(エラー)
      })
    })
  },

  // トークンを削除
  resetToken({コミット}) {
    新しいPromiseを返します(resolve => {
      ...
      コミット('SET_ROLES', [])
      ...
    })
  }
}

store/getters.js にロールを追加する

const ゲッター = {
  サイドバー: 状態 => state.app.sidebar、
  デバイス: 状態 => state.app.device、
  トークン: 状態 => state.user.token、
  アバター: 状態 => state.user.avatar,
  名前: 状態 => state.user.name,
  
  //ロールを追加
  ロール: 状態 => state.user.roles、
  //動的ルーティング permission_routes: state => state.permission.routes,
}
デフォルトのゲッターをエクスポートする

store/index.js に権限を追加する

'vue' から Vue をインポートします
'vuex' から Vuex をインポートします
'./getters' からゲッターをインポートします
'./modules/app' からアプリをインポートします
'./modules/settings' から設定をインポートします
'./modules/user' からユーザーをインポートします

//権限を追加
'./modules/permission' から権限をインポートします

Vue.use(Vuex)

定数ストア = 新しい Vuex.Store({
  モジュール:
    アプリ、
    設定、
    ユーザー、
    
 //権限を追加
    許可
  },
  ゲッター
})

デフォルトストアをエクスポート

最後にルートディレクトリのpermission.jsを変更します。

'./router' から router, { constantRoutes } をインポートします。
'./store' からストアをインポートします
'element-ui' から { Message } をインポートします
import NProgress from 'nprogress' // プログレスバー
import 'nprogress/nprogress.css' // プログレスバーのスタイル
import { getToken } from '@/utils/auth' // クッキーからトークンを取得
'@/utils/get-page-title' から getPageTitle をインポートします。

NProgress.configure({ showSpinner: false }) // NProgress の設定

const whiteList = ['/login'] // リダイレクトホワイトリストなし

router.beforeEach(非同期(to, from, next) => {
  // プログレスバーを開始
  NProgress.start()

  // ページタイトルを設定する
  document.title = getPageTitle(to.meta.title)

  // ユーザーがログインしているかどうかを判定する
  定数hasToken = getToken()

  (トークンを持っている場合){
    to.path === '/login'の場合{
      // ログインしている場合はホームページにリダイレクトします
      次へ({ パス: '/' })
      NProgress.done()
    } それ以外 {
      定数hasRoles = store.getters.roles && store.getters.roles.length > 0
      役割がある場合
        次()
      } それ以外 {
        試す {
          // ユーザー情報を取得する
          // 注意: ロールはオブジェクト配列である必要があります。例: ['admin'] または ['developer','editor']
          const { roles } = store.dispatch('user/getInfo') を待機します。
          console.log(ロール)
          // ロールに基づいてアクセス可能なルートマップを生成する
          const accessRoutes = store.dispatch('permission/generateRoutes', roles) を待機します
          // アクセス可能なルートを動的に追加
          router.options.routes = constantRoutes.concat(accessRoutes)
          ルータ.addRoutes(アクセスルート)
          
          // addRoutes が完了していることを確認するためのハックメソッド
          // replace: true を設定すると、ナビゲーションは履歴レコードを残さなくなります
          次({ ...to, 置き換え: true })
        } キャッチ(エラー){
          // トークンを削除し、ログインページに移動して再度ログインします
          store.dispatch('user/resetToken') を待機します。
          Message.error(error || 'エラーあり')
          次へ(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } それ以外 {
    /* トークンがありません*/

    (whiteList.indexOf(to.path) !== -1) の場合 {
      // 無料ログインホワイトリストでは、直接
      次()
    } それ以外 {
      // アクセス権限のない他のページはログイン ページにリダイレクトされます。
      次へ(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

ルータ.afterEach(() => {
  // 進捗バーを終了する
  NProgress.done()
})

ナビゲーションバーにデータをバインドする

layout/components/sidebar/index.vue内

...mapGetters([
      // 動的ルーティングは permission_routes を追加します
      'permission_routes',
      「サイドバー」
    ])、

 <!-- 動的ルーティング -->
 <sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />

完全なコードは次のとおりです。

<テンプレート>
  <div :class="{ 'has-logo': showLogo }">
    <logo v-if="showLogo" :collapse="isCollapse" />
    <el-scrollbar wrap-class="スクロールバーラッパー">
      <el-メニュー
        :default-active="アクティブメニュー"
        :collapse="折りたたむ"
        :background-color="変数.menuBg"
        :text-color="変数.menuText"
        :unique-opened="false"
        :active-text-color="variables.menuアクティブテキスト"
        :collapse-transition="false"
        モード="垂直"
      >
        <!-- <サイドバー項目
          v-for="ルート内のルート"
          :key="ルートパス"
          :item="ルート"
          :base-path="ルートパス"
        /> -->
        <サイドバー項目
          v-for="permission_routes 内のルート"
          :key="ルートパス"
          :item="ルート"
          :base-path="ルートパス"
        />
      </el-menu>
    </el-スクロールバー>
  </div>
</テンプレート>

<スクリプト>
'vuex' から { mapGetters } をインポートします。
'./Logo' からロゴをインポートします
'./SidebarItem' から SidebarItem をインポートします。
'@/styles/variables.scss' から変数をインポートします

エクスポートデフォルト{
  コンポーネント: { サイドバーアイテム、ロゴ },
  計算: {
    ...mapGetters([
      // 動的ルーティングは permission_routes を追加します
      'permission_routes',
      「サイドバー」、
    ])、
    ルート() {
      これを返します。$router.options.routes
    },
    アクティブメニュー() {
      const ルート = this.$route
      const { meta, path } = ルート
      // パスを設定すると、サイドバーに設定したパスがハイライト表示されます
      メタアクティブメニューの場合
        meta.activeMenu を返す
      }
      戻り経路
    },
    表示ロゴ() {
      これを返します。$store.state.settings.sidebarLogo
    },
    変数() {
      変数を返す
    },
    折りたたみ() {
      !this.sidebar.opened を返す
    },
  },
}
</スクリプト>

vue-admin-template 動的ルーティングの実装に関するこの記事はこれで終わりです。vue-admin-template 動的ルーティングの実装の詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • vue-admin-template はクイックナビゲーションコード(タブナビゲーションバー)を構成します。
  • vue-admin-template を使用した最適化プロセスの詳細な説明
  • vue-admin-template テンプレートに tagsview を追加する実装

<<:  HTML 初心者のためのベストプラクティス 15 選

>>:  CSSはBEM命名規則の実践を使用する

推薦する

CSS で QR コードスキャンボックスを実装するためのサンプルコード

カメラを開くと通常はスキャンボックスが表示されますが、静的なQRコードではフォーカスを合わせたりスキ...

Django プロジェクトを作成して MySQL に接続する方法

1: django-admin.py startproject プロジェクト名2: cd プロジェク...

mysql8.0.11データディレクトリ移行の実装

mysql のデフォルトのストレージ ディレクトリは/var/lib/mysql/です。以下は、デフ...

Excel エクスポートは docker 環境では常に失敗する

Excel のエクスポートは、docker 環境では常に失敗します。最も直接的な原因は、中国語フォン...

CSS フレックスレイアウトのリストの最後の行を左揃えにする N 通りの方法 (要約)

張新旭氏の記事を引用して皆さんにシェアしたいと思います。 変更を加えたい場合は、対応する画像によって...

CSS3 アドバンス LESS で星空アニメーションを実装するサンプルコード

この記事では、星空アニメーションを実現するための高度な CSS3 LESS のサンプルコードを次のよ...

MongoDBのパフォーマンスを向上させる方法

MongoDB は高性能なデータベースですが、使用していくうちにパフォーマンスの問題が発生することが...

nginxリバースプロキシを介したデバッグコードの実装

背景現在、会社のプロジェクトは、フロントエンドとバックエンドが分離された方法で開発されています。新し...

MySQL ビューの紹介と基本操作のチュートリアル

序文ビューは、データベース システム内で非常に便利なデータベース オブジェクトです。 MySQL 5...

Dockerコンテナの中国語言語パックの設定の問題を解決する

Dockerでdocker search centosを使用する場合docker pull dock...

Linux環境でOpenSSL証明書を生成する

1. 環境: CentOS7、OpenSSL1.1.1k。 2. コンセプト:ルート証明書: サーバ...

Dockerでの接続例外中のエラーを解決する

Docker を初めて使い始めると、通常とは異なる問題に遭遇して、必然的に混乱してしまいます。大丈夫...

CSS でよく使用されるフォントサイズ、フォント単位、行の高さの詳細な説明

px(ピクセル)ピクセルという言葉は皆さんもよくご存知だと思います。次に、この単位に関するちょっとし...

Vueはタブを切り替えてデータの状態を維持する3つの方法を実装します

Vue でタブ切り替えを実装する 3 つの方法1. v-showはコンテンツの切り替えを制御します1...