React使用

一、React简介

1.1特点

轻量
原生
易扩展
不依赖宿主环境
渐进式
单向数据流
用JS代码声明界面
组件化

1.2使用

1.直接在页面上使用React,引用下面JS

<body>
<div id="root"></div>
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script>
	//React.createElement
	const element = React.createElement("h1", {}, "Hello, world");
    ReactDOM.render(element, document.getElementById("root"));
</script>

<script type="text/babel">
	//JSX
   	const element = <h1>Hello, world!</h1>;
    ReactDOM.render(element, document.getElementById("root"));
</script>
</body>

创建元素用React.createElement或JSX,JSX用babel转义。

2.脚手架
官方:create-react-app
第三方:next.js、umijs

二、React核心概念

2.1JSX

2.2组件和组件属性

创建一个组件

注意: 组件名称必须以大写字母开头。

1.函数组件
返回一个 React 元素

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

对于函数组件,属性会作为一个对象的属性,传递给函数的参数

2.类组件
必须继承React.Component,必须提供render函数,返回一个 React 元素,用于渲染组件

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

对于类组件,属性会作为一个对象的属性,传递给构造函数的参数

注意:组件的属性应该使用小驼峰命名。

组件无法改变自身的属性,React中的数据,自顶而下流动, 单向数据流。

2.3组件的状态

1.什么是组件状态?

  • 组件状态是指组件可以自行维护的数据。
  • 组件状态仅在类组件中有效。
  • 状态本质上是类组件的一个属性,一个对象。

2.状态初始化
2.1在类组件的构造函数中添加state,状态是必须要初始化的,否则为undefined。

constructor(props){
     super(props);
     this.state = {
         n:this.props.number
     }
 }

2.2在类组件中直接添加state,该方法属于JS Next 语法,目前处于实验阶段。

export default class Tick extends Component {
    state = {
        left: this.props.number,
        n: 123
    }
    constructor(props) {
        super(props);
    }
    render() {
        return (<div></div>)
    }
}

3.状态的变化

改变组件状态不能直接用this.state.XXX来改变,React无法监控到状态发生了变化

改变状态要用this.setState(param),该函数为父类提供的构造函数,一旦调用该函数,组件会重新渲染。

  • param是一个对象,函数执行时,param会混入到this.state对象中。
  • 即如果param中有属性与this.state中的属性相同,那么this.state中的属性会被覆盖。
  • 如果属性不相同,则param中的属性会添加到this.state中
// 组件Tick
import React, { Component } from 'react';
export default class Tick extends Component {
    constructor(props){
        super(props);
        this.state = {
            n:this.props.number
        }
        this.timer = setInterval(()=>{
            this.setState({
                n:this.state.n-1
            })
        },1000);
    }
    render() {
        return (
            <>
                <h1>{this.state.n}</h1>
            </>
        )
    }
}

4.案例解析
组件Test.js中,组件A中的状态数据n数据流向依次是A->B->C

import React, { Component } from 'react'
export default class A extends Component {
    state = {
        n: 123
    }
    constructor(props) {
        super(props);
        setInterval(() => {
            this.setState({
                n: this.state.n - 1
            })
        }, 1000);
    }
    render() {
        console.log("A组件重新渲染了")
        return (
            <div>
                <B n={this.state.n} />
            </div>
        )
    }
}
function B(props) {
    return <div>
        B组件:{props.n}
        <C n={props.n} />
    </div>
}
function C(props) {
    return <div>
        C组件:{props.n}
    </div>
}
  • 该案例中组件A数据变化导致组件B组件C数据依次变化。
  • 这说明数据属于谁,谁就有权利更改,该案例中A自己更改了数据,假如组件A还有一个父组件,但是父组件是不能修改A数据的。
  • 该案例同样说明了React数据流是自顶向下流动的。

5.组件的数据来源
目前组件中数据的来源有如下两种途径。

  • props:该数据是由组件的使用者传递的数据,所有权不属于自身,所以组件无法改变数据。
  • state:该数组是由组件自身创建的,所有权属于组件自身,因此组件有权改变该数据。

2.4组件事件

在React中,组件的事件,本质上就是一个属性

按照之前React对组件的约定,由于事件本质上是一个属性,因此也需要使用小驼峰命名法

1、内置组件事件

