React动画和路由

1.过渡动画

React并没有提供过渡动画操作,组件的过渡动画需要依赖第三方模块:transition
安装

yarn add react-transition-group

单元素过渡动画

import {CSSTransition} from 'react-transition-group'
...
<CSSTransition in={布尔值,控制单元素显示/隐藏} timeout={动画持续事件,单位毫秒} unmountOneExit={布尔值,元素隐藏后卸载,必选} className="字符串,动画样式名称前缀">
<单元素标签></单元素标签>
</CSSTransition>
...
.前缀-enter{} /*进入前*/
.后缀-enter-active{} /*进入中*/
.前缀-enter-done{} /*进入后,不常用*/
.前缀-exit{} /*离开前*/
.前缀-exit-active{} /*离开中*/
.前缀-exit-done{} /*离开后样式:不常用*/

多元素过渡动画:列表动画

import {TransitionGroup,CSSTranition} from "react-transition-group"
...
<TransitionGroup>
...多个元素
<CSSTransition ...><单元素标签></单元素标签></CSSTransition>
<CSSTransition ...><单元素标签></单元素标签></CSSTransition>
<CSSTransition ...><单元素标签></单元素标签></CSSTransition>
</TransitionGroup>
...

2.界面组件库:Ant Design

安装

yarn add antd

引入
安装完成后,引入样式文件 src/index.css

@import '~antd/dist/antd.css'

按需/全局引入antd组件库

import {Button} from 'antd'
...
<Button type="primary">点击</Button>
...

3.路由

1.概述

路由,描述了根据用户请求跳转到不同视图页面的一种操作规则
React中的路由,涉及到核心API

HashRouter:路由容器,主要用于包含路由匹配规则和路由组件,路径匹配方式包含#
BrowserRouter:路由容器,路径匹配方式和HashRouter不同,常规匹配方式
Switch:路由匹配对象,一般包裹在Router的外层,用户唯一匹配单个路由规则对象
Route:路由规则对象,包含类路径匹配、对应的渲染组件
NavLink:路由导航链接,一般用于导航作用
Redirect:路由重定向,可以将用户的访问路径,重定向到其他路径

2.新版本(6.x)路由操作

安装路由模块

yarn add react-router-dom

开发布局组件:src/Layout.jsx,完成组件和路由的跳转

import React,{Componet} from 'react'
import {BrowserRouter as Router,Routes,Route,NavLink} from 'react-router-dom'
import Home from './Home'
import About from './About'
export default class Layout extends Component {
	render() {
		return (
			<div>
				{/* 路由容器,将所有匹配规则包含起来*/}
				<Router> 
				{/* 规则集合(新版),将所有规则包含起来 */}
					<Routes>
						{/*定义路由规则*/}
						<Route path="/home" element={<Home />}></Route>
						<Route path="/about" element={<About />}></Route>
					</Routes>
				
				<nav>
				<ul>
					<li><NavLink to="/home">首页</NavLink></li>
					<li><NavLink to="/about">相关</NavLink></li>
					</ul>
				</nav>
				<Router>
			</div>
		)
	}
}

3.老版本路由操作(常用)

yarn add react-router-dom@5.3.X

开发布局组件:src/Layout.jsx,完成组件和路由的跳转

<div>
	<Router>
		<Route path="/home" component={Home} />
		<Route path="/about" component={About} />
		<NavLink to="/home">首页</NavLink>
		<NavLink to="/about">相关</NavLink>
	</Router>
</div>

4.路由重定向

<Route path="/">
	<Redirect to="/home">
</Route>

5.路由导航高亮

react-router-dom提供的NavLink组件包含了默认导航高亮提示,主要通过导航链接的class="active"的样式处理来实现导航高亮的操作
注意:NavLink组件编译后的结果算是超链接标签

a.active {
	color:red
}

6.路由严格匹配

导航链接中如果出现了同时多个路由规则匹配用户请求的情况,就会导致多个导航同时高亮的情况,需要通过路由模块提供的严格匹配方式排除导航多高亮的问题
需要在导航连接上,添加exact关键词
需要在路由组件上,添加exact关键词

<div>
	<Router>
	<Route path="/" exact>
	<Redirect to="/home">
</Route>
		<Route path="/home" component={Home} />
		<Route path="/about" component={About} />
		<NavLink to="/" exact>去首页</NavLink>
		<NavLink to="/home">首页</NavLink>
		<NavLink to="/about">相关</NavLink>
	</Router>
</div>

7.404路由

针对用户访问的路由规则以外的路径,需要友好的提示404信息
创建404组件:NotFont.jsx

