关于javascript:react学习

47次阅读

共计 20255 个字符,预计需要花费 51 分钟才能阅读完成。

react

框架库

  • react-router 路由
  • pubsub 音讯治理
  • redux 状态治理
  • ant-design UI 库

要点

  • jsx 最初翻译过去就是 React.createElement 办法

    createElement(element,options,content)

    elment 元素名称

    options 属性对象

    content 属性外面的内容

    demo: createElement('h1',{id:'test'},'hello react')

  • 虚构 dom 解析后是 Object
  • jsx 注意事项

    1. 变量用一个大括号括起来;
    2. 如果援用 class 款式,须要用className
    3. 定义的 jsx 不须要引号,如果有多层,用小括号括起来
    4. 内联款式 style 要用对象的模式,且属性要用驼峰命名
    5. 只容许一个根标签
    6. 标签必须闭合
    7. 自定义组件以大写字母结尾

      const name='zhangsan'
      const Rdom=(
          <div>
              <h1 className='test' style={{fontSize:'20px'}}>{name}<h1>
              <h1 className='test' style={{fontSize:'20px'}}>{name}<h1>
          </div>
      )
  • react创立函数组件

    1. 函数名大写, 且要有返回值
    2. 援用须要用标签,且标签要有闭合

      function Demo(){return <h1>demo test</h1>}
      ReactDOM.render(<Demo/>,document.getElementById('test'))
  • react创立类组件

    1. 自定义组件类必须继承React.Component
    2. 类组件外面必须定义 render 办法,并且须要返回值
    3. 调用组件,渲染到页面,组件是命名是大写结尾
    4. 调用组件会 new 一个组件,而后调用 render 办法,且类外面 this 指向的是组件创立的实力对象,也叫组件实力对象。
    class MyComponent extends React.Component{render(){
               return (<h1>test</h1>)
           }
       }
       ReactDOM.render(<MyComponent/>,document.getElementById('test'))
  • react事件以及state

    1. 节点绑定事件须要用on+ 事件名,须要驼峰命名

    2. 事件的回调函数须要用 bind 从新绑定, 否则 this 会失落, 或者用箭头函数赋值给属性,绑定该属性

    3.state对象外面须要定义须要变动的状态(属性)

    4. 更改 state 外面的状态,须要用 this.setState 办法

    5. 自定义办法须要用箭头函数赋值给属性,或者用 bind 办法绑定this

     class ChangeWeather extends React.Component{constructor(){super()
             this.state={flag:true}
             this.changeFlag=this.changeFlag.bind(this)
         }
         render(){const {flag}=this.state
             return (<h1 onClick={this.changeFlag}> 今天天气很{flag?'好':'不好'}</h1>
             )
         }
         changeFlag(){
            this.setState({flag:!this.state.flag})
         }
     }
     ReactDOM.render(<ChangeWeather/>,document.getElementById('test'))
      // 下面例子精简版
    class ChangeWeather extends React.Component {state = { flag: true}
            render() {const { flag} = this.state
                return (<h1 onClick={this.changeFlag}> 今天天气很{flag ? '好' : '不好'}</h1>
                )
            }
            changeFlag = () => {
                this.setState({flag: !this.state.flag})
            }
        }
        ReactDOM.render(<ChangeWeather />, document.getElementById('test'))
  • react外面的props

    1. 通过标签传递属性, 能够通过扩大运算符进行传递

    2. 组件外面通过 props 援用

    3. 如果是变量须要用大括号的模式进行传递

     class ChangeWeather extends React.Component{render (){
               return (
                   <div>
                        {this.props.title}
                        {this.props.age}
                        {this.props.obj.test}
                        {this.props.test}
                    </div>
               )
           }
       }
        const obj={test:123}
        ReactDOM.render(<ChangeWeather title="title" age={18} obj={obj} {...obj}/>, document.getElementById('test'))
  • props的属性限度以及默认值

    1.16.x 版本之前是用 React.propsType.xxxx 进行限度,之后的版本是须要引入 propstype.js,而后再类的propTypes 属性下面进行定义

    2. 限度属性的时候,间接定义到类下面进行限度

    3. 如果是函数限度传的类型为func,而不是function

    4. 如果没有传值,须要给默认值,须要再类的 defaultProps 属性下面进行定义默认值

    5. 定义的这些规定须要咋渲染之前进行定义

    6. 定义的属性规定也能够用动态属性进行定义static

     // 间接定义到类下面
    class ChangeWeather extends React.Component{render (){
               return (
                   <div>
                        {this.props.title}
                        {this.props.age}
                        {this.props.obj.test}
                        {this.props.test}
                    </div>
               )
           }
       }
            // 须要再渲染之前进行规定定义,在类的 propTypes 下面进行定义
           ChangeWeather.propTypes = {
                title: PropTypes.string.isRequired,
                fun:PropTypes.func.isRequired// 函数要用 func 这个类型
            }
            // 默认值须要再类的 defaultProps 属性下面进行定义
            ChangeWeather.defaultProps={
                title:"fdsaf",
                fun:function(){}
                
            }
        const obj={test:123,}
        ReactDOM.render(<ChangeWeather title="test" age={18} obj={obj} {...obj}/>,             document.getElementById('test'))
      // 用动态属性的形式
    class ChangeWeather extends React.Component {
            static propTypes = {
                title: PropTypes.string.isRequired,
                fun: PropTypes.func.isRequired
            }
            static defaultProps = {
                title: "fdsaf",
                fun: function () {}
    
            }
            render() {
                return (
                    <div>
                        {this.props.title}
                        {this.props.age}
                        {this.props.obj.test}
                        {this.props.test}
                    </div>
                )
            }
        }
    
        const obj = {test: 123,}
        ReactDOM.render(<ChangeWeather title="test" age={18} obj={obj} {...obj} />, document.getElementById('test'))
  • react外面的ref

    1. 在节点外面通过 ref 属性进行绑定

    2. 在逻辑外面通过 refs 承受

    3. 承受的 ref 是一个实在节点

      class Test extends React.Component{render(){
                return (
                    <div>
                        <input ref="input1" type="text"/>
                        <button onClick={this.btnClick}> 点击 </button>
                    </div>
                )
            }
            btnClick=() => {const {input1}=this.refs
                alert(input1.value)
            }
        }
        ReactDOM.render(<Test/>,document.getElementById('test'))

    4.ref通过回调形式获取

     /* ref  回调函数的模式 */
       class Reftest extends React.Component{
           inputel=null
           btnClick=() => {alert(this.inputel.value)
           }
           render(){
               return (
                   <div>
                    <input  type="text" ref={(el)=>{this.inputel=el}}/>
                    <button onClick={this.btnClick}> 点击 </button>
                   </div>
               )
           }
        }
        ReactDOM.render(<Reftest/>,document.getElementById('test'))
    1. ref如果用内联的形式进行获取,在数据更新的 时候会调用两次回调函数,第一次会给回调函数传 null 第二次会传以后的节点。解决办法为间接用绑定的回调函数。只会调用一次回调函数,不会调用屡次。然而内联和绑定的形式不会有任何影响。开发中个别用内联的形式进行开发。
    2. ref的创立形式三,通过 React.createRef 的形式创立。该函数调用后会返回一个对象,keycurrent 的对象,值为节点。有多少个 ref 就要调用几次后面的函数。官网举荐写法

       /* ref  React.createRef 的形式 */
         class Test extends React.Component{
             // 有多少个就要创立多少个
             refstest=React.createRef();
             btnclick=()=>{console.log(this.refstest.current.value);
                 
             }
             render(){
                 return (
                     <div>
                         // 这里了是须要绑定下面返回的属性
                          <input ref={this.refstest} type="text"/>
                          <button onClick={this.btnclick}> 点击 </button>
                      </div>
                 )
             }
         }
         ReactDOM.render(<Test/>,document.getElementById('test'))
  • react的非受控组件
  1. 所有的表单组件现用现取的组件。取值须要用到ref
  • react的受控组件

    1. 所有的输入框的值都存到状态外面,相似 vue 的双向绑定

          /* 受控组件 */
          class Test extends React.Component {
              state = {name: ''}
              getTestValue = (e) => {
                  this.setState({name: e.target.value})
              }
              handleClick = () => {console.log(this.state.name);
              }
              render() {
                  return (
                      <div>
                          <input type="text" onChange={this.getTestValue} />
                          <button onClick={this.handleClick}> 点击 </button>
                      </div>
                  )
              }
          }
          ReactDOM.render(<Test />, document.getElementById('test'))
  • 函数的柯力化以及高阶函数

    1. 高阶函数:

    1.1 函数返回一个函数

    1.2 函数传参,该参数为一个函数

    2. 柯力化函数:

    2.1 函数返回函数,最初返回的函数一起解决后面函数的参数。

        class Test extends React.Component {
            state = {name: ''}
            getTestValue = (name) => {return (event) => {console.log(name,event);
              }
            }
            handleClick = () => {console.log(this.state.name);
            }
            render() {
                return (
                    <div>
                        <input type="text" onChange={this.getTestValue('test')} />
                        <button onClick={this.handleClick}> 点击 </button>
                    </div>
                )
            }
        }
        ReactDOM.render(<Test />, document.getElementById('test'))
  • react的申明周期

    ReactDOM.unmountComponentAtNode(el)卸载组件

    // 只有一获取值就销毁组件
    class Test extends React.Component {getValue(key, e) {ReactDOM.unmountComponentAtNode(document.getElementById('test'))
            }
            render() {
                return (
                    <div>
                        <input type="text" onChange={(e) => {this.getValue('userName', e) }} />
                    </div>
                )
            }
        }
        ReactDOM.render(<Test />, document.getElementById('test'))
  • react组件生命周期

    1.componentDidMount// 组件挂在时调用,只调用一次

    2.componentWillUnmount // 组件行将销毁

       /* 组件生命周期演示 */
        class Test extends React.Component {
            state = {count: 1}
            timer = null;
            render() {const { count} = this.state;
                return (
                    <div>
                        <div> 数字:{count}</div>
                        <div onClick={this.removeTimer}> 点击我 </div>
                    </div>
                )
            }
            // 组件挂载
            componentDidMount() {this.timer = setInterval(() => {let { count} = this.state;
                    count += 1;
                    this.setState({count,})
                }, 200)
            }
            // 组件行将卸载
            componentWillUnmount() {clearInterval(this.timer)
            }
            removeTimer = () => {
                // 移除以后组件
                ReactDOM.unmountComponentAtNode(document.getElementById('test'))
            }
        }
        ReactDOM.render(<Test />, document.getElementById('test'))
  • 子组件生命周期执行程序

    1. constructor
    2. componentWillMount
    3. render
    4. componentDidMount
    5. componentWillUnmount
  • getSnapshotBeforeUpdate

       // 初始化的申明周期执行程序
    class Demo extends React.Component {constructor(props) {super(props)
                console.log('constructor');
                this.state = {count: 1}
            }
    
            componentWillMount() {console.log('componentWillMount');
            }
            componentWillUnmount() {console.log('componentWillUnmount');
            }
            render() {console.log('render');
                const {count} = this.state
                return (
                    <div>
                        <div> 展现的 count:{count}</div>
                        <div onClick={this.btnClick}> 点击我 </div>
                        <div onClick={this.remove}> 卸载组件 </div>
                    </div>
                )
            }
            remove = () => {ReactDOM.unmountComponentAtNode(document.getElementById('test'))
            }
            btnClick = () => {let { count} = this.state
                count += 1;
                this.setState({count,})
            }
        }
        ReactDOM.render(<Demo />, document.getElementById('test'))
    
         class A extends React.Component{
            state={count:1}
            render(){console.log('render');
                const {count}=this.state
                return (
                    <div>
                        <B name={count}/>
                        <div>count {count}</div>
                        <div onClick={this.btnClick}> 点击我 </div>
                    </div>
                )
            }
            // 跟新的时候会走这个生命周期,必须要返回 true 或者 false, 若返回 false 就不会执行前面的申明周期
            shouldComponentUpdate(){console.log('shouldComponentUpdate');
                return true
            }
            componentWillUpdate(){console.log('componentWillUpdate');
            }
            componentDidUpdate(){console.log('componentDidUpdate');
    
            }
            btnClick=() => {let {count}=this.state
                count+=1;
                this.setState({count ,})
            }
        }
        class B extends React.Component{
            // 父组件传递的 props 更新了才会调用这个生命周期,首次不会调用该生命周期
            componentWillReceiveProps(){console.log('componentWillReceiveProps');
            }
            render(){
                return (<div>{this.props.name}</div>
                )
            }
        }
    
        ReactDOM.render(<A />, document.getElementById('test'))
      class Demo extends React.Component {
            state = {arr: []
            }
            componentDidMount() {setInterval(() => {const { arr} = this.state;
                    this.setState({arr: ['新闻' + (arr.length + 1), ...arr]
                    })
                }, 1000)
            }
            // 新的申明周期,在更新前执行,能够像 componentDidUpdate 申明周期外面传递一个参数
            getSnapshotBeforeUpdate() {return this.refs.list.scrollHeight}
            componentDidUpdate(prepops, prestates, scrollheight) {console.log(this.refs.list.scrollHeight, '...', scrollheight);
    
                this.refs.list.scrollTop += this.refs.list.scrollHeight - scrollheight
    
            }
            render() {
                return (
                    <div>
                        <div className="list" ref="list">
                            {this.state.arr.map((item, index) => {
                                    return (<div key={index} className="li">{item}</div>
                                    )
                                })
                            }
                        </div>
                    </div>
                )
            }
        }
        ReactDOM.render(<Demo />, document.getElementById('test'))
  • react diff算法

    1. 通过数据渲染成虚构dom
    2. 通过 key 值去判断是否存在雷同的值,如果 key 值雷同,判断对应的内容是否雷同,若内容雷同复用原来的 dom,如果不雷同,创立新的dom 渲染到页面,如果 key 值不雷同间接生成 dom 渲染到页面
    3. 应用 index 作为 key 值存在的问题:可能会使效率低下 (旧dom 可能复用不了),页面错位(若数据存在逆反操作)。
  • react脚手架

    1. 全局装置npm i -g create-react-app

    2. 进入要创立我的项目的目录控制台执行 create-react-app projectName 即创立胜利

  • 款式模块化

    1. 利用文件名 XXX.module.css,引入形式import hello from './xxx.module.css' 在用的中央用 hello.className 的模式进行

    2. 利用 less 进行嵌套

  • react组件父子通信

    1. 父传子利用 props 进行传递

    2. 子传父利用 props 给子组件传递函数,子组件通过 props 接管该函数,而后调用,且能够传值。

  • 公共用的状态放到父组件中(状态晋升), 状态定义到哪里,对应的办法就对应在哪个组件中
  • 解决跨域

    1. 利用 package.jsonproxy字段进行代理。申请的时候用本地的域名加端口号加接口名进行申请

      //pageage.json   
      "development": [
            "last 1 chrome version",
            "last 1 firefox version",
            "last 1 safari version"
          ],
          "proxy":"http://localhost:5000"
       // 申请的地址,端口号为本地的 3000,3000 代理到服务器为端口号 5000 的服务器
      axios.get('http://localhost:3000/students')
            .then((res) => {console.log(res.data)
            })
        }

      2. 在我的项目目录 src/ 下新建 setupProxy.js 文件,而后写入如下代码:

      const proxy = require('http - proxy - middleware');
      
      module.exports = function (app) {
          app.use(proxy('/api', { 
              target: 'http://localhost:5000',
              secure: false,
              changeOrigin: true,
              pathRewrite: {"^/api": ""},
          }));
      };
  • 兄弟组件之间的通信,利用pubsubjs

    1. 装置pubsub-js

      yarn add pubsub-js

    2. 引入 pubsubjs 并在传递数据的组件中进行音讯公布,在须要获取数据的组件中进行音讯订阅

        componentDidMount() {this.id=Pubsub.subscribe('getData', (name, stateObj) => {this.setState(stateObj)
               })
          }
      componentWillUnmount(){pubsub.undescribe(this.id)
      }
      request=()=>{
              axios.get('http://localhost:3000/xxx')
                  .then((res) => {
                      Pubsub.publish('getData',{
                          loading: false,
                          users: res.data.items,
                          err:false
                      })
                  })
                  .catch((err) => {
                      Pubsub.publish('getData',{
                          loading: false,
                          err:err.message
                      })
                   })
      }
  • react路由

    1. 装置react-router-dom

    yarn add react-router-dom

    引入必要组件

    import React, {Component} from 'react'
    import {Link, Route} from 'react-router-dom'
    import About from './components/About'
    import Home from './components/Home'
    export default class App extends Component {render() {
        return (
          <div>
            <div className="row">
              <div className="col-xs-offset-2 col-xs-8">
                <div className="page-header"><h2>React Router Demo</h2></div>
              </div>
            </div>
            <div className="row">
              <div className="col-xs-2 col-xs-offset-2">
                <div className="list-group">
                  {/* <a className="list-group-item active" href="./about.html">About</a>
                  <a className="list-group-item" href="./home.html">Home</a> */}
                  <Link to="/about" className="list-group-item">About</Link>
                  <Link to="/home" className="list-group-item">Home</Link>
                </div>
              </div>
              <div className="col-xs-6">
                <div className="panel">
                  <div className="panel-body">
                    {/* <h3> 我是 About 的内容 </h3> */}
                    <Route path='/about' component={About}/>
                  <Route path='/Home' component={Home}/>
                </div>
              </div>
            </div>
            </div>
            </div>
        )
      }
    }
    import React from 'react';
    import ReactDOM from 'react-dom';
    import {BrowserRouter} from 'react-router-dom'
    import './index.css';
    import App from './App';
    
    ReactDOM.render(
      <BrowserRouter>
        <App />
      </BrowserRouter>,
      document.getElementById('root')
    );
    
  • 通过 this.props.children 能够获取标签体内容
  • switch组件包裹路由只会匹配第一个匹配到 的路由进行渲染对应组件
  • react多级路由导致款式失落问题

    1. public文件下的 index.html 文件引入文件门路批改为 / 绝对路径的这种模式,或者用 %PUBLIC_URL% 这种模式进行引入。
    2. 或者将 BrowserRouter 组件换成 HashRouter 组件
  • `Router组件中的 exact` 属性用于精准匹配路由

     <Route exact path='/home' component={Home} />
  • Redirect组件用于没有匹配到门路的时候,调转到默认路由,个别放到注册组件最初
  • Switch组件用于匹配到第一个路由就不往后面进行匹配
  • NavLink用于路由高亮显示,能够自定义className
  • Link用于路由跳转

      <Switch>
          <Route  path='/about/about' component={About} />
          <Route exact path='/home' component={Home} />
          <Redirect to="/home"></Redirect>
       </Switch>
  • 嵌套路由

    1. 子组件注册组件须要带上父组件的path

    • 父组件
    import React, {Component} from 'react'
    import {Switch, Route ,Redirect} from 'react-router-dom'
    import About from './pages/About'
    import Home from './pages/Home'
    import MyNavLink from './components/MyNavLink'
    import './App.css'
    export default class App extends Component {render() {
        return (
          <div>
            <div className="row">
              <div className="col-xs-offset-2 col-xs-8">
                <div className="page-header"><h2>React Router Demo</h2></div>
              </div>
            </div>
            <div className="row">
              <div className="col-xs-2 col-xs-offset-2">
                <div className="list-group">
                  <MyNavLink to="/about" >About</MyNavLink>
                  <MyNavLink to="/home" >Home</MyNavLink>
                </div>
              </div>
              <div className="col-xs-6">
                <div className="panel">
                  <div className="panel-body">
                    <Switch>
                      <Route  path='/about' component={About} />
                      <Route  path='/home' component={Home} />
                      <Redirect to="/home"></Redirect>
                    </Switch>
                  </div>
                </div>
              </div>
            </div>
          </div>
        )
      }
    }
    
    • 子组件
    import React from "react";
    import Message from "./Message";
    import News from "./News";
    import MyNavLink from "../../components/MyNavLink";
    import {Switch, Route,Redirect} from 'react-router-dom'
    export default class Home extends React.Component {render() {console.log(this.props);
            return (
                <div>
                    <h2>Home 组件内容 </h2>
                    <div>
                        <ul className="nav nav-tabs">
                            <li>
                                <MyNavLink to="/home/news">News</MyNavLink>
                                
                            </li>
                            <li>
                                <MyNavLink to="/home/message">message</MyNavLink>
                            </li>
                        </ul>
                        <Switch>
                            <Route path="/home/news" component={News}></Route>
                            <Route path="/home/message" component={Message}></Route>
                            <Redirect to="/home/message"></Redirect>
                        </Switch>
                    </div>
                </div>
            )
        }
    }
  • 路由组件传参

    • params传参

      1. 跳转的中央须要进行参数按程序传递

      2. 注册的中央须要进行按程序进行接管

      3. 子组件通过 this.props.match.params 获取

      import React, {Component} from 'react'
      import {Route} from 'react-router';
      import {Link} from 'react-router-dom';
      import MsgDetail from './MsgDetail';
      export default class Message extends Component {
          state = {
              students: [{
                  id: 1,
                  name: '张三',
                  age: 12
              }, {
                  id: 2,
                  name: '李四',
                  age: 13
              }, {
                  id: 3,
                  name: '王二',
                  age: 14
              }]
          }
          render() {const { students} = this.state;
              return (
                  <div>
                      <ul>
                          {students.map((item) => {
                                  return (
                                      <li>
                                          <Link to={`/home/message/msgdetail/${item.name}/${item.age}`} key={item.id}>{item.name}</Link>
                                      </li>
                                  )
                              })
                          }
      
                      </ul>
                      <hr />
                      <Route path='/home/message/msgdetail/:name/:age' component={MsgDetail}/>
                      
                  </div>
              )
          }
      }
      

      4. 子组件进行获取

      import React, {Component} from 'react';
      
      class MsgDetail extends Component {render() {console.log(this.props);
              const {name, age} = this.props.match.params;
              return (
                  <div>
                      {name}----{age}
                  </div>
              );
          }
      }
      
      export default MsgDetail;
    • search传参(相似 vue 外面的query

      1. 在跳转的中央进行传递

      2. 在子组件的 this.props.location.search 进行取值

      3. 须要将 search 参数进行转换成对象的模式

      import React, {Component} from 'react'
      import {Route} from 'react-router';
      import {Link} from 'react-router-dom';
      import MsgDetail from './MsgDetail';
      export default class Message extends Component {
          state = {
              students: [{
                  id: 1,
                  name: '张三',
                  age: 12
              }, {
                  id: 2,
                  name: '李四',
                  age: 13
              }, {
                  id: 3,
                  name: '王二',
                  age: 14
              }]
          }
          render() {const { students} = this.state;
              return (
                  <div>
                      <ul>
                          {students.map((item) => {
                                  return (
                                      <li>
                                          <Link to={`/home/message/msgdetai?name=${item.name}&age=${age}`} key={item.id}>{item.name}</Link>
                                      </li> 
                                  )
                              })
                          }
      
                      </ul>
                      <hr />
                      <Route path='/home/message/msgdetail' component={MsgDetail} />
      
                  </div>
              )
          }
      }
      

      4. 子组件进行获取

      import React, {Component} from 'react';
      import qs from 'querystring'
      class MsgDetail extends Component {render() {console.log(this.props);
              const {search} = this.props.location.search
              const {name,age}=qs.parse(search.slice(1))
              return (
                  <div>
                      {name}----{age}
                  </div>
              );
          }
      }
      
      export default MsgDetail;
    • state传参

      1. 路由跳转的中央须要通过对象的形式进行传递,须要蕴含 path 以及 state 属性。state属性是一个对象

      2. 子组件通过 this.props.locaiton.state 进行获取

      3.state传递的参数在地址栏下面是看不到的,下面的两种都是在地址栏下面看的到的。

      import React, {Component} from 'react'
      import {Route} from 'react-router';
      import {Link} from 'react-router-dom';
      import MsgDetail from './MsgDetail';
      export default class Message extends Component {
          state = {
              students: [{
                  id: '00122',
                  name: '张三',
                  age: 12
              }, {
                  id: '00233',
                  name: '李四',
                  age: 13
              }, {
                  id: '003432423',
                  name: '王二',
                  age: 14
              }]
          }
          render() {const { students} = this.state;
              return (
                  <div>
                      <ul>
                          {students.map((item) => {
                                  return (<li key={item.id}>
                                          <Link  to={{path: '/home/message/msgdetail', state: { name: item.name, age: item.age} }}>{item.name}</Link>
                                      </li>
                                  )
                              })
                          }
      
                      </ul>
                      <hr />
                      <Route path='/home/message/msgdetail' component={MsgDetail} />
      
                  </div>
              )
          }
      }
      

      4. 子组件进行接管

      import React, {Component} from 'react';
      import qs from 'querystring'
      class MsgDetail extends Component {render() {console.log(this.props);
              
              const {name,age}=this.props.location.state
              return (
                  <div>
                      {name}----{age}
                  </div>
              );
          }
      }
      
      export default MsgDetail;
  • 编程式组件导航

    通过 this.props.historyapi进行跳转

     jump = (name,age) => {this.props.history.push('/home/message/msgdetail', { name, age} )
        }
  • withRouter 若想在个别组件中应用路由跳转的 api 能够引入 withRouter 办法

    import React, {Component} from 'react'
    import {withRouter} from 'react-router-dom'
    class Header extends Component {goBack = () => {this.props.history.goBack()
        }
        goFowrd = () => {this.props.history.goForward()
        }
        render() {
            return (
                <div className="page-header">
                    <h2>React Router Demo</h2>
                    <button onClick={this.goBack}> 回退 </button>
                    <button onClick={this.goFowrd}> 后退 </button>
                </div>
            )
        }
    }
    export default withRouter(Header)
    
  • antd按需引入,可参考地址 https://3x.ant.design/docs/react/use-with-create-react-app-cn 中的高级配置
  • redux

    1. 装置redux

    yarn add redux

    2. 创立 redux 文件夹,在该文件下创立 store 文件,action文件,reducer文件,constent文件

​ 3.store.js

import {createStore} from "redux";
import countRedux from './count_redux'
export default createStore(countRedux)

4.count_action.js

import {ADD,DESC} from './constent'
export const add = (data) => ({
    type: ADD,
    data
})
export const desc = (data) => ({
    type: DESC,
    data
})

5.count_redux.js

import {ADD,DESC} from './constent'
export default function (preState=0, action) {const { type,data}=action
    switch (type) {
        case ADD:
            return preState + data
        case DESC:
            return preState - data

        default:
           return preState
    }
 }

6.constent.js

export const ADD='add'
export const DESC='desc'

7.index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App.js";
import store from './redux/store'
ReactDOM.render(<App></App>, document.getElementById('root'))
store.subscribe(() => {ReactDOM.render(<App></App>, document.getElementById('root'))
})
  • 异步action

    1. 引入并装置redux-thunk

    2. 利用中间件传入thunk

    3.action返回的是一个函数,该函数会带有 dispatch 函数参数

    代码如下:

    store.js

    import {createStore, applyMiddleware} from "redux";
    import countRedux from './count_redux'
    import thunk from 'redux-thunk'
    export default createStore(countRedux, applyMiddleware(thunk))

    action.js

    export const  addAsync = (data, time) => {
        // 返回一个带有 dispatch 的参数的函数
        return (dispatch) => {setTimeout(() => {dispatch(add(data))// 调用同步 action
            },time)
        }
    }
  • react-redux

    1. 引入并装置

    yarn add react-redux

​ 2. 创立容器组件,用于操作状态以及包裹 ui 组件(链接 ui 组件以及redux)

      // 引入要展现的 UI 组件
import countUi from '../../components/Count'
// 用于连贯 UI 组件以及 redux
import {connect} from 'react-redux'
// 引入 action
import {add, desc, addAsync} from '../../redux/count_action'
// 将 store 外面的状态映射到 props,能够用过 UI 组件进行操作(ui 组件通过 this.props.xxx 获取)function mapStateToProps(state) { 
    return {count: state}
}
// 将 store 外面的操作状态的办法映射到 props,能够用过 UI 组件进行操作(ui 组件通过 this.props.xxx 获取)function mapDispatchToProps(dispatch) {
    return {add: (num) => {dispatch(add(num))
        },
        desc: (num) => {dispatch(desc(num))
        },
        addasync: (num, time) => {dispatch(addAsync(num,time))
        }
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(countUi)     
  1. 通过 props 传递给子组件store
  2. UI组件的优化写法

    // 引入要展现的 UI 组件
    import countUi from '../../components/Count'
    // 用于连贯 UI 组件以及 redux
    import {connect} from 'react-redux'
    // 引入 action
    import {add, desc, addAsync} from '../../redux/count_action'
    // 将 store 外面的状态映射到 props,能够用过 UI 组件进行操作(ui 组件通过 this.props.xxx 获取)/* function mapStateToProps(state) { 
    return {count: state}
    } */
    // 将 store 外面的操作状态的办法映射到 props,能够用过 UI 组件进行操作(ui 组件通过 this.props.xxx 获取)/* function mapDispatchToProps(dispatch) {
    return {add: (num) => {dispatch(add(num))
        },
        desc: (num) => {dispatch(desc(num))
        },
        addasync: (num, time) => {dispatch(addAsync(num,time))
        }
    }
    } */
    // export default connect(mapStateToProps, mapDispatchToProps)(countUi)
    
    // 优化写法
    export default connect(state => ({ count: state}),
    // 这里能够返回一个简略对象,外部能够主动散发 action
    {
        add: add,
        desc: desc,
        addasync: addAsync
    }
    )(countUi)

    5. 引入 react-redux 能够不必手动监听转态变动

    import React from "react";
    import ReactDOM from "react-dom";
    import App from "./App.js";
    // import store from './redux/store'
    ReactDOM.render(<App></App>, document.getElementById('root'))
    // 引入 react-redux 后能够不必手动监听状态变动
    // // 监测 redux 转态扭转,redux 状态扭转会从新渲染页面
    // store.subscribe(() => {//     ReactDOM.render(<App></App>, document.getElementById('root'))
    // })
    

    6. 利用 react-reduxprovider传递store

    import React from "react";
    import ReactDOM from "react-dom";
    import App from "./App.js";
    import store from './redux/store'
    import {Provider} from 'react-redux'
    ReactDOM.render(<Provider store={store}>
        <App />
    </Provider >
    , document.getElementById('root'))
    
    
  • 多个 reducer 利用 combineReducers 函数合并

    import {createStore, applyMiddleware ,combineReducers} from "redux";
    import countRedux from './reducers/count_redux'
    import person from "./reducers/person";
    import thunk from 'redux-thunk'
    
    export default createStore(
      // 多个 reducer 用 combineReducers 合并
      combineReducers({
        count: countRedux,
        person: person,
      }),
      applyMiddleware(thunk)
    );
  • reducer必须是一个纯函数,即传入的什么参数,就返回改参数,且传入的参数不能被改写。如果传入的是对象或者是数组。返回的值也应该是一个对象或数组,不能够在原有的对象或数组中进行操作再返回

    import {ADD_PERSON} from "../constent";
    export default function (prestate=[],action) {const { type, data} = action;
        switch (type) {
          case ADD_PERSON:
            return [data,...prestate]
          default:
           return []}
    
    }
  • redux配置的开发者工具

    1. 谷歌浏览器装置redux-devtools
    2. 在我的项目中装置redux-devtools-extension
    3. store.js 中进行如下配置

      import {createStore, applyMiddleware} from "redux";
      import thunk from 'redux-thunk'
      import {composeWithDevTools} from "redux-devtools-extension";
      import reducers from "./reducers";
      export default createStore(
        // 多个 reducer 用 combineReducers 合并
        reducers,
        composeWithDevTools(applyMiddleware(thunk))
      );
  • 打包后的文件如何在本地启动

    1. 全局装置 serve 插件

    npm install -g serve

    进入打包的文件目录运行 serve 命令

正文完
 0