import React from 'react';
import ReactDOM from 'react-dom';
function handleClick(e){
  console.log("点击了!");
}
const btn = <button onClick={handleClick} onMouseEnter={(e)=>{
  console.log("鼠标进入了!",e);
}}>按钮</button>
ReactDOM.render(btn, document.getElementById('root'));

2、自定义组件事件

//TickControl.js
import React, { Component } from 'react'
import MyComp from './MyComp'

export default class TickControl extends Component {
  state = {
    isOver: false
  }
  render() {
    let status = "正在倒计时";
    if(this.state.isOver){
      status = "倒计时完成";
    }
    return (
      <div>
        <MyComp onOver={()=>{
          this.setState({
            isOver: true
          })
        }} time={6} />
        <h2>{status}</h2>
      </div>
    )
  }
}
//MyComp.js
import React, { Component } from 'react'

export default class MyComp extends Component {
  constructor(props){
    super(props);
    this.state = {
      time: props.time
    }
    const timer = setInterval(()=>{
      this.setState({
        time: this.state.time-1
      })
      if(this.state.time === 0){
        clearInterval(timer);
        this.props.onOver && this.props.onOver();
      }
    },800);
  }
  render() {
    return (
      <div>
        倒计时: {this.state.time}
      </div>
    )
  }
}

如果一个函数逻辑比较复杂的话,我们推荐先将函数封装好,直接绑定在属性上。

//TickControl.js
export default class TickControl extends Component {
  state = {
    isOver: false
  }
  handleOver(){
    this.setState({
      isOver: true
    })
  }
  render() {
    let status = "正在倒计时";
    if(this.state.isOver){
      status = "倒计时完成";
    }
    return (
      <div>
        <MyComp onOver={this.handleOver} time={6} />
        <h2>{status}</h2>
      </div>
    )
  }
}

但这里就有问题了(this的指向问题,在类组件中出现)。

在这里插入图片描述
此时handleOver是在当前对象原型上
在这里插入图片描述

react中,如果没有特殊处理,在事件处理函数中,this指向undefined

解决方法:

1.使用bind函数,绑定this,将方法绑定在当前对象上。

  constructor(props){
    super(props);
    this.handleOver = this.handleOver.bind(this);
  }
  handleOver(){
    this.setState({
      isOver: true
    })
  }

或者

  render() {
    let status = "正在倒计时";
    if(this.state.isOver){
      status = "倒计时完成";
    }
    return (
      <div>
        <MyComp onOver={this.handleOver.bind(this)} time={6} />
        <h2>{status}</h2>
      </div>
    )
  }

在这里插入图片描述
2.箭头函数
我们前面写的就是,只是如果函数过于复杂,不方便阅读。那么我们进行改进。

  handleOver = () => {
    console.log(this);
    this.setState({
      isOver: true
    })
  }

在这里插入图片描述

2.5深入setState

Vue 的渲染是异步执行的,但是React的对状态的改变,可能是异步的也可能是同步的。

如果改变状态的代码处于某个HTML元素的事件中,则其是异步的,否则是同步

开发的时候始终当成异步的,然后使用回调函数进行处理。

this.setState(() => {
    //改变状态
    n: xxx,
}, () => {
    //状态改变完成之后触发,改回调运行在render之后
    xxxx
})

若遇到某个事件,需要同步调用多次,需要使用函数的方式得到最新状态。

this.setState(cur => {
    //改变状态
    return {
        n: xxx
    }
}, () => {
    //状态改变完成之后触发,改回调运行在render之后
    xxxx
})

React会对异步的setState进行优化,将多次setState进行合并(将多次状态改变完成后,再统一对state进行改变,然后触发render)

最佳实践

  • 把所有的setState当作是异步的
  • 永远不要信任setState调用之后的状态
  • 如果要使用改变之后的状态,需要使用回调函数(setState的第二个参数)
  • 如果新的状态要根据之前的状态进行运算,使用函数的方式改变状态(setState的第一个函数)

2.6生命周期

生命周期仅存在于类组件中,函数组件每次调用都是重新运行函数,旧的组件即刻被销毁

React16.3版本以前的生命周期
在这里插入图片描述
React16.3版本以后的生命周期
在这里插入图片描述

注意:componentWillMount()、componentWillReceiveProps()、componentWillUpdate()在React16.3新版本中都被移除;

旧版生命周期

1、constructor

  • 同一个组件对象只会创建一次
  • 不能在第一次挂载到页面之前,调用setState,为了避免问题,构造函数中严禁使用setState

