Rumah  >  Artikel  >  hujung hadapan web  >  Bagaimana untuk memuatkan menu dinamik dalam Vue3

Bagaimana untuk memuatkan menu dinamik dalam Vue3

PHPz
PHPzke hadapan
2023-05-10 13:58:062067semak imbas

1. Idea keseluruhan

Pertama sekali, mari kita susun idea pelaksanaan keseluruhan Pertama sekali: Idea keseluruhannya sama persis dengan vhr.

Memandangkan sesetengah rakan mungkin terlupa idea pelaksanaan menu dinamik bahagian hadapan dalam vhr, artikel ini akan menganalisisnya bersama anda.

Untuk memastikan data menu boleh diakses dalam semua .vue fail, kami memilih untuk menyimpan data menu dalam vuex ialah tempat biasa untuk menyimpan data dalam Semua .vue Fail boleh membaca data daripada vuex. Data yang disimpan dalam vuex pada asasnya disimpan dalam ingatan, jadi ia mempunyai ciri bahawa selepas penyemak imbas menekan F5 untuk memuat semula, data itu hilang. Jadi apabila lompat halaman berlaku, kita harus membezakan sama ada lompat halaman berlaku selepas pengguna mengklik butang menu pada halaman atau sama ada lompat halaman berlaku selepas pengguna mengklik butang muat semula penyemak imbas (atau menekan F5).

Untuk mencapai ini, kami perlu menggunakan fungsi pengawal navigasi laluan dalam vue Bagi kami jurutera Java, ini mungkin terdengar agak asing, tetapi anda boleh menganggapnya sebagai Penapis di Java memahami. Sebenarnya, kami menggunakan analogi ini apabila menerangkannya kepada rakan-rakan kami dalam video. Ia mudah difahami dengan membandingkan perkara baru dengan perkara yang sudah biasa dalam fikiran kami.

Pengawal navigasi dalam vue adalah seperti monitor Ia boleh memantau semua lompatan halaman, kita boleh menilai sama ada data menu dalam vuex masih ada, Ini bermakna bahawa pengguna mengklik butang menu pada halaman untuk menyelesaikan lompatan Jika ia tidak ada, ia bermakna pengguna mengklik butang muat semula pelayar atau menekan F5 untuk memuat semula halaman Pada masa ini, kita perlu pergi ke pelayan dengan cepat. Muat semula data menu.

---xxxxxxxxxxxxxxxxxxxxx---

Idea pelaksanaan keseluruhan adalah seperti ini. Seterusnya, mari kita lihat beberapa butiran pelaksanaan khusus.

2. Butiran pelaksanaan

2.1 Memuatkan butiran

Pertama, mari kita lihat butiran pemuatan.

Seperti yang anda ketahui, pintu masuk ke projek satu halaman ialah main.js Kandungan yang dimuatkan oleh laluan adalah dalam fail src/permission.js. Fail ini diperkenalkan dalam main.js dan dalam src /permission.js Kandungan pengawal navigasi hadapan adalah seperti berikut:

router.beforeEach((to, from, next) => {
  NProgress.start()
  if (getToken()) {
    to.meta.title && useSettingsStore().setTitle(to.meta.title)
    /* has token*/
    if (to.path === '/login') {
      next({ path: '/' })
      NProgress.done()
    } else {
      if (useUserStore().roles.length === 0) {
        isRelogin.show = true
        // 判断当前用户是否已拉取完user_info信息
        useUserStore().getInfo().then(() => {
          isRelogin.show = false
          usePermissionStore().generateRoutes().then(accessRoutes => {
            // 根据roles权限生成可访问的路由表
            accessRoutes.forEach(route => {
              if (!isHttp(route.path)) {
                router.addRoute(route) // 动态添加可访问路由表
              }
            })
            next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
          })
        }).catch(err => {
          useUserStore().logOut().then(() => {
            ElMessage.error(err)
            next({ path: '/' })
          })
        })
      } else {
        next()
      }
    }
  } else {
    // 没有token
    if (whiteList.indexOf(to.path) !== -1) {
      // 在免登录白名单,直接进入
      next()
    } else {
      next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
      NProgress.done()
    }
  }
})

