React-学习笔记(8—react-router@5 and @6)

目录

1、react-router@5

1-1、在项目中安装路由

1-2、一个项目使用一个路由器来管理路由即可

1-3、 路由组件和一般组件的区别

1-6、使用 Switch 标签

1-7、BrowserRouter解决多级路径匹配样式丢失问题

1-8、路由的模糊匹配和严格匹配

1-9、路由重定向 Redirect

1-10、嵌套路由(多级路由)

1-11、向路由组件传递参数

1)params:            传递参数:

2)search(query):            传递参数:

         3)state (不同于组件身上的 state)

1-12、使用 replace 模式

1-13、使用编程式路由导航

1-14、在一般组件中使用编程式路由导航

1-15、BrowserRouter 和 HashRouter 对比

2、react-router@6

2-1、6版本中移除了先前的,引入了新的替代者

2-2、内置组件 navigate

2-3、useRoutes 使用路由表

2-4、 Outlet 组件标签

2-5、路由 params 参数

2-6、search 参数

2-7、使用state参数

2-8、编程式路由导航

2-9、useNavigationType() 判断进入当前页面(路径)的方式

2-10、useResolvePath() 解析路径

2-11、懒加载

2-12、react.createContext 祖组件向后代组件传递内容


1、react-router@5

1-1、在项目中安装路由

    这里使用旧版本5:
    npm i react-router-dom@5
    
    新版本是@6

1-2、一个项目使用一个路由器来管理路由即可

    在 index.jx 文件中,渲染App时,用 指定的路由器包裹 App 组件
    使用 BrowerRouter 或 HashRouter

import {BrowserRouter} from 'react-router-dom'; 

......

root.render( 
    <BrowserRouter> 
        <App/> 
    </BrowserRouter>
);

1-3、 路由组件和一般组件的区别

    1)写法不同:
        一般组件:<Demo/>
        路由组件:<Route path="/demo" component={Demo}></Route>


    2)存放位置最好区分开
        一般组件:component
        路由组件:pages        routeComponent


    3)接收到的参数不同:
        一般组件:接收到的参数是在组件标签中所传的参数
        路由组件:接收到三个固定的属性history、location、match

        Link 和 NavLink 都是内置组件 ,相当于原生HTML中的a标签,点击这两个元素后,都会跳转到指定的路由页面。

        当 Link 标签处于激活状态时,如果需要给该 Link 动态添加一个CSS类(非激活状态时该类移除)时,可以使用 NavLink 标签替代 Link 标签。
        NavLink 默认添加的类名为 active,如果需要自己指定一个类名,使用属性activeClassName = "customActiveClassName"

<NavLink activeClassName="customActiveClassName" 
    path="/home" component={Home}
>
    Home
</NavLink>

        当需要使用多个 NavLink,且多个 NavLink 有相同的属性和值(如有共同标签属性activeClassName='act-link')时。
    
        如果有多个参数传递给 MyNavLink,可以在 MyNavLink 中使用 {...this.props} 来展开
    <MyNavLink activeClassName="act-link" {...this.props}/>
    
    指定 MyNavLink 的 innerText:
    1)使用指定的children标签属性:<MyNavLink children="text"/>
    2)传统非闭合标签方式:
        <MyNavLink>text</MyNavLink>

1-6、使用 Switch 标签

        在路由区域块中,如果不使用 Switch 将注册路由包裹,那路由在匹配到对应的注册路由后,仍然会向后继续匹配,
        最后会将匹配到的所有组件都展示到路由区域。
    
        使用Switch将注册路由都包裹起来,那么路由匹配到第一个注册路由后就会停止往后匹配。switch 也可以简单理解为路由组件的展示区域。

    <Switch>
        <Route path="/home" component={Home}/>
        <Route path="/about" component={About}/>
        <Route path="/about" render={()=><h1>context | test</h1>}/>
    </Switch>