2、componentWillMount(新版被移除)

  • 正常情况下,和构造函数一样,它只会运行一次
  • 可以使用setState,但是为了避免bug,不允许使用,因为在某些特殊情况下,该函数可能被调用多次

3、render

  • 返回一个虚拟DOM,会被挂载到虚拟DOM树中,最终渲染到页面的真实DOM中
  • render可能不只运行一次,只要需要重新渲染,就会重新运行
  • 严禁使用setState,因为可能会导致无限递归渲染

4、componentDidMount

  • 只会执行一次
  • 可以使用setState
  • 通常情况下,会将网络请求、启动计时器、订阅消息等一开始需要的操作,书写到该函数中

组件进入活跃状态

5、componentWillReceiveProps(新版被移除)

  • 即将接收新的属性值
  • 参数为新的属性对象
  • 该函数可能会导致一些bug,所以不推荐使用

6、shouldComponentUpdate

  • 指示React是否要重新渲染该组件,通过返回true和false来指定
  • 默认情况下,会直接返回true
  • 可以做性能优化
shouldComponentUpdate(nextProps, nextState) {
     if (this.props.n === nextProps.n && this.state.n === nextState.n) {
         return false;
     }
     return true;
 }

7、componentWillUpdate(新版被移除)
组件即将被重新渲染

8、componentDidUpdate
往往在该函数中使用dom操作,改变元素

9、componentWillUnmount
通常在该函数中销毁一些组件依赖的资源,比如计时器、取消订阅

新版生命周期

版增加了两个钩子:

getDerivedStateFromProps

通过参数可以获取新的属性和状态
该函数是静态的
该函数的返回值会覆盖掉组件状态
该函数几乎是没有什么用

getSnapshotBeforeUpdate

真实的DOM构建完成,但还未实际渲染到页面中。
在该函数中,通常用于实现一些附加的dom操作
该函数的返回值,会作为componentDidUpdate的第三个参数

React官方为什么要改它的生命周期?
React16.3之前,用户在使用React的时候有一种反模式,组件的props和state同时控制数据(实现原理是在componentWillReceiveProps里监听props的变化,props是变化时使用this.setSate同步props和state的数据),数据来源不再单一。

React官方认为某个数据的来源必须是单一的,否则很容易出现Bug

componentWillReceiveProps生命周期里用户可以操作this,所以在React16.3之后官方移除了componentWillReceiveProps,使用静态属性getDerivedStateFromProps(该属性几乎没什么用)来替代。

2.7传递元素内容

1.传递属性

import React from 'react';
import ReactDOM from 'react-dom';
import Comp from "./Comp"

ReactDOM.render(<Comp html={<h1>传递的元素</h1>} />, document.getElementById('root'));
//Comp组件
export default function Comp(props) {
    return (
        <div className="comp">
            <h1>组件自身的内容</h1>
            {props.html || <h1>默认值</h1>}
        </div>
    )
}

2.语法糖

import React from 'react';
import ReactDOM from 'react-dom';
import Comp from "./Comp"
ReactDOM.render((<Comp>
  <h1>传递的元素</h1>
</Comp>), document.getElementById('root'));
//Comp
export default function Comp(props) {
    return (
        <div className="comp">
            <h1>组件自身的内容</h1>
            {props.children || <h1>默认值</h1>}
        </div>
    )
}

2.8表单

三、React高级指引

3.1属性默认值和类型校验

属性默认值:
通过一个静态属性defaultProps告知react属性默认值

static defaultProps = {
    xxx: xxx
}

属性类型检查:
使用库:prop-types
对组件使用静态属性propTypes告知react如何检查属性

static propTypes = {
    xxx: xxx
}

3.2HOC高阶组件

HOF:高阶函数,以函数作为参数,并返回一个函数,例如(compose、bind、防抖节流)
HOC: 高阶组件,以组件作为参数,并返回一个组件。

react-redux 也是使用 HOC, connect 将应用 store 的值传递到“已连接” 的组件。它还会执行一些错误检查和组件生命周期优化,如果手动完成将导致编写大量重复代码。

3.3ref

使用场景:直接使用dom元素中的某个方法,或者直接使用自定义组件中的某个方法

1.ref作用于内置的html组件,得到的将是真实的dom对象
2.ref作用于类组件,得到的将是类的实例
3.ref不能作用于函数组件,函数组件里面的react 元素才可以使用的。

