1.配置路由代理的两种方式
a:在package.json中直接添加代理,请求到本地端口:
//package.json
"proxy" : "http://localhost:5000"
//请求
axios.get("http://localhost:3000/movies")
b.创建setupProxy.js文件
const {createProxyMiddleware}=require("http-proxy-middleware")
module.exports=function(app){
app.use("/api1",
createProxyMiddleware({
target : 'http://localhost:5000',
changeOrigin : true, //控制服务器收到的请求头的host值,true:http://localhost:5000,false:http://localhost:3000
pathRewrite : {
"^/api1" : ''
}
})
)
app.use("/api2",
createProxyMiddleware({
target : 'http://localhost:5001',
changeOrigin : true,
pathRewrite : {
"^/api2" : ''
}
})
)
}
2.消息订阅与发布
消息发布组件:
import PubSub from "pubsub-js"
search=()=>{
PubSub.publish("myMessage",{isFirst:false,isLoading : true})
}
消息订阅组件:
import PubSub from "pubsub-js"
componentDidMount(){
this.pubHandle=PubSub.subscribe("myMessage",(mes,data)=>{
this.setState(data)
})
}
componentWillUnmount(){
PubSub.unsubscribe(this.pubHandle)
}
3.fetch请求
fetch("/api1/search/users?q="+str).then(res=>{
return res.json()
}).then(res=>{
PubSub.publish("myMessage",{users : res.items,isLoading:false})
}).catch(err=>{
PubSub.publish("myMessage",{err : err,isLoading:false})
})
4.连续结构赋值并重命名
const obj={a:{b:{c:3}}}
const {a:{b:{c:d}}}=obj
console.log(d);
5.React-router-dom
//index.jsx
import {BrowserRouter} from "react-router-dom"
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
//react-router-6.0版本,建议安装5.0版本
//组件内
<div className='left'>
<Link to="/about">about页</Link>
<Link to="/home">首页</Link>
</div>
<div className='right'>
<Routes>
<Route path="/about" element={<About></About>}/>
<Route path="/home" element={<Home></Home>}/>
</Routes>
</div>
//高亮路由
import {NavLink} from "react-router-dom"
<NavLink className={({isActive})=>isActive ? 'demo' : ''} to="/about">about页</NavLink>
<NavLink className={({isActive})=>isActive ? 'demo' : ''} to="/home">首页</NavLink>
6.Switch/Route路由组件
可以使路由匹配到后不会继续向下匹配,可以提升性能
<Switch>
<Route path="/about" component={About}></Route>
<Route path="/home" component={Index}/>
<Route path="/home" component={Home}/>
</Switch>
7.路由精准匹配:路由与地址必须完全一致,不能多几个字符
<div className='left'>
<MyNavLink to='/home' children="首页" />
<MyNavLink to='/about/a/b' children="关于" />
</div>
<div className='right'>
<Switch>
<Route exact={true} path="/home" component={Home}/>
<Route exact path="/about" component={About}></Route>
</Switch>
</div>
8.路由重定向,如果其他的路由都无法匹配到,则跳转到重定向页面
<div className='body'>
<div className='left'>
<MyNavLink to='/home' children="首页" />
<MyNavLink to='/about/a/b' children="关于" />
</div>
<div className='right'>
<Switch>
<Route exact={true} path="/home" component={Home}/>
<Route exact path="/about" component={About}></Route>
<Redirect to="/about"></Redirect>
</Switch>
</div>
9.二级路由及其重定向
<div className="row">
<h1>Home页面</h1>
<div className='home-title'>
<h3><MyNavLink to="/home/news" children="NEWS"/></h3>
<h3><MyNavLink to="/home/message" children="MESSAGE"/></h3>
</div>
<div className='home-content'>
<Switch>
<Route path="/home/news" component={News}></Route>
<Route path="/home/message" component={Message}></Route>
<Redirect to="/home/news"></Redirect>
</Switch>
</div>
</div>
10.路由参数传递
a.params传参:
<div className='body'>
<div className='left'>
<Link activeclassname='demo' to="/about/121/英雄" >about页</Link>
<Link activeclassname='demo' to="/home">首页</Link>
</div>
<div className='right'>
<Route path="/about/:id/:title" component={About}></Route>
<Route path="/home" component={Home}/>
</div>
</div>
//接收参数
const {id,title}=this.props.match.params
b.search传参:
<div className='body'>
<div className='left'>
<Link activeclassname='demo' to="/about?id=11&title=333" >about页</Link>
<Link activeclassname='demo' to="/home">首页</Link>
</div>
<div className='right'>
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}/>
</div>
</div>
//接收参数
import qs from "qs"
const {id,title}=qs.parse(this.props.location.search.slice(1))
c.state传参,此方式参数不会显示在地址栏,但是哈希模式下刷新页面参数会丢失
<div className='body'>
<div className='left'>
<Link activeclassname='demo' to="/about" >about页</Link>
<Link activeclassname='demo' to={ {pathname:'/home',state:{id:223,title:"霸王别姬"}} }>首页</Link>
</div>
<div className='right'>
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}/>
</div>
</div>
//接收参数
const {id,title}=this.props.location.state
11.编程式路由导航
this.props.history.push(`/home/message/detail`,{id:item.id,name:item.name,year:item.year})
this.props.history.replace(`/home/message/detailid=${item.id}&name=${item.name}&year=${item.year}`)
this.props.history.goBack()
this.props.history.goForward()
this.props.history.go(-2)
12.redux
App组件引入容器组件,容器组件连接redux与UI组件,容器组件内引入redux的action方法,并传递redux的state属性与action方法到子UI组件,UI组件内通过props调用redux参数与方法
详情参考:https://gitee.com/ywxkweb/react-redux-demo
13.setState回调
setState是异步的,如果setState状态改变后想获取最新数据要用setState回调
state={
num:0,
}
changeData=()=>{
let {num}=this.state
num++
this.setState({num:num},()=>{
console.log(this.state.num);
})
}
render() {
return <div>
<h2>{this.state.num}</h2>
<button onClick={this.changeData}>点击</button>
</div>;
}
14.函数式setState
state={
num:0,
}
changeData=()=>{
this.setState((state,props)=>{
console.log(state,props);
return {num:++state.num}
},()=>{
console.log(this.state.num);
})
}
render() {
return <div>
<h2>{this.state.num}</h2>
<button onClick={this.changeData}>点击</button>
</div>;
}
15路由懒加载
import React,{Component,lazy,Suspense} from 'react';
const Home=lazy(()=>import("./pages/Home"))
const About=lazy(()=>import("./pages/About"))
<Suspense fallback={<h2>waiting...</h2>}>
<Switch>
<Route path="/home" component={Home}/>
<Route path="/about" component={About}></Route>
<Redirect to="/home"></Redirect>
</Switch>
</Suspense>
16.stateHook
import React from "react"
function FuncDemo(){
//第一次初始化的参数会被缓存
let [count,setCount]=React.useState(100)
let [name,setName]=React.useState("长津湖")
function add(){
//setCount(++count)
setCount(count=>++count)
}
function changeName(){
setName("天下无贼")
}
return (
<div>
<h1>funcDemo</h1>
<h2>求和为{count}</h2>
<button onClick={add}>点击</button>
<h2>{name}</h2>
<button onClick={changeName}>改变名称</button>
</div>
)
}
export default FuncDemo
17.effectHook,类似生命周期函数
//第二个参数,要监测的变量,不传则监测所有state变量,为空则不监测任何state变量
React.useEffect(()=>{
console.log("aaa");
const timer=setInterval(()=>{
setCount(++count)
},1000)
//返回一个函数,相当于类式组件中的willunmount生命周期
return ()=>{
clearInterval(timer)
console.log("<<<<<<<<");
}
},[])
18.refHook
const myRef=React.useRef()
console.log(myRef.current.value);
19.祖组件与后代组件的值传递
import React, { Component } from 'react';
const MyContext=React.createContext()
const {Provider,Consumer}=MyContext
export default class Context extends Component {
state={
movie : '唐人街探案',
price : 111
}
render() {
const {movie,price}=this.state
return <div>
<h1>A组件</h1>
<h1>A电影名:{movie}</h1>
<Provider value={{movie,price}}>
<B></B>
</Provider>
</div>;
}
}
class B extends Component{
//声明接收祖组件参数
static contextType=MyContext
render(){
return <div>
<h2>B组件</h2>
<h2>电影名称:{this.context.movie}</h2>
<C></C>
</div>
}
}
class C extends Component {
static contextType=MyContext
render() {
console.log(this);
return <div>
<h3>C组件</h3>
<h3>电影名称:{this.context.movie}</h3>
<h3>电影票价:{this.context.price}</h3>
<D></D>
</div>;
}
}
function D(){
return (
<div>
<h4>函数式组件D</h4>
<Consumer>
{
value=>{
console.log(value);
return (
<div>
<h4>电影名称:{value.movie}</h4>
<h4>电影票价:{value.price}</h4>
</div>
)
}
}
</Consumer>
</div>
)
}
20.PureComponent
组件继承PureComponnet可以在状态没有发生改变的时候不渲染组件,提升性能。
import React, { Component,PureComponent } from 'react';
export default class Context extends PureComponent {
//不能直接改变对象或数组的值,setState需要传入跟原来不一样的指针
}
21.插槽
//父组件render
render() {
const {movie,price,mArr}=this.state
return <div>
<B render={(name)=><C name={name}/>} />
</div>;
}
//子组件B
class B extends PureComponent{
state={
name : '墨攻'
}
render(){
return <div>
<h3>{this.props.render(this.state.name)}</h3>
</div>
}
}
22.错误边界
使用错误边界,在父组件监听,使错误停留在子组件,不会让页面空白,提示友好,只能捕获生命周期错误,一般用来捕获render时错误
import React, { Component,PureComponent } from 'react';
const MyContext=React.createContext()
export default class Context extends Component {
state={
movie : '唐人街探案',
price : 111,
hasError : '',
}
static getDerivedStateFromError(error){
return {hasError : error}
}
componentDidCatch(error,info){
console.log("统计页面错误,发送请求到后端,修正错误",error,info);
}
render() {
const {movie,price,hasError}=this.state
return <div>
<h1>A组件</h1>
<h1>A电影名:{movie}</h1>
{ hasError ? <h3>网络错误</h3> : <B /> }
</div>;
}
}
class B extends PureComponent{
state={
name : '墨攻',
mArr:"aaa"
}
render(){
console.log("子组件调用了嘛",this);
return <div>
<h2>B组件</h2>
{
this.state.mArr.map((item,index)=>{
return (
<h3 key={index}>{item}</h3>
)
})
}
</div>
}
}