1-7、BrowserRouter解决多级路径匹配样式丢失问题

    1)public/index.js 中引入样式 ./xxx 写成 /xxx
    2)public/index.js 中引入样式 ./xxx 写成 %PUBLIC_URL%/xxx   (React中适用)
    3)使用 HashRouter

1-8、路由的模糊匹配和严格匹配

        let NavLinkToArr = NavLink.to.split('/')
        let RoutePathArr = Route.path.split('/')
    
1) 模糊匹配
        模糊匹配是默认开启的
        NavLinkToArr 和 RoutePathArr 两个数组依次对应匹配,RoutePathArr 被完全匹配后,便应用该注册路由,而不论 NavLinkToArr 中是否还有剩余的元素(即 NavLinkToArr.length >= RoutePathArr)
    
2) 严格匹配:
        开启严格匹配(exact 属性为 true 时):

<Route exact path="xxx"></Route>


        需要NavLinkToArr 和 RoutePathArr 两数组长度相等,且元素值一一对应时,才应用该注册路由。
        严格匹配需要时再开启,有时会导致无法匹配到二级路由。

1-9、路由重定向 Redirect

        写在所有注册路由的后面,当前面的注册路由都匹配不到时,就匹配到重定向的注册路由

    <Switch>
        <Route path="/home" component={Home}/>
        <Route path="/about" component={About}/>
        <Redirect to="/home"/>
    </Switch>


        不使用 Switch 包裹注册路由时,如果匹配到注册路由了,会继续往下匹配其他路由,包括在最后面的 Redirect,最后会应用 Redirect 所指定的路由页面 。

1-10、嵌套路由(多级路由)

1) 注册子路由时,path上要带上父路由组件的path
    如 News 和 Message 是 Home 的子组件 在Home.jex中:

    <div>
        <div>
            this is Home Page
            <NavLink to="/home/message">to message</NavLink>
            <NavLink to="/home/news">to news</NavLink>
        </div>
        <div>
            <Switch>
                <Route path="/home/message" component={Message}></Route>
                <Route path="/home/news" component={News}></Route>
                <Redirect to="/home/news"></Redirect>
            </Switch>
        </div>
    </div>

2)路由的匹配每次都是重头开始的,按注册的顺序进行匹配的。

1-11、向路由组件传递参数

1)params:
            传递参数:

<NavLink to={`/message/detail/${id}/${content}`}>detail</NavLink>

            or:

<NavLink to={
   
   {pathname:`/message/detail/${id}/${content}`}}>detail</NavLink>

            声明接收参数:

<Route path="/message/detail/:id/:content" component={Detail}/>

            在路由组件中拿到传递过来的参数:

this.props.match.params.id

            如果没有声明接收参数,即

<Route path="/message/detail" component={Detail}/>

             虽然可以模糊匹配到该路由组件,但是参数会丢失。


    
2)search(query):
            传递参数:

<NavLink to={`/message/detail?id=${id}&content=${content}`}>detail</NavLink>

            不需要声明接收:

<Route path="/message/detail" component={Detail}/>

在路由组件中获取到 search 参数:
            2-1)需要引入一个React配套已经安装好的库——querystring 直接引入即可:

import qs from 'querystring';

            2-2)qs 的基本使用:

// 将 urlencode 解析成对象:
let res = qs.parse(urlencode);

// 将 对象转换成 urlencode 字符串:
let obj = qs.stringify(obj);

            2-3)获取到 search 参数:

this.props.location.search;

            获取到的是 urlencode 类型的字符串,如:?id=3&content=你好
            然后使用 qs 进行解析,就可以使用。


    
3)state (不同于组件身上的 state)

        state 参数与上述两种类型不同,state类型参数不会展示到 URL 地址栏中;
    
        传递参数:

<NavLink to={
    {
        pathname:'/message/detail',
        state:{
            id:this.id,
            content:this.content
        }
    }
}>
    detail
</NavLink>

        不需要声明接收:

<Route path="/message/detail" component={Detail}/>

        在路由组件中使用 state 参数:

