Table of contents
Configuration (/src/router/index.js)
Configuration Fields for Routing Tables
Routing meta information (meta, any additional information, such as authorization)
query (explicit) carries auxiliary information
params (explicit/implicit (refreshing the page will disappear)) differential interface
Dynamic routing (different parmas, access to the same component)
Programmatic routing (non-link mode)
loader callback function (triggered before routing)
Guard (authority, route interception)
/src/components/BeforeEach.jsx
The browser enters the URL to display the corresponding component of the route
Vue placeholder router-view\router-link
Navigation duplication (modified prototype method)
Routing: display different content according to different url addresses , path manager for SPA (Single Page Application)
Install
Vue3 is paired with Vue Router4, and other usages have not changed much from vue2
//Vue.use() 方法进行安装和注册VueRouter插件
//自动调用插件对象中的 install 方法
Vue.use(VueRouter);
npm install vue-router
npm i react-router-dom
browser routing pattern
history
mode uses the browser's History API to hide extra characters in the URL, suitable for most general browser environments.- Routing is more beautiful without using hash symbols
#
. - You can take full advantage of the browser's forward and backward functions.
- Server configuration support is required to ensure that the correct page is returned when accessing the route directly.
- HTML5 's history API monitors URL changes, so there are browser compatibility issues
//Vue 2.x 或 3.x Options API
const router = new VueRouter({
mode: 'history',
routes
});
// Vue 3.x Composition API
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes
})
hash
The pattern uses a hash value in the URL (#
, you can implement route navigation by listening for hash changes)- No server configuration support is required (hashes are not sent to the server)
- Suitable for cases where the History API is not supported or compatibility with older browsers is required.
- Doesn't make full use of the browser's forward and back functions, there is only one history entry.
- Listen to the browser's onhashchange() event change through window.addEventListener to find the corresponding routing rules
//Vue 2.x 或 3.x Options API
const router = new VueRouter({
mode: 'hash',
routes
});
// Vue 3.x Composition API
import { createRouter, createWebHashHistory} from 'vue-router';
const router = createRouter({
history: createWebHashHistory(),
routes
})
- No routing mode is specified, it will automatically choose the appropriate mode according to the current environment.
const router = new VueRouter({
routes
})
configure( /src/router/index.js
)
Configuration Fields for Routing Tables
-
path: specify the path
-
element (React)/component (Vue): corresponding component
-
children: nested routes
Vue
named route (name)
Automatic encoding/decoding of params
{
path: '/about/foo/:id',
name: 'foo',
component: Foo
}
{ name: 'foo', params: {id: 123} }
Named view (sibling display)
Routing meta information (meta, any additional information, such as authorization)
meta: { auth: false }
this.$route.meta.auth
import { useLocation, matchRoutes, Navigate } from 'react-router-dom'
import { routes } from '../../router';
export default function BeforeEach(props) {
const location = useLocation();
const matchs = matchRoutes(routes, location)
const meta = matchs[matchs.length-1].route.meta
if(meta.auth){
return <Navigate to="/login" />
}
else{
return (
<div>{ props.children }</div>
)
}
}
pass parameters
url parameter
http://example.com/page?param1=value1¶m2=value2#section1
? | Separate the actual URL and parameters |
& | Separator between parameters specified in the URL |
= | Parameter name on the left, parameter value on the right |
# | Anchor (Anchor), used to identify a specific location or element in the document, Used only on the client side and processed by the browser, not sent to the server Instructs the browser to scroll to |
location attribute value
window
The global object of window, representing the current page http://www.example.com/path/index.html
window.location.href: get/set url
window.location.orgin: protocol, hostname and port number sections
//https://www.example.com:8080/page.html
// :// :
//https%3A%2F%2Fwww.example.com%3A8080。
encodeURIComponent(window.location.origin)
//encodeURIComponent用于将字符串中的特殊字符(空格、&、+、= 、?)转换为编码形式,确保URL中不包含任何无效字符
//查询参数时 或者 动态参数时 需要encodeURIComponent
const url = 'https://example.com/api?param=' + encodeURIComponent(queryParam);
window.location.href =`https://www.example.com/path/to/resource.html/domain=${location.host}&req=${encodeURIComponent(location.pathname)}&protocol=https${location.hash}`
window.location.protocol: protocol http
window.location.host: host + port (host:8080)/IP address (127.123.32.1 unique)/domain name (www.example.com mnemonic)
window.location.hostname: host host
window.location.port: port 8080
window.location.pathname: resource path path/index.html, resource index.html
window.location.hash:
window.location.search: search
var searchParams = new URLSearchParams(window.location.search);
console.log(searchParams.get('name')); // 输出 "John"
useLocation()
import { useLocation } from 'react-router-dom'
-
hash: hash value
-
key: unique identifier
-
pathname: path
-
search: query value (need to parse the string into an object.)
-
state: implicit data
query (explicit) carries auxiliary information
path: '/user/',
$route.query
import { useSearchParams } from 'react-router-dom'
const [searchParams, setSearchParams] = useSearchParams()
console.log( searchParams.get('age') );
const handleClick = () => {
setSearchParams({ age: 22 })
}
params (explicit/implicit (refreshing the page will disappear)) differential interface
$route.params
Explicit: path: '/user/:id',
Implicit: path: '/user/',
query explicit /workbenchConfiguration/upload ?wpReleId= 59
params explicit /workbenchConfiguration/upload / 59
Dynamic routing ( different parmas , access to the same component)
import { Outlet, Link } from 'react-router-dom'
export default function About() {
return (
<div>
<Link to="/about/foo/123">foo 123</Link> | <Link to="/about/foo/456">foo 456</Link>
</div>
)
}
//...
{
path: 'foo/:id',
element: <Foo />
}
//...
import { useParams } from 'react-router-dom'
export default function Foo() {
const params = useParams()
return (
<div>Foo, { params.id }</div>
)
}
//Vue与React唯一不同
this.$route.params.id
Programmatic routing (non-link mode)
//vue
this.$router.push({
path: `/about/foo/${id}`
})
//react
import {useNavigate } from 'react-router-dom'
const navigate = useNavigate()
const handleClick= () => {
navigate('/about/foo/123')
}
Default route (no match), redirection route (redirect/Navigate), 404 (*/errorElement)
Vue
import VueRouter from 'vue-router'
import Home from '@/views/Home.vue'
const About={template:'<div>About</div>'}
const routes: Array<any> = [
{
path: '/',
redirect: '/workbenchConfiguration'
},
{
path: '/404',
meta: { title: '404' },
component: () => import('@/views/404.vue')
},
{ path: '*', redirect: '/404' }
]
const router = new VueRouter({
routes
})
React
import { createBrowserRouter, createHashRouter } from 'react-router-dom'
//路由表
export const routes = [
// 默认路由
{
index: true,
//重定向
element: <Navigate to="/about/foo/123" />,
//自带errorElement
errorElement: <div>404</div>,
},
//*局部404
{
path: '*',
element: <div>404</div>
}
];
//路由对象
const router = createBrowserRouter(routes);
export default router;
loader callback function (triggered before routing)
Synchronization by default, cooperate with redirect to do permission interception.
{
path: 'bar',
element: <Bar />,
//async,await异步,Promise用于表示一个异步操作的最终完成(或失败)及其结果值。
loader: async() => {
let ret = await new Promise((resolve)=>{
setTimeout(()=>{
resolve({errcode: 0})
}, 2000)
})
return ret;
}
}
useLoaderData() gets the data returned by the loader function
import { useLoaderData } from 'react-router-dom'
export default function Bar() {
const data = useLoaderData()
console.log(data)
return (
<div>Bar</div>
)
loader
There is no way to use the <Navigate> component for redirection in the function
{
path: 'bar',
element: <Bar />,
loader: async() => {
let ret = await new Promise((resolve)=>{
setTimeout(()=>{
resolve({errcode: Math.random() > 0.5 ? 0 : -1})
}, 2000)
})
if(ret.errcode === 0){
return ret;
}
else{
return redirect('/login')
}
}
}
main entrance
//index.js
import { RouterProvider } from 'react-router-dom'
import router from './router';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<RouterProvider router={router}></RouterProvider>
</React.StrictMode>
);
Guard (authority, route interception)
Navigation analysis process
-
Navigation is triggered.
-
Call guards in deactivated components
beforeRouteLeave
. -
Call the global
beforeEach
guard. -
beforeRouteUpdate
Call guards (2.2+) in reusable components . -
Called in the routing configuration
beforeEnter
-
Parse asynchronous routing components.
-
Called in the activated component
beforeRouteEnter
. -
Calls the global
beforeResolve
guard (2.5+). -
Navigation is confirmed.
-
Call the global
afterEach
hook. -
Triggers a DOM update.
-
Call the callback function
beforeRouteEnter
passed in the guardnext
, and the created component instance will be passed in as the parameter of the callback function.
global
Vue
//to
router.beforeEach((to, from, next)=>{
if(to.meta.auth){
next('/');
}
else{
next();
}
})
//vue+ts
router.beforeEach((to: any, from: any, next: any) => {
const metaTitlt = (to.meta && to.meta.title) || ''
document.title = `${metaTitlt} - 默认模版`
//是否从根路径而来,当前路由的来源路径和即将进入的路由的路径是否相同
if (from.path !== '/' && from.matched[0].path !== to.matched[0].path) {
message.destroy()
}
next()
})
React
/src/components/BeforeEach.jsx
import React from 'react'
import { Navigate } from 'react-router-dom'
import { routes } from '../../router';
export default function BeforeEach(props) {
if(true){
return <Navigate to="/login" />
}
else{
return (
<div>{ props.children }</div>
)
}
}
export const routes = [
{
path: '/',
element: <BeforeEach><App /></BeforeEach>//包裹根组件APP
}
]
Partial routing (compared to component routing, partial routing is recommended, better logical block)
const routes = [
{
name: 'bar',
component: Bar,
beforeEnter(to, from, next){
if(to.meta.auth){
next('/');
}
else{
next();
}
}
}
];
component routing
<script>
export default {
name: 'FooView',
beforeRouteEnter(to, from, next){
if(to.meta.auth){
next('/');
}
else{
next();
}
}
}
</script>
The browser enters the URL to display the corresponding component of the route
If there is no placeholder, the default is the entire page
Vue placeholder router-view\router-link
<template>
<div>
<router-link to="/">首页</router-link> |
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
</template>
React placeholder Outlet\Link
import React from "react";
import { Outlet, Link } from 'react-router-dom'
function App() {
return (
<div className="App">
<h2>hello react</h2>
<Link to="/">首页</Link> | <Link to="/about">关于</Link>
<Outlet />
</div>
);
}
export default App;
Styled declarative routing NavLink
Navigation repetition (modify the prototype push and replace methods)
push: Add the new route to the browser's history, so that the user can return to the previous route through the browser's back button.
this.$router.push('/about')
replace: does not leave a new entry in the browser's history, but directly replaces the current history entry.
this.$router.replace('/contact')
For example, when processing the login page, the current route may be
replace
replaced with a method after successful login to prevent the user from returning to the login page through the back button.
Modify the prototype method of VueRouter push
and replace
to capture and process navigation repetition errors,
Instead of throwing errors in the console , avoiding unnecessary error messages and potential problems.
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => {
if (err.name !== 'NavigationDuplicated') {
throw err;
}
});
};
const originalReplace = VueRouter.prototype.replace;
VueRouter.prototype.replace = function replace(location) {
return originalReplace.call(this, location).catch(err => {
if (err.name !== 'NavigationDuplicated') {
throw err;
}
});
};
const router = new VueRouter({
// 路由配置...
});
export default router;