9.21 React 全家桶

260 阅读7分钟

1. 安装

1. 检查版本号

  • 安装node
    node -v npm -v
  • Node >= 8.10
  • npm>= 5.6

2. create-react-app

  • 安装react脚手架
    npm install -g create-react-app

3. 创建项目

    create-react-app react-app
    

4. 启动项目

    cd react-app
    //进入项目文件夹
    npm start

2. 安装ReactRouter

    npm install --save react-router-dom
    //引入所需对象
    import React from ‘react’;
    import {BrowserRouteras Router, Route, Link} from ‘react-router-dom’

3. 路由基本组件

    class App extends Component {
      render() {
        return (
          <div>
            <Router>
              <Link to="/">go to page Home</Link><br/>
              <Link to="/a">go to page A</Link><br/>
              
              <Route exact path="/" component={Home}></Route>
              <Route path="/a" component={A}></Route>
            </Router>
          </div>
        );
      }
    }

1. 两种跳转方式

  1. <BrowserRouter>使用HTML5提供的history API来保持UI和URL的同步
    import {BrowserRouter as Router,Route ,Link} from 'react-router-dom'
  1. <HashRouter>使用URL的hash (例如:window.location.hash)来保持UI和URL的同步
    import {HashRouter as Router,Route ,Link} from 'react-router-dom'

2. link

  • <Link>react路由中的点击切换到哪一个组件的链接

3. route

  • Route代表了你的路由界面path代表路径component代表路径所对应的界面。
  • exact严格匹配模式,一般情况模糊匹配‘/a’包含‘/’,该情况下不模糊匹配
    <Route exact path="/" component={Home}></Route>

4. switch

  • 按照顺序匹配第一个符合条件的子元素
    <Switch>
        <Route path="/a" component={A}></Route>
        <Route path="/b" component={B}></Route>
        <Route path="/f" children={F} ></Route>
        <Route path="/" component={Home}></Route>
    </Switch>

5. router其他渲染方式

  1. render属性 渲染一个function形式定义的组件
    class App extends Component {
      render() {
        return (
          <div>
            <Router>
              <Link to="/d">go to page D</Link><br/>
              <Link to="/e">go to page E</Link><br/>
              
              {/* render属性 渲染一个function形式定义的组件 */}
              <Route path="/d" render={
                () => {
                  return (
                    <div>
                      page D
                    </div>
                  )
                }
              } ></Route>
    
              <Route path="/e" render={()=> <div>page E</div> } ></Route>
            </Router>
          </div>
        );
      }
    }
  1. children function形式定义的组件
  • 这种情况不能使用switch的方式,且子组件需要是function的方式定义的
    class App extends Component {
          render() {
            return (
              <div>
                <Router>
                  <Link to="/f">go to page F</Link><br/>
                  
                  {/* children function形式定义的组件 */}
                  <Route path="/f" children={F} ></Route>
                </Router>
              </div>
            );
          }
        }

4. 传参

  • 传递的参数在this.props.math.params
  • props获取父组件传给自组件的内容
  • match可接收路由的默认对象
  • 主页
    class App extends Component {
      render() {
        return (
          <div>
            <Router>
              <Link to="/b/5/aaaa">go to page B</Link><br/>
              <Link to="/c/5/aaaa">go to page C</Link><br/>
    
              <Route path="/b/:id/:name" component={B} name="123"></Route>
              <Route path="/c/:id/:name" component={C} ></Route>
            </Router>
          </div>
        );
      }
    }
  • 组件
    class B extends Component {
      render() {
        let {match} = this.props
        return (
          <div>
            page B
            <p>{this.props.match.params.id}</p>
            <p>{this.props.match.params.name}</p>
          </div>
        );
      }
    }

5. 重定向Redirect

  • 引入Redirect
    import {BrowserRouter as Router,Route ,Link ,Redirect} from 'react-router-dom'
    import React , { Component } from 'react';
  • 重定向
    class App extends Component {
      render() {
        return (
          <div>
            <Router>
              <Route path='/b' render={() => {
                return <Redirect to='/'></Redirect>
              }}>
              </Route>
            </Router>
          </div>
        );
      }
    }

6. 自定义链接

    import React from "react";
    import { BrowserRouter as Router, Route, Link } from "react-router-dom";
    
    function CustomLinkExample() {
      return (
        <Router>
          <div>
            <OldSchoolMenuLink activeOnlyWhenExact={true} to="/" label="Home" />
            <OldSchoolMenuLink to="/about" label="About" />
            <hr />
            <Route exact path="/" component={Home} />
            <Route path="/about" component={About} />
          </div>
        </Router>
      );
    }
    
    function OldSchoolMenuLink({ label, to, activeOnlyWhenExact }) {
      return (
        <Route
          path={to}
          exact={activeOnlyWhenExact}
          children={({ match }) => (
            <div className={match ? "active" : ""}>
              {match ? "> " : ""}
              <Link to={to}>{label}</Link>
            </div>
          )}
        />
      );
    }
    
    function Home() {
      return (
        <div>
          <h2>Home</h2>
        </div>
      );
    }
    
    function About() {
      return (
        <div>
          <h2>About</h2>
        </div>
      );
    }
    
    export default CustomLinkExample;

7. 编程式导航

1. history

  • props下的history属性可以用来控制页面的跳转
  • push(’/’)方法跳转到对应页面
  • go()后退或前进n
  • goBack()后退一页
  • goForward()前进一页
    import React from 'react';
    
    const C = ({match, history}) => {
      console.log(history)
      return (
        <div>
          page C
          <p>{match.params.id}</p>
          <p>{match.params.name}</p>
          <button onClick = {() => {
            // 进入到指定路径
            history.push('/a') 
    
          }}>push</button>
          <button onClick = {() => {
            // 后退一步
            history.goBack()
          }}>goBack</button>
          <button onClick = {() => {
            // 前进或后退n步
            history.go(-2)
          }}>go</button>
        </div>
      )
    }