ref不再推荐使用字符串赋值,字符串赋值的方式将来可能会被移出

对象

export default class MyRef extends Component {
    constructor(props) {
        super(props);
        this.test = React.createRef();   //创建一个 ref 对象
       // 这个对象 也就是  { current : null}  那么就可以通过 { current : null} 替换 React.createRef() 也是可以的。
    }
    getFac= (e)=> {
        this.test.current.focus();
    }
    render(){
        return (
            <div> 
                <input type="text" ref={this.test} />
                <button onClick={this.getFac}>聚焦</button>
            </div>
        ) 
    }
}

函数

函数的调用时间:

  • componentDidMount的时候会调用该函数,在componentDidMount事件中可以使用ref
  • 如果ref的值发生了变动(旧的函数被新的函数替代),分别调用旧的函数以及新的函数,时间点出现在componentDidUpdate之前
    旧的函数被调用时,传递null
    新的函数被调用时,传递对象
  • 如果ref所在的组件被卸载,会调用函数

谨慎使用
能够使用属性和状态进行控制,就不要使用ref。
使用场景:
1.调用真实的DOM对象中的方法 (如聚焦、播放器、画布)
2.某个时候需要调用类组件的方法

ref转发
使用forwardRef方法
在做高阶函数组件的时候有用

3.4Context上下文

react中的上下文的特点:

  • 当某个组件创建了上下文后,上下文中的数据,会被所有后代组件共享,如概念所说,子组件与父组件中都可以使用上下文的数据。
  • 如果某个组件依赖了上下文,会导致该组件不再纯粹(外部数据仅来源于属性props),毕竟组件的数据都是都是一层一层往下传的,如果突然组件的数据来自祖先组件,这会给组件维护起来带来一定的麻烦。
  • 一般情况下,用于第三方组件(通用组件)

四、HOOK

4.1HOOK简介

HOOK是React16.8.0之后出现

组件:无状态组件(函数组件)、类组件

类组件中的麻烦:
1.this指向问题
2.繁琐的生命周期
3.其他问题

HOOK专门用于增强函数组件的功能(HOOK在类组件中是不能使用的),使之理论上可以成为类组件的替代品。

官方强调:没有必要更改已经完成的类组件,官方目前没有计划取消类组件,只是鼓励使用函数组件

HOOK(钩子)本质上是一个函数(命名上总是以use开头),该函数可以挂载任何功能

HOOK种类:

useState
useEffect
其他…


4.2State Hook

State Hook是一个在函数组件中使用的函数(useState),用于在函数组件中使用状态。

  • 函数有一个参数,这个参数的值表示状态的默认值
  • 函数的返回值是一个数组,该数组一定包含两项
    第一项:当前状态的值
    第二项:改变状态的函数

一个函数组件中可以有多个状态,即可以多次使用useState,这种做法非常有利于横向切分关注点。

注意的细节

  1. useState最好写到函数的起始位置,便于阅读

    错误示范:

    import React, { useState } from 'react'
    // 代码写在function外部,是不行的
    const [data, setData] = useState(0)
    export default function TestStateHook() {
      return (
        <div>
          <button onClick={() => {
            setData(data - 1)
          }}> - 1 </button>
          <span> {data} </span>
          <button onClick={() => {
            setData(data + 1)
          }}> + 1 </button>
        </div>
      )
    }
    

在这里插入图片描述

  1. useState严禁出现在代码块(判断、循环)中

  2. useState返回的函数(数组的第二项),引用不变(节约内存空间)

import React, { useState } from 'react'

export default function TestStateHook() {
  const [data, setData] = useState(0);
  //定义一个数组来装setData 函数
  const arr = [setData]
  return (
    <div>
      <button onClick={() => {
        setData(data - 1)
        arr.push(setData)
      console.log( arr[0] === arr[1]); //打印true
      }}> - 1 </button>
      <span> {data} </span>
      <button onClick={() => {
        setData(data + 1)
        arr.push(setData)
      }}> + 1 </button>
    </div>
  )
}
  1. 使用函数改变数据,若数据和之前的数据完全相等(使用Object.is比较),不会导致重新渲染,以达到优化效率的目的。

  2. 使用函数改变数据,传入的值不会和原来的数据进行合并,而是直接替换。