this.props.location.state.id

this.props.location.state.content

        需要注意的是,当在有history,即有浏览器历史缓存的时候,刷新页面在访问该地址,是有数据的。但如果用户清除了缓存数据,那么直接访问该地址,就不会有数据。
       

1-12、使用 replace 模式

    默认使用的是 push。
    使用 replace:

<NavLink replace to={`/message/detail/${id}/${content}`}>detail</NavLink>

        or:

<NavLink replace={true} to={`/message/detail/${id}/${content}`}>detail</NavLink>

1-13、使用编程式路由导航

        关键是使用路由组件的 props 上的 history 中的函数:
        this.props.history.go(n)        —— 往前或往后 n 个单位
                          .goBack()     —— 回退一个页面
                          .forword()    —— 前进一个页面
                          .push(path, state)       —— 将新页面压入栈顶(跳转到一个新的页面,可以回退到当前的页面)
                          .replace(path, state)    —— 将新页面替换掉当前页面(跳转到一个新的页面,不可回退到当前页面)

1-14、在一般组件中使用编程式路由导航

        借助 react-router-dom 中的 withRouter 函数:
        import withRouter from 'react-router-dom'
    
        在 Message 组件中先使用 this.props.history. 或其他路由组件中的属性(location、match)
    
        创建完类式组件后,再使用默认导出:

export default withRouter(Message);

        导出经 withRouter 加工后的组件。Message 组件经过 withRouter 加工后,this.props 中将具有路由组件所具有的几个属性:
        history、location、match

1-15、BrowserRouter 和 HashRouter 对比

    1、底层原理不同:
        BrowserRouter 使用的是 H5 中的history API,对 IE9 以下版本不兼容
        HashRouter 使用的是URL的哈希值
    2、path表现形式不同
        体现在 HashRouter 的路径中以 /#/ 开头,而 BrowserRouter 正常
    3、对于路由传递state类型参数的影响
        BrowserRouter 因为依靠浏览器历史对象,直接刷新不会有影响,state参数在浏览器缓存中
        而 HashRouter 刷新页面 state 参数会丢失
    4、HashRouter 可以解决多级路径时,样式丢失的问题

2、react-router@6

2-1、6版本中移除了先前的<switch/>,引入了新的替代者<Routes/>

        <Routes/> 包裹着 若干个 <Route>,并且这两个必须要配合使用。
        <Routes/> 就相当于一个 if 语句,如果其路径与当前的URL匹配,则展现该组件。
        <Routes caseSensitives/> 用来指定匹配时区分大小写。
        当URL发生变化时,Routes会查找全部的Route,以找到最佳的组件。
        <Route/> 可以嵌套使用。

2-2、内置组件 navigate

        只要 <Navigate/> 组件被渲染,就会修改路径,切换视图
        可以用来重定向

    <Routes>
        <Route path="/about" element={<About/>}/>
        <Route path="" element={}/>
        <Route path="" element={}/>      {\* element即组件 *\}
        <Navigate to="/about" replace/>  {\* replace表示跳转的方式 *\}
    </Routes>

2-3、useRoutes 使用路由表

        使用路由表之后就不用写 Routes 包裹 n 个 Route了,使用Outlet来占位表示路由组件的展示区域
    
        路由表的规则可以放到src的routes文件夹下的index.jx

import Home from './pages/Home'
import About from './pages/About'
import {Navigate} from 'react-router-dom'
import Child from './pages/Child'
    
export default [
    {
         path:'/home',
         element:<Home/>,
         children:[
             {
                  path:'child',
                  element:<Child/>
             }
         ]
    },{
         path:'/About',
         element:<About/>
    },{
         path:'/',
         element:<Navigate to="/about">
    }
]


        在 App.jsx 中引入该路由表

import useRoutes from 'react-router-dom'
import routes from './routes/index.js'
    
// 根据路由表生成相应的路由规则
const element = useRoutes(routes);
    