import React, { Component } from 'react'

export default class NotFound extends Component {
    render() {
        return (
            <div>
                404NotFond
            </div>
        )
    }
}

编辑Layout.jsx
所有路由规则后面

  <Route path="*" component={NotFound}></Route>

关于404路由和路由穿透

用户访问规则路径以外的路径,会得到404页面
用户访问路由规划页面,除了访问到页面组件,同时也访问到了404页面,这样的问题就是路由穿透问题
react-router-dom中提供的Switch组件,结局多个路由同时匹配的问题

<Switch>
路由规则
</Switch>

8.动态路由

多个路由规则匹配同一个路由组件,让路由组件达到复用的目的;该路由规则中包含固定的访问路径和访问数据部分,就是常规的RESTful路径风格
创建 Goods.jsx

...
<div>商品详情组件</div>
...

编辑Layout.jsx,添加Goods.jsx组件路由规则

 <Route path="/goods/:id" component={Goods}></Route>

编辑About.jsx

import React, { Component } from 'react'
import { Link } from 'react-router-dom'
export default class About extends Component {
    state= {
        goods:[{id:1,name:'苹果'},{id:2,name:"橘子"}]
    }
    render() {
        return (
            <div>
               {this.state.goods.map(item=>(
                  <Link to={`/good/${item.id}`}  key={item.id}>{item.name}查看详情</Link>
               ))}
            </div>
        )
    }
}

9.路由传参

路由规则,可以让路由在多个组件之间进行切换的同时传递数据,传递数据的方式有两种

RESTful参数
查询字符串参数

1.RESTful动态路由参数

路由规则Layout.jsx

 <Route path="/goods/:id" component={Goods}></Route>

路由链接About.jsx

