React进阶学习——React动态路由

382 阅读3分钟

这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情

动态路由

高傲自大是成功的流沙。——阿比 ,
我是小晨,今天学习React动态路由

对于大型应用来说,一个首当其冲的问题就是所需加载的 JavaScript 的大小。程序应当只加载当前渲染页所需的 JavaScript。有些开发者将这种方式称之为“代码分拆” —— 将所有的代码分拆成多个小包,在用户浏览过程中按需加载。

对于底层细节的修改不应该需要它上面每一层级都进行修改。举个例子,为一个照片浏览页添加一个路径不应该影响到首页加载的 JavaScript 的大小。也不能因为多个团队共用一个大型的路由配置文件而造成合并时的冲突。

路由是个非常适于做代码分拆的地方:它的责任就是配置好每个 view。

React Router 里的路径匹配以及组件加载都是异步完成的,不仅允许你延迟加载组件,并且可以延迟加载路由配置。在首次加载包中你只需要有一个路径定义,路由会自动解析剩下的路径。

Route 可以定义 getChildRoutes 和 getComponents这几个函数。它们都是异步执行,并且只有在需要时才被调用。我们将这种方式称之为 “逐渐匹配”。 React Router 会逐渐的匹配 URL 并只加载该 URL 对应页面所需的路径配置和组件。

如果配合 **webpack **这类的代码分拆工具使用的话,一个原本繁琐的构架就会变得更简洁明了。

const CourseRoute = {
    path: 'course/:courseId',
    getChildRoutes (location, callback) {
        require.ensure([],
            function (require) {
                callback(null, [require('./routes/Announcements'), require('./routes/Assignments'), require('./routes/Grades'),])
            })
    }, getIndexRoute (location, callback) {
        require.ensure([], function (require) {
            callback(null, {
                component: require('./components/Index')
            })
        })
    }, getComponents (location, callback) {
        require.ensure([], function (require) {
            callback(null, require('./components/Course'))
        })
    }
}

跳转前确认

React Router 提供一个 routerWillLeave 生命周期钩子这使得 React 组件 可以拦截正在发生的跳转,或在离开 route 前提示用户。routerWillLeave 返回值有以下两种:

  1. return false 取消此次跳转
  2. return 返回提示信息,在离开 route 前提示用户进行确认。

你可以在  route 组件 中引入 Lifecycle mixin 来安装这个钩子。

import { Lifecycle } from 'react-router'
const Home = React.createClass({
    // 假设 Home 是一个 route 组件,它可能会使用  
    // Lifecycle mixin 去获得一个 routerWillLeave 方法。
    mixins: [Lifecycle],
    routerWillLeave (nextLocation) {
        if (!this.state.isSaved) return 'Your work is not saved! Are you sure you want to leave?'
    },
})

如果你在组件中使用了 ES6 类,你可以借助 react-mixin 包将 Lifecycle mixin 添加到组件中,不过我们推荐使用 React.createClass 来创建组件,初始化路由的生命周期钩子函数。

如果你想在一个深层嵌套的组件中使用  routerWillLeave 钩子,只需在  **route 组件 ** 中引入 RouteContext mixin,这样就会把 route 放到 context 中。

import { Lifecycle, RouteContext } from 'react-router'
const Home = React.createClass({
    // route 会被放到 Home 和它子组件及孙子组件的 context 中, 
    // 这样在层级树中 Home 及其所有子组件都可以拿到 route。 
    mixins: [RouteContext], render () {
        return <NestedForm />
    }
})
const NestedForm = React.createClass({
    // 后代组件使用 Lifecycle mixin 获得 
    // 一个 routerWillLeave 的方法。 
    mixins: [Lifecycle],
    routerWillLeave (nextLocation) {
        if (!this.state.isSaved) return 'Your work is not saved! Are you sure you want to leave?'
    },
})