中文官网: https://react.docschina.org/

一、虚拟DOM及JSX语法

1、引入

  1. <!-- 准备容器 -->
  2. <div id="test"></div>
  3. <!-- 引入react核心库 -->
  4. <script src="./js/react.development.js"></script>
  5. <!-- 引入react-dom,用于支持react操作dom,需先引入核心库 -->
  6. <script src="./js/react-dom.development.js"></script>
  7. <!-- 引入babel,用于将jsx转为js -->
  8. <script src="./js/babel.min.js"></script>

2、使用jsx创建虚拟dom

  1. <script type="text/babel">
  2. //1.创建虚拟dom
  3. const VDOM = <h1>hello,react</h1> //此处不可写引号,因为不是字符串
  4. const VDOM2 = (
  5. <div id="title">
  6. <span>Hello,react</span>
  7. </div>
  8. )
  9. //2.渲染虚拟dom到页面
  10. ReactDOM.render(VDOM,document.getElementById('test'))
  11. </script>

3、使用js创建虚拟dom(创建虚拟dom不方便)

  1. <script type="text/javascript">
  2. //1.创建虚拟dom
  3. const VDOM = React.createElement('h1',{id:'title'},'Hello React')
  4. //2.渲染虚拟dom到页面
  5. ReactDOM.render(VDOM,document.getElementById('test'))
  6. </script>

4、关于虚拟DOM:
1⃣️本质是object类型的对象虚拟DOM身上属性少,真实DOM身上属性多,因为虚拟DOM是react内部在用,不需要那么多属性
2⃣️虚拟DOM最终会被react展现成真实DOM,呈现在页面上
5、JSX语法规则

  1. 1、定义虚拟DOM不要用引号
  2. 2、标签中混入js表达式要用{}
  3. 3、样式的类名指定不要用class,要用className
  4. 4、内敛样式,要用style={{key:value}}的形式去写
  5. 5、只有一个根标签
  6. 6、标签必须闭合
  7. 7、标签首字母:
  8. 若小写开头,则转为html中同名元素,若无该标签,则报错;
  9. 若大写开头,react就去渲染对应的组件,无则报错。
  10. const myId = "123"
  11. const myData = "hello react"
  12. const VDOM = (
  13. <h2 className="title" id={myId} style={{color:'red'}}>
  14. <span>{myData}</span>
  15. </h2>
  16. )
  17. ReactDOM.render(VDOM,document.getElementById('test'))

6、循环
js表达式:能用变量接收的就是表达式,可以放在任何一个需要值的地方

  1. const data = ["angular","react","vue"]
  2. const VDOM = (
  3. <div>
  4. <h1>前端js框架列表</h1>
  5. <ul>
  6. {
  7. data.map((item,index)=>{
  8. return <li key={index}>{item}</li>
  9. })
  10. }
  11. </ul>
  12. </div>
  13. )
  14. ReactDOM.render(VDOM,document.getElementById('test'))

二、组件化

1、函数式组件

  1. //创建函数式组件
  2. function Demo(){
  3. console.log(this); //此处this是undefined,因为babel编译后开启了严格模式
  4. return <h2>我是函数定义的组件,适用于简单组件的定义</h2>
  5. }
  6. //渲染组件到页面
  7. ReactDOM.render(<Demo/>,document.getElementById('test'))

2、类式组件

(1)类的复习

  1. class Person{
  2. constructor(name,age){ //构造器函数,由实例对象调用,所以指向实例对象
  3. this.name = name
  4. this.age = age
  5. }
  6. speak(){
  7. console.log(`我叫${this.name},我的年龄是${this.age}`);
  8. }
  9. }
  10. //创建student类,继承于person,不使用constructor也可以接收父类自带的name age
  11. class Student extends Person{
  12. constructor(name,age,grade){
  13. super(name,age)
  14. this.grade = grade
  15. }
  16. speak(){ //重写,重写从父类继承的方法,不向原型链继续查找
  17. console.log(`我叫${this.name},我的年龄是${this.age},我是${this.grade}年级`);
  18. }
  19. }
  20. const s1 = new Student('cq',24,'高一')
  21. console.log(s1);
  22. s1.speak()

