安装路由的环境
1.yarn add react-router-dom
2.在入口文件(index.js)处引入
import{BrowserRouter as Router} from "react-router-dom"
3.两种模式(hash模式,历史纪录模式)
hash模式:后面带#号的 HashRouter
拿到#号后面的值:location.hash
历史纪录模式: BrowserRouter(原理,window.history.State)
import {BroswerRouter as Router} from "react-router-dom"
4.使用<Router><App/></router> 将其包起来,通过context传到他下面的所有子孙组件里面
5.引图片(public可以直接引入,不需要require,src下面的图片再用require)
6.引入sass
yarn add node-sass sass-loader
7.阿里矢量图标库如何使用:
font放在public,在public里面的index.html下面引入iconfont.css
8、移动端适配
html{font-size:13.33333vw}
body{font-size:14px}
实例代码:
ReactDOM.render(
<Router>
<App />
</Router>
, document.getElementById('root'));
切换路由
1.<Route path="/路径" component={组件名}></Route>
2.NavLink带样式:点击后会出现active的class类名(在index.js里面设置css样式)
Link不带样式
3.路由切换组件三个属性
history 编程式导航
location(search,state)
match (params)
默认主页
exact精确匹配
<Redirect from="/" to="/one" exact></Redirect>
引入redirect(重定向)
```javascript
<Switch>
<Route path="/one" component={One} />
<Route path="/two" component={Two} />
<Redirect from="/" to="/one" exact></Redirect>
<Route component={notFound}/>
</Switch>
404页面
<Route component={}>
但是此时404页面会出现在所有页面,,解决办法是引入Switch,同时要将Route404这个组件写在最下面
轮播(只有当数据请求到了之后,财经数据发送过去,所以此处做了一个三元运算符进行判断)
实例代码:
请求数据的组件:
import React, { Component } from 'react'
import MySwiper from "../myswiper"
export default class Test2 extends Component {
constructor(props){
super(props)
this.state ={
list:[]
}
}
//这个组件的做用就是异步拿到数据,传给子组件
componentDidMount(){
this.getData()
}
getData(){
fetch("http://localhost:4000/list").then((res)=>res.json()).then((res)=>{
this.setState({
list:res
})
})
}
render() {
return (
<div>
test2
{this.state.list.length>0?
<MySwiper list={this.state.list} />:""}
</div>
)
}
}
lunbo:
import React, { Component } from 'react'
import Swiper from 'swiper'
import "swiper/css/swiper.css"
export default class Test extends Component {
constructor(props){
super(props)
this.state ={
list:[]
}
}
componentDidMount(){
this.getData()
// new Swiper ('.swiper-container', {//如果内容是静态的,可以这样做
// loop: true, // 循环模式选项
// // 如果需要分页器
// pagination: {
// el: '.swiper-pagination',
// }
// })
}
componentDidUpdate(){
//说明数据变化了,异步数据回来
new Swiper ('.swiper-container', {
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
}
})
}
getData(){
fetch("http://localhost:4000/list").then((res)=>res.json()).then((res)=>{
this.setState({
list:res
})
})
}
render() {
return (
<div>
{this.state.list.length}
<div className="swiper-container">
<div className="swiper-wrapper">
{
this.state.list.map((item)=>{
return <div className="swiper-slide" key={item.bannerId}>
{item.name}
</div>
})
}
</div>
<div className="swiper-pagination"></div>
</div>
</div>
)
}
}
withRouter(在路由组件传值时一定要引入withRouter)
监控路由的变化,默认情况下必须经过路由匹配渲染的组件才存在this.props,才拥有路由参数,执行this.props.history.push('/detail')跳转到对应路由的页面,然而不是所有组件都直接与路由相连(通过路由跳转到此组件)的,当这些组件需要路由参数时,使用withRouter就可以给此组件传入路由参数,将react-router的history、location、match三个对象传入props对象上,此时就可以使用this.props。
引入:import{withRouter} from “react-router-dom”
导出:export default withRouter(App);
解决刷新出现react的默认标题栏
刷新时调用一次 在constructon里有调用了一此函数,将this.props.location.pathname传入,就不会刷新产生react
当引入withRouter后就会出现三个参数,location,match,history
监控路由参数的变化(路由传参)
:type传参
取得参数:this.props.match.params.type
useState(新特性) hook
let [a,setA] = userState(1)初始值赋值给a
前面的两个参数为自定义的
let [数据,修改数据的函数] = useState('可以传默认值')
编程式导航:this.props.history.push listen go ...适合做编程式导航和及监听路由的变化("/list/"+type)
match 主要是用于取路由的参数 this.props.match.params.参数
location location.pathname 还能查询location.search 就是?号后面的参数,查询字符串
###qs包
qs这个包可以将这个参数(查询字符串)拆分,?a=xxx&b=xxx
import qs from "queryString" 引入包
location.search.slice(1)去问号
qs.parse(location.search.slice(1)) {a:xxx,b:yyyy}
location.state 可以传递多个值 console.log(this.props.location.state)
无状态组件的路由传值(第一种方法)
组件1:
<div className="App">
<NavLink to="/list/users">users</NavLink>
<NavLink to="/list/goods">goods</NavLink>
<Route path="/list/:type" component={List}></Route>
</div>
组件2:
1.此时在componentDidMount打印this.props 会出现三个参数(match,history,location)
2.使用match里面的this.props.match.params.type拿到变化的路由参数
3.在state中设置参数和数据的初始值
this.state={list:[],type=""}
4.在componentDidMount(){}在组件加载的时候请求数据,分别调用getData方法,只走一次
5.在componentDidUpdate(){}在组件变化时监听路由变化,监听变化
6.因为在componentDidUpdate中监听了路由的变化,并调用了getdata方法修好改了type值,
#####所以一定要判断一下两次切换的路由的值不相等,否侧会不停的请求数据
7.在setState中一定要修改type值否则数据无法切换,值无法拿到无状态组件的路由传值的第二种方法
function App(props) {
console.log(props)
return (
<div className="App">
//第一种方法:
{/* <NavLink to="/list/users">users</NavLink>
<NavLink to="/list/goods">goods</NavLink> */}
//第二种方法:
<button onClick={()=>{props.history.push("/list/user")}}>user</button>
<button onClick={()=>{props.history.push("/list/goods")}}>goods</button>
<Route path="/list/:type" component={List}></Route>
</div>
);
}
类组件
第一种方法
第二种方法
接收的组件使用:
console.log(this.props.match.params.type)
1、NavLink activeClassName 可以指定当前路由的类名
2、 this.props.history.push(“/list”,{type})
第二个组件console.log(this.props.location.state.type)
params 默认值 是一个{} state的默认值是undefined
state传值(传多个值),params传值,(一个参数)
NavLink Link 除了可以 to=“字符串”,还可以写对象to={{pathName:’/list’}}
所以此时做判断
if(!this.props.location.state.type) return
权限路由:
<Route path="/two" render={(props)=>{return sessionStorage.getItem('user')?<Two {...props}/>:<Redirect to="/login">}}></Route>
redirect组件 to属性可以传值
to={{pathname:’/login},state:{key:value}}