Что такое динамическая маршрутизация
Личное понимание: динамическая маршрутизация отличается от обычной статической маршрутизации, и список маршрутизации сайта может быть изменен в соответствии с различными «факторами». Большинство общих динамических маршрутов используются для реализации: разные пользователи в многопользовательской системе разрешений отображают разные навигационные меню.
Как реализовать динамическую маршрутизацию с помощью Vue Router
VueСуществует два способа реализации динамической маршрутизации в проекте:
- Внешний интерфейс определяет все маршруты и динамически отображает маршруты в соответствии с разрешениями роли пользователя при входе в систему;
- Маршрут хранится в базе данных, а интерфейс получает через интерфейс список маршрутов, соответствующий текущему пользователю, и отображает его;
Первый способ во многихVue UI AdminВсе вышеперечисленное уже реализовано, вы можете прочитать их исходный код, чтобы понять конкретные идеи реализации, поэтому я не буду здесь слишком много распространяться.
Второй метод тоже сейчас более распространен, потому что он используется в последних проектах, поэтому я расскажу о нем отдельно.Vue RouterНекоторые функции реализуют динамическую маршрутизацию с преобладанием серверной части.
Используемые функции
Глобальная передняя защита Vue Router
Официальное объяснение веб-сайта
Здесь мы в основном используем функцию «внешнего интерфейса» глобальной внешней защиты для внедрения списка маршрутизации, используемого текущим пользователем, на страницу до загрузки страницы.RouterВ примере метод, используемый для инъекции, следующий:router.addRoutesметод.
Метод экземпляра Vue Router router.addRoutes
Официальное объяснение веб-сайта
router.addRoutesметод может бытьRouterЭкземпляр динамически добавляет правила маршрутизации, что просто предоставляет нам метод внедрения для реализации динамической маршрутизации.
Отложенная загрузка маршрутизации Vue Router
Официальное объяснение веб-сайта
Эта функция ленивой загрузки не является необходимой функцией динамической маршрутизации, но поскольку эта возможность предусмотрена, она используется непосредственно в проекте.
конкретные идеи
Подготовка основной информации
Код фронтенда реализует базовую статическую маршрутизацию, такую как: маршрутизация страницы входа, маршрутизация страницы ошибки сервера и т. д. (здесь есть ямка, о которой будет сказано позже). В базе данных хранится вся информация о динамической маршрутизации.
Как база данных хранит информацию о динамической маршрутизации?
Решение, которое я выбрал, состоит в том, чтобы сначала преобразовать объект, на который ссылается маршрут, а затем преобразовать список маршрутов вJSONФормат для передачи в тыл, после хранения в базе данных внутренней обработки. Таким образом, он передается на переднюю и заднюю частьJSONИнформация о списке маршрутов в формате.
Как упорядочить объекты, на которые есть ссылки в маршрутах?
Настоящая проблема, с которой я сталкиваюсь: использованиеUIКомпонент предоставляет схему макета и должен ссылаться на компонент макета и ссылаться на конкретную страницу в дочернем маршруте.
Решение, которое я выбрал, таково: относиться к компонентам макета, на которые нужно ссылаться, по-разному.componentсвойств, используйте короткие строки вместо компонентов макета и используйте строки пути к файлу вместо импорта страниц.
Конкретную реализацию можно увидеть в следующем примере кода.
Используйте глобальную переднюю защиту для оценки информации о маршрутизации
1-判断用户是否登录
1.1-若未登录,跳转至登录页面
1.2-若已经登录,判断是否已获取路由列表
1.2.1-若未获取,从后端获取、解析并保存到 `Vuex` 中
1.2.2-若已获取,跳转至目标页面
Я не проводил здесь особых исследований, я напрямую сохранял полученные данные вVuexВ процессе реального применения проекта следует учитывать безопасность хранения данных.
Как реализовать парсинг списка маршрутов?
- Буду
JSONИнформация о маршрутизации в формате анализируется какJavaScriptобъект списка; - использование объектов списка
filterметод реализует аналитическую функцию черезcomponentОпределите, является ли это компонентом макета; - Если это компонент макета, используйте вместо него компонент макета.
componentнить; - Для конкретной страницы используйте
loadViewФункция загружает соответствующую конкретную страницу;
Используйте метод Mar Router.addrotes для динамического добавления маршрутизации
Этот шаг очень прост, передайте проанализированный список маршрутов черезrouter.addRoutesСпособ добавлен кRouterв примере.
Простой код реализации
// router/index.js
import Vue from 'vue'
import store from '@/store'
import Router from 'vue-router'
import { getToken } from '@/lib/util'
Vue.use(Router)
// 定义静态路由
const staticRoutes = [
{
path: '/login',
name: 'login',
meta: {
title: '登录页面',
hideInMenu: true
},
component: () => import('@/view/login/login.vue')
},
{
path: '/401',
name: 'error_401',
meta: {
hideInMenu: true
},
component: () => import('@/view/error-page/401.vue')
},
{
path: '/500',
name: 'error_500',
meta: {
hideInMenu: true
},
component: () => import('@/view/error-page/500.vue')
}
]
// 定义登录页面名称(为了方便理解才定义的)
const LOGIN_PAGE_NAME = 'login'
// 实例化 Router 对象
const router = new Router({
routes: staticRoutes,
mode: 'history'
})
// 定义全局前置守卫(里面有两个坑要注意)
router.beforeEach((to, from, next) => {
// 通过自定义方法获取用户 token 用来判断用户登录状态
const token = getToken()
if (!token && to.name !== LOGIN_PAGE_NAME) {
// 如果没有登录而且前往的页面不是登录页面,跳转到登录页
next({ name: LOGIN_PAGE_NAME })
} else if (!token && to.name === LOGIN_PAGE_NAME) {
// 如果没有登录而且前往的页面是登录页面,跳转到登录页面
// 这里有一个坑,一定要注意这一步和上一步得分开写
// 如果把前两步判断合并为 if (!token) next({ name:login })
// 则会形成登录页面无限刷新的错误,具体成因后面解释
next()
} else {
// 如果登录了
if (!store.state.app.hasGetRoute) {
// 如果没有获取路由信息,先获取路由信息而后跳转
store.dispatch('getRouteList').then(() => {
router.addRoutes(store.state.app.routeList)
// 这里也是一个坑,不能使用简单的 next()
// 如果直接使用 next() 刷新后会一直白屏
next({ ...to, replace: true })
})
} else {
// 如果已经获取路由信息,直接跳转
next()
}
}
})
export default router
// store/index.js
import router from '@/router'
import Main from '@/components/main'
import { getToken } from '@/lib/util'
import { getRoute } from '@/api/app'
const loadView = (viewPath) => {
// 用字符串模板实现动态 import 从而实现路由懒加载
return () => import(`@/view/${viewPath}`)
}
const filterAsyncRouter = (routeList) => {
return routeList.filter((route) => {
if (route.component) {
if (route.component === 'Main') {
// 如果 component = Main 说明是布局组件
// 将真正的布局组件赋值给它
route.component = Main
} else {
// 如果不是布局组件就只能是页面的引用了
// 利用懒加载函数将实际页面赋值给它
route.component = loadView(route.component)
}
// 判断是否存在子路由,并递归调用自己
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children)
}
return true
}
})
}
export default {
state: {
routeList: [],
token: getToken(),
hasGetRoute: false
},
mutations: {
setRouteList(state, data) {
// 先将 JSON 格式的路由列表解析为 JavaScript List
// 再用路由解析函数解析 List 为真正的路由列表
state.routeList = filterAsyncRouter(JSON.parse(data))
// 修改路由获取状态
state.hasGetRoute = true
}
},
atcions: {
getRouteList({ state, commit }) {
return new Promise((resolve) => {
const token = state.token
getRoute({ token }).then((res) => {
let data = res.data.data
// 注意这里取出的是 JSON 格式的路由列表
commit('setRouteList', data)
resolve()
})
})
}
}
}
Общая проблема
Страница зависла на странице входа и продолжает обновляться
Решение этой проблемы было упомянуто в «коде реализации», просто будьте осторожны, чтобы не перепутать два незарегистрированных состояния при оценке состояния входа в систему. Но это временное решение, потому что одна и та же проблема может быть вызвана разными формами кода.В чем причина проблемы? Затем медленно анализируем:
Давайте сначала предположим, что два незарегистрированных состояния случайно смешаны вместе, чтобы судить:
if (!token) {
next({ name: LOGIN_PAGE_NAME })
}
здесьnext({ name: LOGIN_PAGE_NAME })Этот метод снова активирует глобальную переднюю защиту, что приводит к еще одному решению о входе и срабатываниюnext({ name: LOGIN_PAGE_NAME }), если этот рекурсивный вызов продолжится, страница будет зависать и постоянно обновляться.
Динамическая маршрутизация с отложенной загрузкой маршрутизации
Схема для достижения этого также показана в примере кода:
const loadView = (viewPath) => {
return () => import(`@/view/${viewPath}`)
}
Вот функция, которая обычно не используется в JavaScript: шаблоны строк, используйте эту функцию для создания строк, которые не поддерживают конкатенацию строк.importДействия могут быть динамичными.importразные модули.
404 после динамического обновления маршрута
Это должно быть одной из самых распространенных ошибок в этом решении.Первоначальный замысел состоит в том, что многие люди добавляют маршрут страницы 404 при создании «базового статического маршрута», чтобы динамический маршрут на начальном этапе загрузки страницы не В экземпляре маршрутизации появится страница 404 с самым широким диапазоном совпадений. Решение состоит в том, чтобы добавить маршрутизацию страницы 404 в динамическую маршрутизацию.
Пустая страница после обновления динамической маршрутизации
Есть много причин для этой проблемы, проблема, с которой я столкнулся, заключается в использованииСправочная статья 3Это решено, но я еще не понял конкретного принципа, и я обновлю его, когда проведу какое-то исследование.
Заголовок нестабилен при обновлении страницы динамической маршрутизации
Причина этой проблемы проста: поскольку информация о маршрутизации не была загружена при обновлении страницы, информация о заголовке вообще не загружается. Но я не нашел лучшего решения, и я обновлю его после изучения.