React路由配置 refs高阶组件
begin enjoy👇

五 React

路由

下载路由文件

  • 只下载 react-router-dom,其它不用下载
  • npm 安装 npm install --save react-router-dom
  • cdn
<script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>

ReactRouterDOM

  • Route : (抽象类) 路由对象,匹配浏览器地址栏url,所有路由记录都必须嵌套在该组件内。
  • BrowserRouter: (Route的实现类)按H5 history 模式匹配url
  • HashRouter:(Route的实现类)按 hash 模式匹配url
  • StaticRouter:(Route的实现类)
  • MemoryRouter:(Route的实现类)
  • Redirect: 重定向,必须配合 <Switch> 一起使用

react不像vue路由规则匹配成功后就不往后面匹配了,react会将所有规则全部匹配。
react 路由规则配合上<Switch>组件使用就会匹配上第一个后就不再向后匹配,如果没有匹配上就继续匹配。

  • Link 声明性,可访问的导航。
  • NavLink:与Link不同点在于会动态的添加一个active类名

NavLink 组件中也要加上 exact 否则匹配时可能会出现都出现 active类名的现象。

  • 也可以指定自已的类名
<NavLink to='/goods/food' activeClassName='my-active' exact>食物</NavLink>

路由基本使用

// 获取路由对象
const HashRouter = ReactRouterDOM.HashRouter
const Route = ReactRouterDOM.Route //设定规则
const Redirect = ReactRouterDOM.Redirect //重定向
const Switch = ReactRouterDOM.Switch 
const Link = ReactRouterDOM.Link
const NavLink = ReactRouterDOM.NavLink

//路由规则匹配匹配成功后要渲染的组件
class Home extends React.Component{
    render() {
        return(<div>
            <h2>Home</h2>
        </div>)
    }
}
class About extends React.Component{
    render() {
        return(<div>
            <h2>About</h2>
        </div>)
    }
}

class App extends React.Component{
    render(){
        return <div>
        <HashRouter>
            <ul className='navbar'>
                <li><Link to='/home'>home</Link></li>
                <li><Link to='/about'>about</Link></li>
                <li><NavLink to='/goods'>goods</NavLink></li>
            </ul>
            {/* 定义路由规则 */}
            <Switch>
                <Route path='/home' component={Home}></Route>
                <Route path='/about' component={About}></Route>
                <Route path='/goods' render={(props)=>{return(
                    <div>
                        <h2>goods</h2>
                    </div>
                )}}></Route>
                <Redirect push to='/home'  />
            </Switch>
        </HashRouter>
        </div>
    }
}

ReactDOM.render(<App />, document.getElementById('app'))

路由重定向

<Redirect push to='/'  />
  • push 为true时,重定向会将新条目推送到历史记录而不是替换当前条目。

路由规则匹配模式

  • exact 精确模式
<Route exact path="/one" component={About} />
path location.pathname exact 匹配
/one /one/two true no
/one /one/two false yes
  • strict 严格模式
<Route strict path="/one/" component={About} />
path location.pathname 匹配
/one/ /one no
/one/ /one/ yes
/one/ /one/two yes
<Route exact strict path="/one" component={About} />
path location.pathname 匹配
/one /one yes
/one /one/ no
/one /one/two no

strict会强制检查路径尾部是否有斜杠。

嵌套路由

  • 嵌套路由,首先会匹配到主路由规则然后再匹配子路由。
  • 主路由匹配规则中不能添加 exact,如果添加的话子路由将匹配不到。
class Home extends React.Component{
    render() {
        return(<div>
            <h2>Home</h2>
        </div>)
    }
}

class Goods extends React.Component{
    render() {
        return(<div>
            <h2>Goods</h2>
            {/* 配置子路由 */}
            <ul className='navbar'>
                <li><NavLink to='/goods/cloth' exact>衣服</NavLink></li>
                <li><NavLink to='/goods/food' activeClassName='my-active' exact>食物</NavLink></li>
            </ul>
            <Switch>
                <Route path='/goods/cloth'  render={()=>{return (<div>
                    <h2>衣服</h2>
                    </div>)}}></Route>
                <Route path='/goods/food'  render={()=>{return (<div>
                    <h2>食物</h2>
                    </div>)}}></Route>
                <Redirect push to='/goods/cloth'  />
            </Switch>
        </div>)
    }
}

