react-router4.x 实用例子,路由过渡动画、代码分割

react-router4.2.0实用例子

  1. 代码分割

    官网上面写的代码分割是不支持create-react-app脚手架的,要使用import实现
    创建一个bundle.js文件
        import { Component } from 'react'
        class Bundle extends Component {
            constructor(props) {
                super(props);
                this.state = {
                    mod: null
                };
            }
            componentWillMount() {
                this.load(this.props)
            }
            componentWillReceiveProps(nextProps) {
                if (nextProps.load !== this.props.load) {
                    this.load(nextProps)
                }
            }
            load(props) {
                this.setState({
                    mod: null
                });
                props.load().then((mod) => {
                    this.setState({
                        mod: mod.default ? mod.default : mod
                    });
                });
            }
            render() {
                return this.state.mod ? this.props.children(this.state.mod) : null;
            }
        }
        export default Bundle
    假设有一个自己的子组件需要代码分割
        demo.js
        import React from 'react'
        const MyComponent = () => (
            <div>我是子组件</div>
        )
        export default MyComponent;
    在需要代码分割的文件中导入这个Bundle
        import Bundle from './test.js'
        const MyComponent = (props) => (
            <Bundle load={() => import('./demo.js')}>
                {(MyComponent) => <MyComponent {...props} />}
            </Bundle>
        )
        只有当MyComponent在文件中使用到了,才会去异步加载需要的组件
    ** 补充
        如果你要和代码分割一起使用建议将Bundle.js文件修改成如下,如果不修改,亲测有bug
        import React, { Component } from 'react'
            class Bundle extends Component {
            constructor() {
                super()
                this.state = {
                    mod: null
                }
            }
            async componentDidMount() {
                const {default: mod} = await this.props.load()
                this.setState({
                    mod: mod.default || mod
                })
            }
            render() {
                return (
                this.state.mod ? this.props.children(this.state.mod) : null
                )
            }
        }
    
        export default Bundle
    
  2. ScrollTop实现方式一

    默认情况下,react中的组件在路由之间切换时不会默认回到页面的最顶部,这时需要自己动手编写一个组件实现这个功能
    创建ScrollTop.js文件
        import { Component } from 'react'
        import { withRouter } from 'react-router'
        class ScrollToTop extends Component {
            componentDidUpdate(prevProps) {
                if (this.props.location !== prevProps.location) {
                    window.scrollTo(0, 0)
                }
            }
            render() {
                return this.props.children
            }
        }
        export default withRouter(ScrollToTop)
    使用
        import ScrollTop from './ScrollTop.js'
        将router内部的子元素全部使用ScrollTop包裹即可
        <Router>
            <ScrollTop>
                <div>
                    <div position":"fixed","top": 0,"left": 0}}>
                        <Link to="/a">组件一</Link>
                        <Link to="/b">组件二</Link>
                    </div>
                    <Route path="/a" component={Demo} />
                    <Route path="/b" component={Demo1} />
                </div>
            </ScrollTop>
        </Router>
    
  3. ScrollTop实现方式二

    创建ScrollTop.js文件,添加如下内容
        import { Component } from 'react'
            import { withRouter } from 'react-router'
            class ScrollToTopOnMount extends Component {
            componentDidMount(prevProps) {
                window.scrollTo(0, 0)
            }
            render() {
                return null
            }
        }
        export default ScrollToTopOnMount
    使用
        import ScrollToTopOnMount from './scrollTop.js'
        将你原本的组件重新封装一个组件来使用即可
        class LongContent extends React.Component {
            render() {
                return (
                    <div>
                        <ScrollToTopOnMount/>
                        <Demo />
                    </div>
                )
            }
        }   
    
  4. 路由之间的动画切换

    结合react-transition-group插件使用,官方推荐,详细点击http://www.cnblogs.com/ye-hcj/p/7723104.html
    demo如下
        import React from 'react'
        import ReactDOM from 'react-dom'
        import {TransitionGroup,CSSTransition } from 'react-transition-group'
        import { withRouter } from 'react-router'
        import './index.css'
        import {
            BrowserRouter as Router,
            Route,
            Link,
            Switch
        } from 'react-router-dom'
        const MyComponent1 = () => (
            <div height": "200px","width": "200px","background": "red","position": "absolute","top": 0, "left": 0}}>我是组件一</div>
        )
        const MyComponent2 = () => (
            <div height": "200px","width": "200px","background": "yellow","position": "absolute","top": 0, "left": 0}}>我是组件二</div>
        )
        const MyComponent3 = () => (
            <div height": "200px","width": "200px","background": "green","position": "absolute","top": 0, "left": 0}}>我是组件三</div>
        )
        const AnimateComponent = withRouter(( {location} ) => (
            <div>
                <p><Link to="/a">组件一</Link></p>
                <p><Link to="/b">组件二</Link></p>
                <p><Link to="/c">组件三</Link></p>
                <hr />
                <TransitionGroup>
                    {/*这里使用location.key会在所有的路由之间使用相同的动画效果,如果你不想子路由也应用动画效果请使用location.pathname.split('/')[1]*/}
                    <CSSTransition key={location.key} timeout={500} classNames="fade" mountOnEnter={true} unmountOnExit={true}>
                        <div position": "relative","top": 0,"left": 0}}>
                            <Switch location={location}>
                                <Route path="/a" exact component={MyComponent1}/>
                                <Route path="/b" component={MyComponent2}/>
                                <Route path="/c" component={MyComponent3}/>
                            </Switch>
                        </div>
                    </CSSTransition>
                </TransitionGroup>
            </div>
        ))
        class MyComponent extends React.Component {
            render () {
                return (
                    <Router>
                        <AnimateComponent></AnimateComponent>
                    </Router>
                )
            }
        }
        ReactDOM.render(
            <MyComponent/>,
            document.getElementById('root')
        ) 
    注:
        你可能使用的动画
        .fade-enter {
            opacity: 0;
            z-index: 1;
        }
        .fade-enter.fade-enter-active {
            opacity: 1;
            transition: opacity 250ms ease-in;
        }