Biar saya membimbing anda melalui idea dalam pengawal navigasi hadapan ini:

  • Panggil dahulu Kaedah getToken ini sebenarnya adalah untuk mendapatkan token pengesahan daripada kuki, iaitu rentetan JWT yang dikembalikan oleh hujung belakang ke hujung hadapan selepas berjaya log masuk.

  • Jika kaedah getToken mempunyai nilai pulangan, bermakna pengguna telah log masuk, kemudian masukkan cawangan if Jika getToken tidak mendapat nilai, bermakna pengguna itu tidak log masuk. Jika tidak, ia terbahagi kepada Terdapat dua situasi: i: alamat sasaran yang diakses berada dalam senarai putih tanpa log masuk, maka anda boleh mengaksesnya secara langsung ii: alamat sasaran yang diakses tiada dalam senarai putih, kemudian anda akan melompat ke halaman log masuk pada masa ini, melompat Pada masa yang sama, ia membawa parameter ubah hala, supaya selepas log masuk berjaya, ia adalah mudah untuk melompat kembali ke halaman sasaran yang dilawati. Senarai putih untuk akses tanpa log masuk ini ialah pembolehubah yang ditakrifkan dalam fail src/permission.js Terdapat empat laluan lalai, iaitu ['/login', '/auth-redirect', '/bind', '/register'].

  • Jika getToken mendapat nilai, ini bermakna pengguna telah log masuk. Pada masa ini, terdapat situasi yang berbeza: jika laluan yang diakses pengguna ialah halaman log masuk, kemudian ubah halanya ke halaman utama projek (juga, jika pengguna sudah log masuk, pengguna tidak dibenarkan mengakses halaman log masuk semula jika laluan yang diakses pengguna bukan halaman log masuk, kemudian tentukan dahulu sama ada peranan dalam vuex masih ada nilai? Jika ada nilai, bermakna pengguna mengklik butang menu untuk melompat, jadi melompat terus jika tiada nilai, bermakna pengguna menekan butang penyegar semula atau butang F5 untuk menyegarkan halaman panggil kaedah getInfo (terletak dalam fail src/store/modules/user.js) untuk memuat semula maklumat asas pengguna semasa, maklumat peranan dan maklumat kebenaran pada pelayan, dan kemudian panggil kaedah generateRoutes (terletak dalam src/store/modules /permission.js) pergi ke pelayan untuk memuatkan maklumat penghalaan, dan letakkan maklumat penghalaan yang dimuatkan ke dalam objek penghala (dengan syarat objek penghalaan ini bukan pautan http, tetapi alamat penghalaan biasa).

Ini ialah idea keseluruhan untuk memuatkan penghalaan dinamik.

Dalam langkah ketiga, dua kaedah terlibat, satu ialah getInfo dan satu lagi adalah generateRoutes Kedua-dua kaedah ini juga penting.

2.2 getInfo

Pertama sekali, kaedah memuatkan maklumat pengguna ini terletak dalam fail src/store/modules/user.js Dengan kata lain, selepas maklumat asas pengguna ini dimuatkan, ia disimpan dalam vuex. Jika anda menyegarkan penyemak imbas Data ini akan hilang:

getInfo() {
  return new Promise((resolve, reject) => {
    getInfo().then(res => {
      const user = res.user
      const avatar = (user.avatar == "" || user.avatar == null) ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
      if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
        this.roles = res.roles
        this.permissions = res.permissions
      } else {
        this.roles = ['ROLE_DEFAULT']
      }
      this.name = user.userName
      this.avatar = avatar;
      resolve(res)
    }).catch(error => {
      reject(error)
    })
  })
},

Logik kaedah itu sebenarnya tidak banyak yang boleh dikatakan jika digabungkan dengan format JSON yang dikembalikan oleh pelayan, ia sepatutnya mudah difahami (. sebahagian daripada JSON):

{
    "permissions":[
        "*:*:*"
    ],
    "roles":[
        "admin"
    ],
    "user":
        "userName":"admin",
        "nickName":"TienChin健身",
        "avatar":"",
    }
}

另外再强调下,之前在 vhr 中,我们是将请求封装成了一个 api.js 文件,里边有常用的 get、post、put 以及 delete 请求等,然后在需要使用的地方,直接去调用这些方法发送请求即可,但是在 TienChin 中,脚手架的封装是将所有的请求都提前统一封装好,在需要的时候直接调用封装好的方法,连请求地址都不用传递了(封装的时候就已经写死了),所以小伙伴们看上面的 getInfo 方法只有方法调用,没有传递路径参数等。

2.3 generateRoutes

generateRoutes 方法则位于 src/store/modules/permission.js 文件中,这里值得说道的地方就比较多了:

generateRoutes(roles) {
  return new Promise(resolve => {
    // 向后端请求路由数据
    getRouters().then(res => {
      const sdata = JSON.parse(JSON.stringify(res.data))
      const rdata = JSON.parse(JSON.stringify(res.data))
      const defaultData = JSON.parse(JSON.stringify(res.data))
      const sidebarRoutes = filterAsyncRouter(sdata)
      const rewriteRoutes = filterAsyncRouter(rdata, false, true)
      const defaultRoutes = filterAsyncRouter(defaultData)
      const asyncRoutes = filterDynamicRoutes(dynamicRoutes)
      asyncRoutes.forEach(route => { router.addRoute(route) })
      this.setRoutes(rewriteRoutes)
      this.setSidebarRouters(constantRoutes.concat(sidebarRoutes))
      this.setDefaultRoutes(sidebarRoutes)
      this.setTopbarRoutes(defaultRoutes)
      resolve(rewriteRoutes)
    })
  })
}

