利用react-router實現按需加載、登陸驗證、刷新組件。。。

因爲React Router 4.0已經正式發佈,因此該博文分React Router 和 React Router 4.0 進行分類討論!該博文會持續更新中,歡迎你們一塊兒討論與補充!

我相信用過react通常都用過react-router,那就頗有必要說說用react-router實現的一些經常使用功能了,好比組件按需加載、用戶登陸驗證、刷新當前路由。。。在這篇文章中,我將列出一些react-router使用小技巧,但願每一個讀者都能至少從中學到一個有用的技巧!react

1、按需加載

React Router:使用 getComponent + require.ensure 實現按需加載

getComponent 相比之前的 component 屬性,這個方法是異步的,也就是當路由匹配時,纔會調用這個方法。webpack

require.ensure(dependencies, callback, chunkName)

require.ensure 是 webpack 提供的方法,這也是按需加載的核心方法。第一個參數是依賴的模塊數組,第二個是回調函數,該函數調用時會傳一個require參數,第三個是模塊名,用於構建時生成文件時命名使用web

實現按需加載核心代碼以下:npm

import React, { Component } from 'react'; // react核心
import { Router, Route, Redirect, IndexRoute, browserHistory } from 'react-router'; 

/**
 * (路由根目錄組件,顯示當前符合條件的組件)
 * 
 * @class Roots
 * @extends {Component}
 */
class Roots extends Component {
    render() {
        return (
            <div>{this.props.children}</div>
        );
    }
}

const history = browserHistory;

// 首頁
const home = (location, cb) => {
    require.ensure([], require => {
        cb(null, require('./Home').default);
    }, 'home');
}

const RouteConfig = (
    <Router history={history}>
        <Route path="/" component={Roots}>
            <IndexRoute getComponent={home} />   
            <Route path="/home" getComponent={home} /> 
            <Route path="/login" component={login} />
            <Redirect from="*" to="/home" />
        </Route>
    </Router>
);

export default RouteConfig;

React Router 4.0:使用 babel-plugin-syntax-dynamic-import + react-loadable 實現按需加載

首先確保已安裝 babel-plugin-syntax-dynamic-import react-loadable,未安裝請先安裝:數組

npm i -D babel-plugin-syntax-dynamic-import

npm i -S react-loadable

實現按需加載核心代碼以下:babel

import React, { Component } from 'react';
import { BrowserRouter, HashRouter, Switch, Route, Redirect} from 'react-router-dom';
import createBrowserHistory from 'history/createBrowserHistory'
const history = createBrowserHistory();

// 按路由拆分代碼
import Loadable from 'react-loadable';

const loadingComponent = ({ isLoading, error }) => {
  // Handle the loading state
  if (isLoading) {
      return <div>Loading...</div>;
  }
  // Handle the error state
  else if (error) {
      return <div>Sorry, there was a problem loading the page.</div>;
  }
  else {
      return null;
  }
};

const Index = Loadable({
  loader: () => import('./Index'),
  loading: loadingComponent
});

const Home= Loadable({
  loader: () => import('./Home'),
  loading: loadingComponent
});

const Login= Loadable({
  loader: () => import('./Login'),
  loading: loadingComponent
});

/**
 * (路由根目錄組件,顯示當前符合條件的組件)
 * 
 * @class Roots
 * @extends {Component}
 */
class Roots extends Component {
    render() {
        return (
            <div>{this.props.children}</div>
        );
    }
}

let Router = process.env.NODE_ENV !== 'production' ? BrowserRouter : HashRouter;

const RouteConfig = (
    <Router history={history}>
        <Switch>
            <Route path="/" exact component={Index} />
            <Route path="/home" component={Home} />
            <Route path="/login" component={Login} />
            <Redirect from='' to="/" />
        </Switch>
    </Router>
);

export default RouteConfig;

2、實現登陸驗證

React Router:利用 Route 的 onEnter 鉤子在渲染對象組件前作攔截操做實現登陸驗證;

import React, { Component } from 'react'; // react核心
import { Router, Route, Redirect, IndexRoute, browserHistory } from 'react-router'; 

/**
 * (路由根目錄組件,顯示當前符合條件的組件)
 * 
 * @class Roots
 * @extends {Component}
 */
class Roots extends Component {
    render() {
        return (
            <div>{this.props.children}</div>
        );
    }
}

const history = browserHistory;

// 首頁
const home = (location, cb) => {
    require.ensure([], require => {
        cb(null, require('./Home').default);
    }, 'home');
}

// 登陸驗證
const requireAuth = (nextState, replace) => {
    if(true) { // 未登陸
        replace({
            pathname: '/login',
            state: { nextPathname: nextState.location.pathname }
        });
    } 
}

const RouteConfig = (
    <Router history={history}>
        <Route path="/" component={Roots}>
            <IndexRoute getComponent={home} onEnter={requireAuth} />   
            <Route path="/home" getComponent={home} onEnter={requireAuth} /> 
            <Route path="/login" component={login} />
            <Redirect from="*" to="/home" />
        </Route>
    </Router>
);

export default RouteConfig;

React Router4.0:在 Route 的 render 屬性上添加一個函數實現登陸驗證;

實現登陸驗證核心代碼以下:react-router

import React, { Component } from 'react';
import { BrowserRouter, HashRouter, Switch, Route, Redirect} from 'react-router-dom';
import createBrowserHistory from 'history/createBrowserHistory'
const history = createBrowserHistory();

// 按路由拆分代碼
import Loadable from 'react-loadable';

const loadingComponent = ({ isLoading, error }) => {
  // Handle the loading state
  if (isLoading) {
      return <div>Loading...</div>;
  }
  // Handle the error state
  else if (error) {
      return <div>Sorry, there was a problem loading the page.</div>;
  }
  else {
      return null;
  }
};

const Index = Loadable({
  loader: () => import('./Index'),
  loading: loadingComponent
});

const Home= Loadable({
  loader: () => import('./Home'),
  loading: loadingComponent
});

const Login= Loadable({
  loader: () => import('./Login'),
  loading: loadingComponent
});

/**
 * (路由根目錄組件,顯示當前符合條件的組件)
 * 
 * @class Roots
 * @extends {Component}
 */
class Roots extends Component {
    render() {
        return (
            <div>{this.props.children}</div>
        );
    }
}

// 登陸驗證
function requireAuth(Layout, props) {
  if (true) { // 未登陸
    return <Redirect to="/login" />;
  } else {
    return <Layout {...props} />
  }
}

let Router = process.env.NODE_ENV !== 'production' ? BrowserRouter : HashRouter;

const RouteConfig = (
    <Router history={history}>
        <Switch>
            <Route path="/" exact component={Index} />
            <Route path="/home" component={props => requireAuth(Home, props)} />
            <Route path="/login" component={Login} />
            <Redirect from='' to="/" />
        </Switch>
    </Router>
);

export default RouteConfig;

3、實現點擊左側菜單刷新當前組件

React Router:利用 Route 的 createElement 鉤子實現點擊左側菜單刷新當前組件;

實現點擊左側菜單刷新當前組件核心代碼以下:dom

import React, { Component } from 'react'; // react核心
import { Router, Route, Redirect, IndexRoute, browserHistory } from 'react-router'; 

/**
 * (路由根目錄組件,顯示當前符合條件的組件)
 * 
 * @class Roots
 * @extends {Component}
 */
class Roots extends Component {
    render() {
        return (
            <div>{this.props.children}</div>
        );
    }
}

const history = browserHistory;

// 首頁
const home = (location, cb) => {
    require.ensure([], require => {
        cb(null, require('./Home').default);
    }, 'home');
}

// 此處爲要點擊刷新的組件
const arr = [
    home
];

// 開關優化
let onOff =false;

// 頁面強制刷新,若是須要強制刷新在路由中添加onChange事件以及在組件數組添加
const createElement=(component, props) =>{
    if (props.children && onOff || props.children && arr.includes(props.routes.slice(-1)[0].getComponent)) {
        let children = Object.assign({}, props.children, {key : `${window.location.pathname}` + new Date().getTime()})
        props = { ...props, children };
        onOff = false;
    }
    return React.createElement(component, props)
 }

 const onChange = (props, next) => {
     onOff = true
     console.log(`${next.location.pathname}`, 'change');
 }

const RouteConfig = (
    <Router history={history} createElement = {createElement}>
        <Route path="/" component={Roots}>
            <IndexRoute getComponent={home} />   
            <Route path="/home" getComponent={home} /> 
            <Route path="/login" component={login} />
            <Redirect from="*" to="/home" />
        </Route>
    </Router>
);

export default RouteConfig;

React Router4.0:直接使用 history.replace 實現點擊左側菜單刷新當前組件便可;

歡迎你們一塊兒討論react-router使用小技巧,該博文會持續更新!異步

相關文章
相關標籤/搜索