vue and React routing

Table of contents

Install

browser routing pattern

Configuration (/src/router/index.js)

Configuration Fields for Routing Tables 

Vue

named route (name)

Named view (sibling display)

Routing meta information (meta, any additional information, such as authorization)

pass parameters

url parameter

location attribute value

window

useLocation()

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)

Default route (no match), redirection route (redirect/Navigate), 404 (*/errorElement)

Vue

React

loader callback function (triggered before routing)

main entrance

Guard (authority, route interception)

Navigation analysis process

global

Vue

React

/src/components/BeforeEach.jsx

Partial routing (compared to component routing, partial routing is recommended, better logical block)

component routing

The browser enters the URL to display the corresponding component of the route

Vue placeholder router-view\router-link

React placeholder Outlet\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

  • historymode 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
})
  • hashThe 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&param2=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 id="section1"the element with the .

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>
  )

loaderThere 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

  1. Navigation is triggered.

  2. Call guards in deactivated components beforeRouteLeave.

  3. Call the global beforeEachguard.

  4. beforeRouteUpdateCall guards (2.2+) in reusable components .

  5. Called in the routing configurationbeforeEnter

  6. Parse asynchronous routing components.

  7. Called in the activated component beforeRouteEnter.

  8. Calls the global beforeResolveguard (2.5+).

  9. Navigation is confirmed.

  10. Call the global afterEachhook.

  11. Triggers a DOM update.

  12. Call the callback function beforeRouteEnterpassed in the guard next, 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 replacereplaced 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 pushand replaceto 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;

Guess you like

Origin blog.csdn.net/qq_28838891/article/details/131691290