(2)react 类式组件

  1. class MyComponent extends React.Component {
  2. render() {
  3. //render是放在哪的? ---类的原型对象上,供实例使用。
  4. console.log(this); //render中的this指向? MyComponent组件的实例对象。
  5. return <h2>我是用类定义的组件,用于复杂组件的定义</h2>
  6. }
  7. }
  8. ReactDOM.render(<MyComponent/>,document.getElementById('test'))
  9. //执行ReactDOM.render发生了什么?
  10. //1、React解析组件标签,找到了MyComponent组件。
  11. //2、发现组件是使用类定义的,随后new出来该类的实例。并通过该实例调用原型上的render方法。
  12. //3、将render返回的虚拟DOM,转换为真实DOM。

3、state(组件三大核心属性 — 状态)

(1)标准形式

  1. class Weather extends React.Component {
  2. constructor(props){
  3. super(props)
  4. //1、初始化状态
  5. this.state = {
  6. isHot:false,
  7. wind:'微风'
  8. }
  9. //3、
  10. //解决this为undefinded,即解决this指向问题。
  11. //this.changeWeather = this.changeWeather.bind(this)
  12. }
  13. render() { //render调用1+n次,n是状态更新的次数
  14. const {isHot,wind} = this.state
  15. return <h2 onClick={this.changeWeather}>今天天气很{isHot?'炎热':'凉爽'},{wind}。</h2>
  16. }
  17. changeWeather(){
  18. //2、
  19. //changeWeather放在哪? Weather的原型对象上,供实例使用
  20. //由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用的
  21. //类中的方法默认开启了严格模式,所以changeWeather中的this为undefined
  22. console.log(this)
  23. //4、
  24. // this.state.isHot = !isHot //状态不可这样直接更改,要借助一个内部的api
  25. const { isHot } = this.state
  26. this.setState({isHot:!isHot}) //5、状态必须通过setState进行更改,且是一种合并,不是替换
  27. }
  28. }
  29. ReactDOM.render(<Weather/>,document.getElementById('test'))

(2)简写方式

  1. class Weather extends React.Component {
  2. //初始化状态
  3. state = {
  4. isHot:false,
  5. wind:'微风'
  6. }
  7. render(){
  8. const {isHot,wind} = this.state
  9. return <h2 onClick={this.changeWeather}>今天天气很{isHot?'炎热':'凉爽'},{wind}</h2>
  10. }
  11. //自定义方法--赋值语句+剪头函数
  12. changeWeather = ()=>{
  13. const { isHot } = this.state
  14. this.setState({isHot:!isHot})
  15. }
  16. }
  17. ReactDOM.render(<Weather/>,document.getElementById('test'))

4、props

(1)简单使用

  1. class Person extends React.Component{
  2. render(){
  3. const {name,age,sex} = this.props
  4. //this.props.name = 'Jack' //此行代码会报错,因为props是只读的
  5. return (
  6. <ul>
  7. <li>姓名:{name}</li>
  8. <li>性别:{age}</li>
  9. <li>年龄:{sex}</li>
  10. </ul>
  11. )
  12. }
  13. }
  14. ReactDOM.render(<Person name="Tom" age="18" sex="女"/>,document.getElementById('test'))

(2)批量传递props

  1. const p = {name:'cq',age:18,sex:'男'}
  2. ReactDOM.render(<Person {...p}/>,document.getElementById('test'))
  3. //此处...p展开对象,是react渲染组件的独有形式,不可在其他地方使用,其他地方为复制一个对象。

(3)类型限制与默认值

  1. <!-- 引入prop-types,用于对组件的标签属性进行限制 -->
  2. <script src="./js/prop-types.js"></script>
  3. Person.propTypes = {
  4. name:PropTypes.string.isRequired, //字符串且必传
  5. age:PropTypes.number,
  6. sex:PropTypes.string,
  7. speak:PropTypes.func
  8. }
  9. Person.defaultProps = {
  10. age:0,
  11. sex:'未知'
  12. }

(4)props简写方式
使用static写在类内,静态方法可以直接被类调用,但不能在类的实例上调用

  1. class Person extends React.Component{
  2. render(){
  3. const {name,age,sex} = this.props
  4. return (
  5. <ul>
  6. <li>姓名:{name}</li>
  7. <li>年龄:{age}</li>
  8. <li>性别:{sex}</li>
  9. </ul>
  10. )
  11. }
  12. static propTypes = {
  13. name:PropTypes.string.isRequired,
  14. age:PropTypes.number,
  15. sex:PropTypes.string,
  16. speak:PropTypes.func
  17. }
  18. static defaultProps = {
  19. age:0,
  20. sex:'未知'
  21. }
  22. }
  23. const p = {name:'cq',age:18,sex:'男'}
  24. ReactDOM.render(<Person {...p}/>,document.getElementById('test'))