<div className="routes-panel-area">
    {/* 注册路由 */}
    {element}                   
</div>

2-4、 Outlet 组件标签

        用来指定路由页面呈现的位置

2-5、路由 params 参数

        在路由规则(路由表)中要占位:

// 路由表中
{
    path:'/home/:id/:name',
    component:<Home/>
}

        Link 组件的 to 要改写。

<link to={`detail/${m.id}/${m.name}`}></link>

        在接收的时候要使用 useParams

import {useParams} from 'react-router-dom'
    
const {id,title,content} = useParams();

        还有 useMatch 也可以拿到,同时也能收集到history、location等内容

2-6、search 参数

        不需要改变路由规则。
    
        传递的时候:

<link to={`/home?id=${m.id}&name=${m.name}`}></link>

        接收的时候需要使用到 useSearchParams

import {useSearchParams} from 'react-router-dom'
    
// 这是对数组的解构,第一个元素赋给searchParams,是我们需要的search数据
// 第二个setSearchParams是用来修改search参数的
const [searchParams, setSearchParams] = useSearchParams();      
    
// 获取到search参数 要使用get方法
const id = searchParams.get('id');
const name = searchParams.get('name');
    
// 使用第二个参数可以修改search参数,location也会跟着一起改变
setSearchParams('id=001&name=张三');

2-7、使用state参数

<link to="/home" state={
   
   {id:m.id, name:m.name}}></link>
// 需要引入 useLocation
import {useLocation} from 'react-router-dom'
    
const {state:{id,name}} = useLocation();

2-8、编程式路由导航

    使用 useNavigate 这个API

import {useNavigate} from 'react-router-dom'
    
const navigate = useNavigate();
    
// navigate('/home',{
//     replace:false,
//     state:{
//         id:m.id,
//         name:m.name
//     }
// })
    
navigate('detail',{
    replace:false,
    state:{
        id:m.id,
        name:m.name
    }
})


    使用编程式路由导航只能传递 state 参数。
    非路由组件(一般组件)也可以使用。

2-9、useNavigationType() 判断进入当前页面(路径)的方式

    返回值有三:POP、PUSH、REPLACE
    pop表示是直接进入到当前页面或是刷新页面的结果

2-10、useResolvePath() 解析路径

    参数接收一个字符串,会返回 search、path、hash 等内容
    useResolvePath('/about#que?name=zhangsan&age=13')

2-11、懒加载

    懒加载组件一般是路由组件

import {lazy, Suspense} from 'react';       // lazy是一个函数,Suspense是一个组件
    
import Loading from './Loading';            // 引入显示正在加载的展示组件
    
const Home = lazy(()=> import('./Home'));   // 懒加载组件的引入方式
const About = lazy(()=> import('./About'));
    
// 需要用Suspense包裹懒加载组件 当还在处理懒加载组件时,会先渲染Loading组件到页面指定位置
<Suspense fallback={<Loading/>}>            
    <Route path="/home" component={About}/>
    <Route path="/About" component={Home}/>
</Suspense>
    

 

2-12、react.createContext 祖组件向后代组件传递内容

// 1) 创建Context容器对象在祖组件和后代组件都看得见的地方创建:
const XxxContext = React .createContext()
    
// 2) 染子组时,外面包xxxContextProvider,通过vaue属性给后代组件传递数据
<xxxContext.Provider value={数据}>
     子组件
</xxxContext.Provider>
    
// 3后代组件读取数据:
//第一种方式:仅适用于类组件
static contextType = xxxContext // 声明接收context
    
this.context    // 读取context中的value数据
    
//第二种方式: 函数组件与类组件都可以
<xxxContext.Consumer>
     {
          value => ()=>{      // value就是context中的value数据要显示的内容
              {/* 要显示的内容 */}
          }
     }
</xxxContext.Consumer>

猜你喜欢

转载自blog.csdn.net/hao_13/article/details/131491497
今日推荐