{this.state.goods.map(item=>(
                  <Link to={`/good/${item.id}`}  key={item.id}>{item.name}查看详情</Link>

接收数据Goods.jsx

render() {
	let {params} = this.props.match
	return <div> 商品详情组件{params.id}</div>
}
2.查询字符串

创建组件 Order.jsx


export default class Order extends Component {
    render() {
        return (
            <div>
                订单页面
            </div>
        )
    }
}

定义路由匹配规则

<Route path="/order" component={Order}>

创建访问链接 Cart.jsx

import React, { Component } from 'react'
import { Link } from 'react-router-dom'

export default class Cart extends Component {
    state = {
        cartList: [
            {id:1,name: '苹果'},
            {id:2,name:'橘子'}
        ]

    }
    render() {
        return (
            <div>
                {this.state.cartList.map(item=>(
                    <Link to={`/order?id=${item.id}`}>下单{item.name}</Link>
                ))}
            </div>
        )
    }
}

接收数据 Order.jsx
需要安装第三方模块qs

import qs from 'qs'
...
render() {
	let {search} = this.props.location 
	let query = qs.parse(search.substring(1))
	retrun (
		<div>
                订单页面{query.id}
         </div>
	)
}
...

10.嵌套路由

React中的嵌套路由,直接在目标页面组件中定义即可
创建组件-登录 Login.jsx
创建组件-注册 Register.jsx
Home.jsx页面添加二级路由

export default class Home extends Component {
    render() {
        return (
            <div>
               <Link to="/home/login">登录</Link>
               <Link to="/home/register">注册</Link>
             <div>
                <Route path="/home/login" component={Login}></Route>
                <Route path="/home/register" component={Register}></Route>
             </div>
            </div>
        )
    }
}

11.高阶路由

为了让路由组件的子组件接收到路由信息
react-router-dom提供了一个高阶组件:withRouter可以让子组件包含/接收到路由数据
编辑:Header.jsx

import { withRouter } from 'react-router-dom'
 class Header extends Component {
    render() {
        return (
            <div>
                <h2>公共页头{this.props.location.pathname}</h2>
            </div>
        )
    }
}
export default withRouter(Header)

12.路由懒加载

路由懒加载,相当于按需导入以及路由切换过程中的加载操作

import {lazy} from 'react'
const Home = lazy(()=>import('./Home'))

路由切换,需要添加一个过渡组件,将路由组件宝航在<React.Suspence>组件内部

<Suspence fallback={<h1>加载中</h1>}>
路由规则
</Suspense>

4.路由封装

1.现有路由的问题

当前项目中,根据React语法习惯,将路由在使用的地方进行声明。如Layout.jsx中配置了一级路由

路由匹配规则代码,和页面视图代码混合到一起,后期不方便维护
路由匹配路径和路由组件,和普通页面组件混合在一起,不利于功能的扩展和项目维护
多级路由的配置,会让路由规则出现在大量不同的页面组件中,不方便后期路由的设置维护

2.路由初步封装

创建router/RouterView.jsx路由组件,封装一级路由

import {lazy} from 'react'
const  About =lazy(()=>import('./componets/About'))
const  Home =lazy(()=>import('./componets/Home'))
const  NotFound =lazy(()=>import('./componets/NotFound'))
const  Goods =lazy(()=>import('./componets/Goods'))
const  Order =lazy(()=>import('./componets/Order'))
const  Cart =lazy(()=>import('./componets/Cart'))

//配置路由规则
const routes = [
	{path:"/",redirect:"/home",exact:true},
	{path:"/home",component:Home,exact:false},{path:"/about",component:About,exact:false},{path:"/goods",component:Goods,exact:false},{path:"/order",component:Order,exact:false},{path:"/cart",component:Cart,exact:false},{path:"*",component:NotFound,exact:false},
]

// 封装路由组件
function RouterView() {
	return <Switch>
		{routes.map((item,index)=>{
		if(item.component) {
			return <Route key={index} exact={item.exact} path={item.path} component={item.component}/>
		}else {
			return <Route key={index} exact={item.exact} path={item.path}><Redirect to={item.redirect}></Redirect></Route>
}
})}
	</Switch>
}
export default RouterView

在Layout.jsx中引入使用

import RouterView from '../router/RouterView'
...
render() {
	<React.Suspence fallback={<h1>加载中</h1>}>
		<RouteView />
	</React.Suspence>
}
...

3.封装升级:组件和配置分离

创建组件RouterView.jsx主要用于生成路由组件,不做具体路由规则配置

function RouterView(props) {
	let {routes} = porps
	return <Switch>
		{routes.map((item,index)=>{
		if(item.component) {
			return <Route key={index} exact={item.exact} path={item.path} component={item.component}/>
		}else {
			return <Route key={index} exact={item.exact} path={item.path}><Redirect to={item.redirect}></Redirect></Route>
}
})}
	</Switch>
}
}
export default RouterView

创建配置文件:indexRouter.js用于一级路由规则配置

import {lazy} from 'react'
const  About =lazy(()=>import('./componets/About'))
const  Home =lazy(()=>import('./componets/Home'))
const  NotFound =lazy(()=>import('./componets/NotFound'))
const  Goods =lazy(()=>import('./componets/Goods'))
const  Order =lazy(()=>import('./componets/Order'))
const  Cart =lazy(()=>import('./componets/Cart'))

//配置路由规则
const routes = [
	{path:"/",redirect:"/home",exact:true},
	{path:"/home",component:Home,exact:false},{path:"/about",component:About,exact:false},{path:"/goods",component:Goods,exact:false},{path:"/order",component:Order,exact:false},{path:"/cart",component:Cart,exact:false},{path:"*",component:NotFound,exact:false},
]
export default routes

一级路由,在Layout中使用

import routes from './indexRouter'
import RouterView from './RouterView'
...
render() {
	...
	<RouterView routes={routes} />
	...
}
...

创建类似文件:users.js,主要用于用户中心二级路由配置

import {lazy} from 'react'
const Login = lazy(()=>import('./pages/Login'))
const Register = lazy(()=>import('./pages/Register'))
const routes = [
{path:"/home/login",component:Login},
{path:"/home/Register",component:Register}
]
export default routes

二级路由在Home.jsx中的应用

import routes from './users'
import RouterView from './RouterView'
...
render() {
	...
	<RouterView routes={routes} />
	...
}
...

4.导航守卫

React中没有导航守卫,通过组件中的配置选项,完成导航守卫的功能

组件需要通过路由规则进行匹配渲染,可以在路由规则中添加渲染组件的条件,起到了导航守卫的功能

function RouterView(props) {
	let {routes} = props
	return <Switch>
		{
			routes.map((item,index)=>{
				if(item.component){
					return <Route key={index} exact={item.exact} path={item.path} render={()=>{
	let token = localStorage.getItem("token")
	if(!token&&item.path==='/about'){
		return <Redirect to="/login" />
	}
	let Component = withRouter(item.component)
	return <Component />
}}>
				}
			})
		}
	</Switch>
}

5.编程式导航

路由组件中,this.props中包含了三大模块
match:用于RESTful参数数据传递处理
location:用于查询字符串参数传递处理
history:可以用于编程式导航

编程式导航:借助于this.props.history
go(num)
goBack()
goForward()
push(path):跳转到指定路径,并暴力流跳转历史记录
replace(path):跳转到指定路径,不报保留跳转历史记录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值