(5)函数式组件声明props

  1. function Person(props){
  2. const {name,age,sex} = props
  3. return (
  4. <ul>
  5. <li>姓名:{name}</li>
  6. <li>年龄:{age}</li>
  7. <li>性别:{sex}</li>
  8. </ul>
  9. )
  10. }
  11. Person.propTypes = {
  12. name:PropTypes.string.isRequired,
  13. age:PropTypes.number,
  14. sex:PropTypes.string
  15. }
  16. Person.defaultProps = {
  17. age:18,
  18. sex:'男'
  19. }
  20. const p = {name:'cq'}
  21. ReactDOM.render(<Person {...p}/>,document.getElementById('test'))

5、refs

(1)字符串形式的ref(不推荐)

  1. class Demo extends React.Component{
  2. render(){
  3. return(
  4. <div>
  5. <input ref="input1" type="text" placeholder="点击按钮提示"/>&nbsp;
  6. <button ref="button1" onClick={this.showData}>点我提示左侧数据</button>&nbsp;
  7. <input ref="input2" type="text" placeholder="失去焦点提示" onBlur={this.showData2}/>
  8. </div>
  9. )
  10. }
  11. showData = ()=>{
  12. const {input1} = this.refs
  13. alert(input1.value)
  14. }
  15. showData2 = ()=>{
  16. const {input2} = this.refs
  17. alert(input2.value)
  18. }
  19. }
  20. ReactDOM.render(<Demo/>,document.getElementById('test'))

(2)回调形式的ref
react执行时会自动调用ref中的箭头函数

  1. class Demo extends React.Component{
  2. render(){
  3. return(
  4. <div>
  5. <input ref={currentNode => this.input1 = currentNode} type="text" placeholder="点击按钮提示"/>&nbsp;
  6. <button ref="button1" onClick={this.showData1}>点我提示左侧数据</button>&nbsp;
  7. <input onBlur={this.showData2} ref={currentNode=>this.input2 = currentNode} type="text" placeholder="失去焦点提示"/>&nbsp;
  8. </div>
  9. )
  10. }
  11. showData1 = ()=>{
  12. const { input1 } = this
  13. alert(input1.value)
  14. }
  15. showData2 = ()=>{
  16. const {input2} = this
  17. alert(input2.value)
  18. }
  19. }
  20. ReactDOM.render(<Demo/>,document.getElementById('test'))

(3)createRef

  1. class Demo extends React.Component{
  2. //React.createRef()调用后返回一个容器,可以存储被ref标识的节点,该容器是专人专用的
  3. render(){
  4. return(
  5. <div>
  6. <input ref={this.myRef} type="text" placeholder="点击按钮提示"/>&nbsp;
  7. <button ref="button1" onClick={this.showData1}>点我提示左侧数据</button>&nbsp;
  8. <input onBlur={this.showData2} ref={this.myRef2} type="text" placeholder="失去焦点提示"/>&nbsp;
  9. </div>
  10. )
  11. }
  12. myRef = React.createRef()
  13. myRef2 = React.createRef()
  14. showData1 = ()=>{
  15. console.log(this.myRef.current.value);
  16. }
  17. showData2 = ()=>{
  18. console.log(this.myRef2.current.value);
  19. }
  20. }
  21. ReactDOM.render(<Demo/>,document.getElementById('test'))

使用react过程中,尽量避免ref的使用,比如操作节点为当前节点,可以通过event获取节点的属性

6、收集表单数据(非受控、受控组件)

(1)非受控组件(现用现取)

  1. class Login extends React.Component{
  2. handleSubmit = (event)=>{
  3. event.preventDefault(); //阻止默认事件
  4. const {username,password} = this;
  5. alert(`用户名:${username.value},密码:${password.value}`);
  6. }
  7. render() {
  8. return(
  9. <form onSubmit={this.handleSubmit}>
  10. 用户名:<input ref={c=>this.username = c} type="text" name="username"/>
  11. 密码:<input ref={c=>this.password = c} type="text" name="password"/>
  12. <button>登陆</button>
  13. </form>
  14. )
  15. }
  16. }
  17. ReactDOM.render(<Login/>,document.getElementById('test'))