import React, { useState } from 'react'
interface obj {
  a?: number,
  b?: number
}
export default function TestStateHook() {
  const [data, setData] = useState<obj>({ a: 123, b: 321 });
  console.log('函数初始化')
  return (
    <div>
      <p>数字A{data.a} </p>
      <p>数字B{data.b} </p>
      <button onClick={() => {
        setData({ b: 42344 })
      }}>改变B </button>
    </div>
  )
}

在这里插入图片描述

  1. 如果要实现强制刷新组件的情况:

    类组件:使用forceUpdate函数, vue2里面也有一个$foreUpdate来强制刷新组件

    函数组件:使用一个空对象的useState,如: setData({}). 因为传入的值是一个引用值,传入一个空对象的引用地址和原来的对象都是不一样的,传入一个空的数组或者函数也是可以做到的。

  2. 如果某些状态之间没有必然的联系,应该分化为不同的状态,而不要合并成一个对象。

  3. 和类组件的状态一样,函数组件中改变状态可能是异步的(在DOM事件中),多个状态变化会合并以提高效率,此时,不能信任之前的状态,而应该使用回调函数的方式改变状态。

    如果状态变化要使用到之前的状态,尽量传递函数。

    练习:
    1.
    Base state: 0
    Queue: [1, 1, 1]
    Expected result: 1
    
    2.
    Base state: 0
    Queue: [n => n+1, n => n+1, n => n+1]
    Expected result: 3
    
    3.
    Base state: 0
    Queue: [5, n => n+1]
    Expected result: 6
    
    4.
    Base state: 0
    Queue: [5, n => n+1, 42]
    Expected result: 42
    

4.3Effect Hook

Effect Hook:用于在函数组件中处理副作用。

副作用:

  • ajax请求
  • 计时器
  • 其它异步操作
  • 更改真实DOM对象
  • 本地存储
  • 其它会对外部产生影响的操作

函数:useEffect,该函数接收一个函数作为参数,接收的函数就是需要进行副作用操作的函数。

常见的useEffect使用方式,三种

//每次更新之后都要执行 相当于componentDidUpdate
// 如果是请求,会一直请求,需要注意一下
useEffect(() => {
  // 副作用函数的内容
})  


//初始化页面时 只执行第一次 相当于componentDidMount
useEffect(() => {
  // 副作用函数的内容
}, []) 


//1.初始执行一次; 2.每次依赖项的值变化时执行
useEffect(() => {
  // 副作用函数的内容
}, [依赖项]) //依赖项可以有多个

细节

  1. 副作用函数的运行时间点,是在页面完成真实的UI渲染之后。因此它的执行是异步的,并且不会阻塞浏览器。

    与类组件中componentDidMount和componentDidUpdate的区别:

  • componentDidMount和componentDidUpdate,更改了真实DOM,但是用户还没有看到UI更新,同步的。

  • useEffect中的副作用函数,更改了真实DOM,并且用户已经看到了UI更新,异步的。

  1. 每个函数组件中,可以多次使用useEffect,但不要放入判断或循环等代码块中。

  2. useEffect中的副作用函数,可以有返回值,返回值必须是一个函数,该函数叫做清理函数。

    该函数运行时间点:
    1.首次渲染组件不会运行
    2.在每次运行副作用函数之前(在下次运行效果之前清理上一次渲染中的效果)
    3.组件被销毁时一定会运行

useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // Specify how to clean up after this effect:
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
  1. useEffect函数,可以传递第二个参数
    第二个参数是一个数组

    数组中记录该副作用的依赖数据

    当组件重新渲染后,只有依赖数据与上一次不一样的时,才会执行副作用

    所以,当传递了依赖数据之后,如果数据没有发生变化
            副作用函数仅在第一次渲染后运行
            清理函数仅在卸载组件后运行

  2. 副作用函数中,如果使用了函数上下文中的变量,则由于闭包的影响,会导致副作用函数中变量不会实时变化。

import React,{useState,useEffect} from 'react'
export default function App() {
  const [n,setN] = useState(0);
  useEffect(() => {
    setTimeout(()=>{
      console.log(n);//每次渲染都会执行
    },5000)
  })
  return (
    <div>
      <span>{n}</span>
      <button onClick={()=>{
        setN(n+1)
      }}>+</button>
    </div>
  )
}
  1. 副作用函数在每次注册时,会覆盖掉之前的副作用函数,因此,尽量保持副作用函数稳定,否则控制起来会比较复杂。