2. withRouter

  • withRouter可以包装任何自定义组件,将react-routerhistory,location,match三个对象传入。

8. 阻止跳转Prompt

  • 引入
    import {BrowserRouter as Router,Route ,Link ,Prompt} from 'react-router-dom'
  • when为布尔值是否开启验证
  • message:string当用户离开当前页面时,设置的提示信息。
    <Prompt message=“确定要离开?”/>
  • message:func当用户离开当前页面时,设置的回掉函数
    import React, { Component } from 'react';
    import { Prompt } from "react-router-dom";
    
    class A extends Component {
      constructor(params) {
        super(params)
        this.state = {
          isEmpty: true
        }
        this.change = this.change.bind(this)
      }
      change(event) {
        if (event.target.value.length > 0) {
          console.log(123)
          this.setState({
            isEmpty: false
          })
        } else {
          this.setState({
            isEmpty: true
          })
        }
      }
      render() {
        return (
          <div>
            page A
            <button onClick={() => {
              let {history} = this.props
              history.go(2)
            }}>go</button>
            <input type="text" onChange={this.change}/>
            <Prompt when={this.state.isEmpty} message={(loation) => {
              console.log(loation)
              return "are you sure ?"
            }}></Prompt>
          </div>
        );
      }
    }

9. NavLink

  • <NavLink><Link>的一个特定版本,会在匹配上当前的url的时候给已经渲染的元素添加参数
  • activeClassName(string)设置选中样式,默认值为active
  • activeStyle(object)当元素被选中时,为此元素添加样式
  • isActive(func)判断链接是否激活的额外逻辑的功能
    class App extends Component {
      render() {
        return (
          <div>
            <Router>
              <Main/>
              <NavLink to="/" activeStyle={
                {
                  opacity: 0.1
                }
              }>go to page Home</NavLink><br/>
              <NavLink to="/a" activeClassName="activea" >go to page A</NavLink><br/>
              <NavLink to="/b/5/aaaa">go to page B</NavLink><br/>
              <NavLink to="/c/5/aaaa">go to page C</NavLink><br/>
              
              <Route exact path="/" component={Home}></Route>
              <Route path="/a" component={A}></Route>
              <Route path="/b/:id/:name" component={B} name="123"></Route>
              <Route path="/c/:id/:name" component={C} ></Route>
            </Router>
          </div>
        );
      }
    }

10. 模糊匹配

  • 如果想进行模糊匹配例如about和company匹配到相应的路由而Kim和Chris匹配到user则必须将带有参数的route放置到最后
    class App extends Component {
      render() {
        return ( 
        <div >
          <Router >
              <Link to = "/b/a" > goa </Link><br/>
              <Link to = "/b/b" > gob </Link><br/>
              <Link to = "/b/11" > go11 </Link><br/>
              
              <Switch >
                  <Route exact path = "/b/a"
                  component = {B} > </Route> 
                  <Route exact path = "/b/b"component = {B}> </Route>
                  <Route exact path = "/b/:id" component = {B}> </Route> 
              </Switch> 
          </Router> 
        </div>
        );
      }
    }
    export default App;

11. Redux

  • Redux是JavaScript状态容器,提供可预测化的状态管理

1. 安装

    npm install redux react-redux

2. 原理

-应用中所有的state都以一个对象树的形式储存在一个单一的store中

  • 惟一改变state的办法是触发action,一个描述发生什么的对象
  • 为了描述action如何改变state树,你需要编写reducers

3. Store

  • createStore 第一个参数是一个reducer(fun) 第二个参数是一个obj 存储的是状态管理的一些变量
    <Providerstore={store}></Provider>
    import {createStore} from 'redux'
    import reducer from './reducer'
    
    let initState = {
      num: 0,
      userInfo: {},
      isLogin: false
    }
    
    // createStore 第一个参数是一个reducer(fun) 第二个参数是一个obj 存储的是状态管理的一些变量
    let store = createStore(reducer, initState)
    
    export default store

4. Action

  • action内必须使用一个字符串类型的type字段来表示将要执行的动作
    const add = (text) => {
      return {
        type: 'ADD',
        text
      }
    }
    const del = (text) => {
      return {
        type: 'DEL',
        text
      }
    }
    
    export {
      add,
      del
    }

5. Reducer

  • store收到Action以后,必须给出一个新的State,这样View才会发生变化。这种State的计算过程就叫做Reducer。
  • reducer就是一个纯函数,接收旧的state和action,返回新的state。
  • combineReducers()所做的只是生成一个函数,这个函数来调用你的一系列reducer,每个reducer根据它们的key来筛选出state中的一部分数据并处理,然后这个生成的函数再将所有reducer的结果合并成一个大的对象
    import { combineReducers } from "redux"
    // state 需要有默认的初始值
    const num = (state=0, action) => {
      console.log(action.text)
      switch(action.type) {
        case 'ADD':
          return state+1;
        case 'DEL':
          return state-1;
        default:
          return state
      }
      
    }
    const reducer = combineReducers ({
      num
    })
    export default reducer

6. 获取state

  • Connect(react-redux提供的)
  • store里能直接通过store.dispatch()调用dispatch()方法调用action,但是多数情况下你会使用提供的connect()帮助器来调用
  • mapStateToProps将state转化成props属性
    const mapStateToProps = (state) => {
      return {
        num: state.num
      }
    } 
    
    export default connect(mapStateToProps)(App);