(2)受控组件(随着你的输入维护状态)(推荐)

  1. class Login extends React.Component{
  2. state = { //初始化状态
  3. username:"",
  4. password:""
  5. }
  6. saveUsername = (event)=>{
  7. this.setState({username:event.target.value})
  8. }
  9. savePassword = (event)=>{
  10. this.setState({password:event.target.value})
  11. }
  12. handleSubmit = (event)=>{
  13. event.preventDefault(); //阻止默认事件
  14. const {username,password} = this.state;
  15. alert(`用户名:${username},密码:${password}`);
  16. }
  17. render() {
  18. return(
  19. <form onSubmit={this.handleSubmit}>
  20. 用户名:<input onChange={this.saveUsername} type="text" name="username"/>
  21. 密码:<input onChange={this.savePassword} type="text" name="password"/>
  22. <button>登陆</button>
  23. </form>
  24. )
  25. }
  26. }
  27. ReactDOM.render(<Login/>,document.getElementById('test'))

7、高阶函数__函数柯里化

  1. //高阶函数,如果一个函数满足下面规范的任何一个,就是高阶函数
  2. //1、若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数
  3. //2、若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数
  4. //常见的高阶函数:Promise、setTimeout、arr.map()等等
  5. //函数的柯里化:通过函数调用,继续返回函数的方式,实现多次接收参数,最后统一处理的函数编码形式
  6. // function sum(a){
  7. // return (b)=>{
  8. // return (c)=>{
  9. // return a+b+c;
  10. // }
  11. // }
  12. // }
  13. // const res = sum(1)(2)(3);
  14. // console.log(res)
  15. class Login extends React.Component{
  16. state = { //初始化状态
  17. username:"",
  18. password:""
  19. }
  20. saveFormData = (dataType)=>{
  21. return (event)=>{
  22. this.setState({[dataType]:event.target.value});
  23. }
  24. }
  25. handleSubmit = (event)=>{
  26. event.preventDefault(); //阻止默认事件
  27. const {username,password} = this.state;
  28. alert(`用户名:${username},密码:${password}`);
  29. }
  30. render() {
  31. return(
  32. <form onSubmit={this.handleSubmit}>
  33. 用户名:<input onChange={this.saveFormData('username')} type="text" name="username"/>
  34. 密码:<input onChange={this.saveFormData('password')} type="text" name="password"/>
  35. <button>登陆</button>
  36. </form>
  37. )
  38. }
  39. }
  40. ReactDOM.render(<Login/>,document.getElementById('test'))

非柯里化实现

  1. class Login extends React.Component{
  2. state = { //初始化状态
  3. username:"",
  4. password:""
  5. }
  6. saveFormData = (dataType,e)=>{
  7. this.setState({[dataType]:e.target.value});
  8. }
  9. handleSubmit = (event)=>{
  10. event.preventDefault(); //阻止默认事件
  11. const {username,password} = this.state;
  12. alert(`用户名:${username},密码:${password}`);
  13. }
  14. render() {
  15. return(
  16. <form onSubmit={this.handleSubmit}>
  17. 用户名:<input onChange={e=>this.saveFormData('username',e)} type="text" name="username"/>
  18. 密码:<input onChange={e=>this.saveFormData('password',e)} type="text" name="password"/>
  19. <button>登陆</button>
  20. </form>
  21. )
  22. }
  23. }
  24. ReactDOM.render(<Login/>,document.getElementById('test'))

8、生命周期

(1)旧版16

react生命周期(旧)的副本.png

  1. /*
  2. 1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
  3. 1. constructor()
  4. 2. componentWillMount()
  5. 3. render()
  6. 4. componentDidMount() =====> 常用
  7. 一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
  8. 2. 更新阶段: 由组件内部this.setSate()或父组件render触发
  9. 1. shouldComponentUpdate()
  10. 2. componentWillUpdate()
  11. 3. render() =====> 必须使用的一个
  12. 4. componentDidUpdate()
  13. 3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
  14. 1. componentWillUnmount() =====> 常用
  15. 一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
  16. */
  17. //创建组件
  18. class Count extends React.Component{
  19. //构造器
  20. constructor(props){
  21. console.log('Count---constructor');
  22. super(props)
  23. //初始化状态
  24. this.state = {count:0}
  25. }
  26. //加1按钮的回调
  27. add = ()=>{
  28. //获取原状态
  29. const {count} = this.state
  30. //更新状态
  31. this.setState({count:count+1})
  32. }
  33. //卸载组件按钮的回调
  34. death = ()=>{
  35. ReactDOM.unmountComponentAtNode(document.getElementById('test'))
  36. }
  37. //强制更新按钮的回调
  38. force = ()=>{
  39. this.forceUpdate()
  40. }
  41. //组件将要挂载的钩子
  42. componentWillMount(){
  43. console.log('Count---componentWillMount');
  44. }
  45. //组件挂载完毕的钩子
  46. componentDidMount(){
  47. console.log('Count---componentDidMount');
  48. }
  49. //组件将要卸载的钩子
  50. componentWillUnmount(){
  51. console.log('Count---componentWillUnmount');
  52. }
  53. //控制组件更新的“阀门”
  54. shouldComponentUpdate(){
  55. console.log('Count---shouldComponentUpdate');
  56. return true
  57. }
  58. //组件将要更新的钩子
  59. componentWillUpdate(){
  60. console.log('Count---componentWillUpdate');
  61. }
  62. //组件更新完毕的钩子
  63. componentDidUpdate(){
  64. console.log('Count---componentDidUpdate');
  65. }
  66. render(){
  67. console.log('Count---render');
  68. const {count} = this.state
  69. return(
  70. <div>
  71. <h2>当前求和为:{count}</h2>
  72. <button onClick={this.add}>点我+1</button>
  73. <button onClick={this.death}>卸载组件</button>
  74. <button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
  75. </div>
  76. )
  77. }
  78. }
  79. //父组件A
  80. class A extends React.Component{
  81. //初始化状态
  82. state = {carName:'奔驰'}
  83. changeCar = ()=>{
  84. this.setState({carName:'奥拓'})
  85. }
  86. render(){
  87. return(
  88. <div>
  89. <div>我是A组件</div>
  90. <button onClick={this.changeCar}>换车</button>
  91. <B carName={this.state.carName}/>
  92. </div>
  93. )
  94. }
  95. }
  96. //子组件B
  97. class B extends React.Component{
  98. //组件将要接收新的props的钩子
  99. componentWillReceiveProps(props){
  100. console.log('B---componentWillReceiveProps',props);
  101. }
  102. //控制组件更新的“阀门”
  103. shouldComponentUpdate(){
  104. console.log('B---shouldComponentUpdate');
  105. return true
  106. }
  107. //组件将要更新的钩子
  108. componentWillUpdate(){
  109. console.log('B---componentWillUpdate');
  110. }
  111. //组件更新完毕的钩子
  112. componentDidUpdate(){
  113. console.log('B---componentDidUpdate');
  114. }
  115. render(){
  116. console.log('B---render');
  117. return(
  118. <div>我是B组件,接收到的车是:{this.props.carName}</div>
  119. )
  120. }
  121. }
  122. //渲染组件
  123. ReactDOM.render(<Count/>,document.getElementById('test'))

(2)新版17

react生命周期(新).png

  1. class Count extends React.Component{
  2. /*
  3. 1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
  4. 1. constructor()
  5. 2. getDerivedStateFromProps
  6. 3. render()
  7. 4. componentDidMount() =====> 常用
  8. 一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
  9. 2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
  10. 1. getDerivedStateFromProps
  11. 2. shouldComponentUpdate()
  12. 3. render()
  13. 4. getSnapshotBeforeUpdate
  14. 5. componentDidUpdate()
  15. 3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
  16. 1. componentWillUnmount() =====> 常用
  17. 一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
  18. */
  19. //构造器
  20. constructor(props){
  21. console.log('Count---constructor');
  22. super(props)
  23. //初始化状态
  24. this.state = {count:0}
  25. }
  26. //加1按钮的回调
  27. add = ()=>{
  28. //获取原状态
  29. const {count} = this.state
  30. //更新状态
  31. this.setState({count:count+1})
  32. }
  33. //卸载组件按钮的回调
  34. death = ()=>{
  35. ReactDOM.unmountComponentAtNode(document.getElementById('test'))
  36. }
  37. //强制更新按钮的回调
  38. force = ()=>{
  39. this.forceUpdate()
  40. }
  41. //若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromProps
  42. static getDerivedStateFromProps(props,state){
  43. console.log('getDerivedStateFromProps',props,state);
  44. return null
  45. }
  46. //在更新之前获取快照
  47. getSnapshotBeforeUpdate(){
  48. console.log('getSnapshotBeforeUpdate');
  49. return 'atguigu'
  50. }
  51. //组件挂载完毕的钩子
  52. componentDidMount(){
  53. console.log('Count---componentDidMount');
  54. }
  55. //组件将要卸载的钩子
  56. componentWillUnmount(){
  57. console.log('Count---componentWillUnmount');
  58. }
  59. //控制组件更新的“阀门”
  60. shouldComponentUpdate(){
  61. console.log('Count---shouldComponentUpdate');
  62. return true
  63. }
  64. //组件更新完毕的钩子
  65. componentDidUpdate(preProps,preState,snapshotValue){
  66. console.log('Count---componentDidUpdate',preProps,preState,snapshotValue);
  67. }
  68. render(){
  69. console.log('Count---render');
  70. const {count} = this.state
  71. return(
  72. <div>
  73. <h2>当前求和为:{count}</h2>
  74. <button onClick={this.add}>点我+1</button>
  75. <button onClick={this.death}>卸载组件</button>
  76. <button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
  77. </div>
  78. )
  79. }
  80. }
  81. //渲染组件
  82. ReactDOM.render(<Count count={199}/>,document.getElementById('test'))