首先大家看到,服务端返回的动态菜单数据解析了三次,分别拿到了三个对象,这三个对象都是将来要用的,只不过使用的场景不同,下面结合页面的显示跟大家细说。

  • 首先是调用 filterAsyncRouter 方法,这个方法的核心作用就是将服务端返回的 component 组件动态加载为一个 component 对象。不过这个方法在调用的过程中,后面还有两个参数,第二个是 lastRouter 在该方法中并无实质性作用;第三个参数则主要是说是否需要对 children 的 path 进行重写。小伙伴们知道,服务端返回的动态菜单的 path 属性都是只有一层的,例如一级菜单系统管理的 path 是 system,二级菜单用户管理的 path 则是 user,那么用户管理最终访问的 path 就是 system/path,如果第三个参数为 true,则会进行 path 的重写,将 path 最终设置正确。

  • 所以这里的 sidebarRoutes 和 defaultRoutes 只是能用于菜单渲染(因为这两个里边的菜单 path 不对),而最终的页面跳转要通过 rewriteRoutes 才可以实现。

  • 除了服务端返回的动态菜单,前端本身也定义了一些基础菜单,前端的基础菜单分为两大类,分别是 constantRoutes 和 dynamicRoutes,其中 constantRoutes 是固定菜单,也就是一些跟用户权限无关的菜单,例如 404 页面、首页等;dynamicRoutes 是动态菜单,也就是也根据用户权限来决定是否展示的菜单,例如分配用户、字典数据、调度日志等等。

  • filterDynamicRoutes 方法则是将前端提前定义好的 dynamicRoutes 菜单进行过滤,找出那些符合当前用户权限的菜单将之添加到路由中(这些菜单都不需要在菜单栏渲染出来)。

  • 接下来涉及到四个不同的保存路由数据的变量,分别是 routes、addRoutes(经松哥分析,这个变量并无实际作用,可以删除之)、defaultRoutes、topbarRouters 以及 sidebarRouters,四个路由变量的作用各有不同:

routes:

routes 中保存的是 constantRoutes 以及服务端返回的动态路由数据,并且这个动态路由数据中的 path 已经完成了重写,所以这个 routes 主要用在两个地方:

首页的搜索上:首页的搜索也可以按照路径去搜索,所以需要用到这个 routes,如下图:

Bagaimana untuk memuatkan menu dinamik dalam Vue3

用在 TagsView,这个地方也需要根据页面渲染不同的菜单,也是用的 routes:

Bagaimana untuk memuatkan menu dinamik dalam Vue3

sidebarRouters:

这个就是大家所熟知的侧边栏菜单了,具体展示是 constantRoutes+服务端返回的菜单,不过这些 constantRoutes 基本上 hidden 属性都是 false,渲染的时候是不会被渲染出来的。

Bagaimana untuk memuatkan menu dinamik dalam Vue3

topbarRouters:

这个是用在 TopNav 组件中,这个是将系统的一级菜单在头部显示出来的,如下图:

Bagaimana untuk memuatkan menu dinamik dalam Vue3

一级菜单在顶部显示,左边显示的都是二级三级菜单,那么顶部菜单的渲染,用的就是这个 topbarRouters。

defaultRoutes:

想要开启顶部菜单,需要在 src/layout/components/Settings/index.vue 组件中设置,如下图:

Bagaimana untuk memuatkan menu dinamik dalam Vue3

开启顶部菜单之后,点击顶部菜单,左边菜单栏会跟着切换,此时就是从 defaultRoutes 中遍历出相关的菜单设置给 sidebarRouters。

Baiklah, ini adalah peranan empat pembolehubah laluan ini Sejujurnya, reka bentuk kod dalam perancah agak mengelirukan. Tidak perlu mempunyai banyak pembolehubah untuk mengoptimumkannya untuk semua orang.

Kaedah generateRoutes akhirnya akan mengembalikan pembolehubah rewriteRoutes kepada pengawal navigasi hadapan yang dinyatakan di atas, dan akhirnya pengawal navigasi hadapan akan menambah data pada penghala.

Penyampaian menu dilakukan dalam src/layout/components/Sidebar/index.vue Selepas melihatnya, ia adalah operasi biasa.

Atas ialah kandungan terperinci Bagaimana untuk memuatkan menu dinamik dalam Vue3. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam