react-router4筆記

前兩天在寫react項目的時候發如今路由上面走了不少的彎路。正所謂磨刀不誤砍柴工,仍是先系統地學習一下吧...html

重要API一覽

路由容器組件

  • BrowserRouter: 瀏覽器自帶的API,restful風格(須要後臺作相應的調整);react

  • HashRouter: 使用hash方式進行路由;webpack

  • MemoryRouter: 在內存中管理history,地址欄不會變化。在reactNative中使用。web

Route標籤

  • 該標籤有三種渲染方式component、render、children(絕大多數狀況使用component組件就行了);segmentfault

  • 三種渲染方式都會獲得三個屬性match、history、location;瀏覽器

  • 渲染組件時,route props跟着一塊兒渲染;babel

  • children方式渲染會無論地址欄是否匹配都渲染一些內容,在這裏加動畫一時很常見的作法。restful

Link標籤

  • to: 後面能夠接字符串,也能夠跟對象(對象能夠是動態地添加搜索的信息);react-router

  • replace: 當設置爲true時,點擊連接後將使用新地址替換掉訪問歷史記錄裏面的原地址。app

NavLink標籤

  • <NavLink>是<Link>的一個特定版本, 會在匹配上當前URL的時候會給已經渲染的元素添加樣式參數;

  • activeClassName,當地址匹配時添加相應class;

  • activeStyle,當地址匹配時添加相應style;

  • exact,當地址徹底匹配時,才生效;

  • isActive,添加額外邏輯判斷是否生效。

Prompt標籤

  • when: when的屬性值爲true時啓用防止轉換;

  • message: 後面能夠跟簡單的提示語,也能夠跟函數,函數是有默認參數的。

Redirect標籤

  • <Redirect/>能夠寫在<Route/>的render屬性裏面,也能夠跟<Route/>平級;

  • to: 依舊是能夠跟字符串或對象;

  • push: 添加該屬性時,地址不會被覆蓋,而是添加一條新紀錄;

  • from: 重定向,與<Route/>平級時。

match

  • params: 經過解析URL中動態的部分得到的鍵值對;

  • isExact: 當爲true時,整個URL都須要匹配;

  • path: 在須要嵌套<Route/>的時候用到;

  • url: 在須要嵌套<Link/>的時候會用到;

  • 獲取方式: 以this.props.match方式。

import {
    BrowserRouter as Router, // 或者是HashRouter、MemoryRouter
    Route,   // 這是基本的路由塊
    Link,    // 這是a標籤
    Switch   // 這是監聽空路由的
    Redirect // 這是重定向
    Prompt   // 防止轉換  
  } from 'react-router-dom'

權限控制

利用組件內的Redirect標籤。

const PrivateRoute = ({ component: Component, ...rest }) => (
    <Route {...rest} render={props => (
      fakeAuth.isAuthenticated ? (
        <Component {...props}/>
      ) : (
        <Redirect to={{
          pathname: '/login',
          state: { from: props.location }
        }}/>
      )
    )}/>
  )

阻止離開當前路由

在組件內部添加Prompt標籤來進行權限控制。

<Prompt
    when={isBlocking}
    message={location => (
      `你真的要跳轉到 ${location.pathname}麼?`
    )}
  />

過渡動畫

樣式分別定義:.example-enter、.example-enter.example-enter-active、.example-leave、.example-leave.example-leave-active。
實例

<ReactCSSTransitionGroup
  transitionName="fade"
  transitionEnterTimeout={300}
  transitionLeaveTimeout={300}
>
  <!-- 這裏和使用 ReactCSSTransitionGroup 沒有區別,惟一須要注意的是要把你的地址(location)傳入「Route」裏使它能夠在動畫切換的時候匹配以前的地址。 -->
  <Route
    location={location}
    key={location.key}
    path="/:h/:s/:l"
    component={HSL}
  />
</ReactCSSTransitionGroup>

按需加載

官方方法

藉助bundle-loader 實現按需加載。
新建一個bundle.js文件:

import React, { Component } from 'react'
  export default class Bundle extends React.Component {
    state = {
      // short for "module" but that's a keyword in js, so "mod"
      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((mod) => {
        this.setState({
          // handle both es imports and cjs
          mod: mod.default ? mod.default : mod
        })
      })
    }
    render() {
      if (!this.state.mod)
        return false
      return this.props.children(this.state.mod)
    }
  }

在入口處使用按需加載:

// bundle模型用來異步加載組件
  import Bundle from './bundle.js';
  // 引入單個頁面(包括嵌套的子頁面)
  // 同步引入
  import Index from './app/index.js';
  // 異步引入
  import ListContainer from 'bundle-loader?lazy&name=app-[name]!./app/list.js';
  const List = () => (
    <Bundle load={ListContainer}>
      {(List) => <List />}
    </Bundle>
  )
  <HashRouter>
    <Router basename="/">
      <div>
        <Route exact path="/" component={Index} />
        <Route path="/list" component={List} />
      </div>
    </Router>
  </HashRouter>

webpack.config.js文件配置:

output: {
    path: path.resolve(__dirname, './output'),
    filename: '[name].[chunkhash:8].bundle.js',
    chunkFilename: '[name]-[id].[chunkhash:8].bundle.js',
  },

我的以爲更好用的寫法

import Loadable from 'react-loadable'
  import Loading from './my-loading-component'
  Loadable({
    loader: () => import(`views/AsyncView`),
    // 若是沒有loading動畫,就返回null
    LoadingComponent: () => null,
    // 若是有loading動畫,則以下
    loading: Loading
  })

webpack配置:

// 添加插件babel-plugin-import-inspector
  {
    "plugins": [
      ["import-inspector", {
        "serverSideRequirePath": true,
        "webpackRequireWeakId": true,
      }]
    ]
  }
相關文章
相關標籤/搜索