React学习笔记

28 篇文章 0 订阅
24 篇文章 0 订阅

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

y_w_x_k

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值