三、react应用(基于react脚手架)

1、起步

全局安装
npm install -g create-react-app
创建项目
create-react-app project-name
启动
npm start

2、react-router-dom

安装

  1. npm install react-router-dom
  2. //or
  3. yarn add react-router-dom

引入

  1. //index.js中
  2. import { BrowserRouter } from 'react-router-dom';
  3. <BrowserRouter> //或<HashRouter>
  4. <App />
  5. </BrowserRouter>

使用

  1. <Link to="/xxxxx">Demo</Link>
  2. //NavLink可以实现路由链接的高亮,通过activeClassName指定样式名,默认active
  3. <Switch>
  4. <Route path="/about" component={About}/>
  5. <Route path="/home" exact component={Home}/>//严格匹配当前路由,无法继续匹配二级路由
  6. //Redirect一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
  7. <Redirect to="/about"/>
  8. </Switch>

封装

  1. //封装
  2. <NavLink activeClassName="active" className="list-group-item" {...this.props}/>
  3. //使用
  4. <MyNavLink to="/about">About</MyNavLink> //About接受时为this.props.children

向路由组件传递参数

  1. 1.params参数
  2. 路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
  3. 注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
  4. 接收参数:this.props.match.params
  5. 2.search参数
  6. 路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
  7. 注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
  8. 接收参数:this.props.location.search
  9. 备注:获取到的searchurlencoded编码字符串,需要借助querystring解析
  10. import qs form 'querystring'
  11. const {id,title} = qs.parse(this.props.location.search.slice(1))
  12. 3.state参数
  13. 路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
  14. 注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
  15. 接收参数:this.props.location.state
  16. 备注:刷新也可以保留住参数

函数式路由导航

  1. 借助this.prosp.history对象上的API对操作路由跳转、前进、后退
  2. -this.prosp.history.push()
  3. -this.prosp.history.replace()
  4. -this.prosp.history.goBack()
  5. -this.prosp.history.goForward()
  6. -this.prosp.history.go()

例子

  1. <button onClick={()=> this.pushShow(msgObj.id,msgObj.title)}>push查看</button>
  2. <button onClick={()=> this.replaceShow(msgObj.id,msgObj.title)}>replace查看</button>
  3. pushShow = (id,title)=>{
  4. //push跳转+携带params参数
  5. // this.props.history.push(`/home/message/detail/${id}/${title}`)
  6. //push跳转+携带search参数
  7. // this.props.history.push(`/home/message/detail?id=${id}&title=${title}`)
  8. //push跳转+携带state参数
  9. this.props.history.push(`/home/message/detail`,{id,title})
  10. }
  11. replaceShow = (id,title)=>{
  12. //replace跳转+携带params参数
  13. //this.props.history.replace(`/home/message/detail/${id}/${title}`)
  14. //replace跳转+携带search参数
  15. // this.props.history.replace(`/home/message/detail?id=${id}&title=${title}`)
  16. //replace跳转+携带state参数
  17. this.props.history.replace(`/home/message/detail`,{id,title})
  18. }

BrowserRouter与HashRouter的区别

  1. 1.底层原理不一样:
  2. BrowserRouter使用的是H5history API,不兼容IE9及以下版本。
  3. HashRouter使用的是URL的哈希值。
  4. 2.path表现形式不一样
  5. BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
  6. HashRouter的路径包含#,例如:localhost:3000/#/demo/test
  7. 3.刷新后对路由state参数的影响
  8. (1).BrowserRouter没有任何影响,因为state保存在history对象中。
  9. (2).HashRouter刷新后会导致路由state参数的丢失!!!
  10. 4.备注:HashRouter可以用于解决一些路径错误相关的问题。