class App extends React.Component{
    render() {
        return(<div>
            <h2>嵌套路由</h2>
            <HashRouter>
                <ul className='navbar'>
                    <li><NavLink to='/' exact>home</NavLink></li>
                    <li><NavLink to='/goods'>goods</NavLink></li>
                    
                </ul>
                <Switch>
                    <Route path='/' exact component={Home}></Route>
                    {/* 不能添加 exact 否则主路由匹配不到子路由永远进入不了 */}
                    <Route path='/goods'  component={Goods}></Route>
                    <Redirect push to='/'  />
                </Switch>
            </HashRouter>
        </div>)
    }
}

动态路由

<Route path="/users/:id" component={User} />
  • props.match.params 接收动态路由传递的参数
class Home extends React.Component{
    render() {
        return(<div>
            <h2>Home</h2>
        </div>)
    }
}
class Goods extends React.Component{
    constructor(props) {
        super(props);
        this.state={ param:'' }
    }
    componentDidMount(){
        // 获取到路由中传递的数据
        let param =  this.props.match.params['goods']
        console.log(param)
        this.setState({param:param})
        
    }
    // 数据有更新时渲染数据到页面
    componentWillReceiveProps(nextProps){
        let param =  nextProps.match.params['goods']
        console.log(">> " + param)
        this.setState({param:param})
    }

    render() {
        return(<div>
            <h2>Goods</h2>
            <p>{this.state.param}</p>
        </div>)
    }
}

class App extends React.Component{
    render() {
        return(<div>
            <h2>嵌套路由</h2>
            
            <HashRouter >
                <ul className='navbar'>
                    <li><NavLink to='/' exact>home</NavLink></li>
                    <li><NavLink to='/food'>food</NavLink></li>
                    <li><NavLink to='/fruits'>fruits</NavLink></li>
                </ul>
                <Switch>
                    <Route path='/' exact component={Home}></Route>
                    {/* 配置动太路由 */}
                    <Route path='/:goods'  component={Goods}></Route>
                    <Redirect push to='/'  />
                </Switch>
            </HashRouter>
        </div>)
    }
}

路由编程式导航

  • 不是路由组件,但想使用路由组件中的对象方法,那么可以使用 withRouter 高阶组件进行封装。
class Home extends React.Component{
    render() {
        return(<div>
            <h2>Home</h2>
        </div>)
    }
}
class Goods extends React.Component{
    render() {
        return(<div>
            <h2>Goods</h2>
        </div>)
    }
}
// 普通组件需要经过高阶组件withRouter包装才能使用路由中方法
class MyNav extends React.Component{
    render() {
        return(<div>
            <div>
                <button onClick={this.goHome.bind(this)}>home</button>
                <button onClick={this.goGoods.bind(this)}>food</button>
            </div>
        </div>)
    }
    goHome(){
        // 必须将该组件通过高阶组件 withRouter 转换后才可以使用push方法
        this.props.history.push('/home')
    }
    goGoods(){
        this.props.history.push('/goods')
    }
}
// 高阶组件
const withRouter = ReactRouterDOM.withRouter
// 使用普通组件拥有路由组件的方法
const NewNav = withRouter(MyNav)
class App extends React.Component{
    render() {
        return(<div>
            <h2>编辑式导航</h2>
            <HashRouter>
                <NewNav />
                <Switch>
                    <Route path='/' exact component={Home}></Route>
                    <Route path='/goods'  component={Goods}></Route>
                    <Redirect push to='/'  />
                </Switch>
            </HashRouter>
        </div>)
    }
}

posted @ Zycin (非转载 来自个人学习资料整理)