4.4自定义Hook

State Hook: useState
Effect Hook:useEffect

自定义Hook:将一些常用的、跨越多个组件的Hook功能,抽离出去形成一个函数,该函数就是自定义Hook,自定义Hook,由于其内部需要使用Hook功能,所以它本身也需要按照Hook的规则实现:

  • 函数名必须以use开头
  • 调用自定义Hook函数时,应该放到顶层

4.5Context Hook

用于获取上下文数据

使用context:

import React from 'react'

const context = React.createContext()

const Provider = context.Provider
const Consumer = context.Consumer

function Test() {
  return (
    <Consumer>
      { value => <h1>Test, 上下文的值:{ value }</h1> }
    </Consumer>
  )
}

export default function () {
  return (
    <div>
      <Provider value="hello context hook">
        <Test />
      </Provider>
    </div>
  )
}

使用Context Hook:

import React, { useContext } from 'react'

const context = React.createContext()

const Provider = context.Provider

function Test() {
  // 直接获取
  const value = useContext(context)
  return <h1>Test, 上下文的值:{ value }</h1>
}

export default function () {
  return (
    <div>
      <Provider value="hello context hook">
        <Test />
      </Provider>
    </div>
  )
}

4.6Ref Hook

用以下三种方式创建 Ref 都可以

const myRef = React.createRef()
const myRef2 = React.useRef()	// Ref Hook 的方式
const myRef3 = {current: undefined}

(1)除了可以进行ref操作以外,还能进行数据存储的操作,即相当于在函数式组件中拥有了this
(2)ref的改变不会引起组件的重新渲染

1、引入
import React, { Component,useRef } from ‘react’;

2、使用ref
const xx=useRef(任意内容);
在标签上: ref={xx}

3、操作ref
xx.current.dom操作

4、若使用ref容器存储数据,即当作this来使用
const xx=useRef(初始数据);
改变数据:xx.current=数据;
获取数据:xx.current

Ref Hook用于对ref的缓存,通常用于对某个函数组件节点中某个局部引用进行缓存

五、Router

1.可以根据不同的地址,展示不同的组件

2.可以无刷新的跳转页面

具备上面两个功能的可以称之为路由

React Router

1.react-router:路由核心库,包含诸多和路由相关的核心代码

2.react-router-dom:利用路由核心库,结合实际页面,实现跟页面路由密切相关的功能

两种路由模式

  1. Hash Router 哈希路由

根据url地址中的哈希值来确定显示的组件(原因:哈希值改变,不会刷新页面)

这种模式兼容新最好

  1. Broswer History Router 浏览器历史记录路由

HTML5出现后,新增了History Api 后,浏览器拥有了改变路径二不刷新页面的方式

History表示浏览器的历史纪录,它使用栈的方式存储

history.length:获取栈中的数据量

history.pushState()

参数1:附加的数据,自定义的数据,可以是任何类型

参数2:页面标题,目前大部分浏览器不支持

参数3:新的地址

history.replaceState()

参数1:附加的数据,自定义的数据,可以是任何类型

参数2:页面标题,目前大部分浏览器不支持

参数3:新的地址

根据页面的路径来决定渲染哪个组件

路由组件

  1. Router组件

它本身不会做任何展示,仅提供路由模式配置,另外,该组件会产生一个上下文,上下文中会提供一些使用的对象和方法,供其他相关组件使用

1.HashRouter :该组件,使用hash模式匹配

2.BrowserRouter:该组件使用了BrowserHistory模式匹配

通常情况下,Router组件只有一个,该组件包裹整个页面

  1. Route组件

根据不同的地址,展示不同的组件

两个重要属性

1.path:匹配的路径

默认情况下不区分大小写, 可以添加boolean属性sensitive来控制是否区分大小写

默认情况下,只匹配根目录,加上boolean属性exact进行精确匹配

如果不写path的话,会匹配所有路径

2.component:匹配成功后显示的组件

3.children:

传递React元素,无论是否匹配,一定会显示children,并且会忽略component属性

传递一个函数,该函数有多个参数,这些参数来自于上下文,该函数返回React元素,则一定会显示返回的元素,并且忽略component属性

Route组件可以写在任何地方,只要保证他是Router组件的后代元素

六、Redux

https://www.redux.org.cn/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值