詳解react-router4 異步加載路由兩種方法
方法一:我們要借助bundle-loader來(lái)實(shí)現(xiàn)按需加載。
首先,新建一個(gè)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模型用來(lái)異步加載組件
import Bundle from './bundle.js';
// 引入單個(gè)頁(yè)面(包括嵌套的子頁(yè)面)
// 同步引入
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',
},
方法二:用原生的
Webpack 配置
首先在 webpack.config.js 的 output 內(nèi)加上 chunkFilename
output: {
path: path.join(__dirname, '/../dist/assets'),
filename: 'app.js',
publicPath: defaultSettings.publicPath,
// 添加 chunkFilename
chunkFilename: '[name].[chunkhash:5].chunk.js',
},
name 是在代碼里為創(chuàng)建的 chunk 指定的名字,如果代碼中沒(méi)指定則 webpack 默認(rèn)分配 id 作為 name。
chunkhash 是文件的 hash 碼,這里只使用前五位。
在路由頁(yè)面
這里寫的是舊的沒(méi)按需要加載的路由寫法
ReactDOM.render(
(
<Router history={browserHistory}>
{/* 主頁(yè) */}
<Route path="/" component={App}>
{/* 默認(rèn) */}
<IndexRoute component={HomePage} />
{/* baidu */}
<Route path="/baidu" component={BaiduPage}>
<Route path="result" component={BaiduResultPage} />
<Route path="frequency" component={BaiduFrequencyPage} />
</Route>
{/* 404 */}
<Route path='/404' component={NotFoundPage} />
{/* 其他重定向到 404 */}
<Redirect from='*' to='/404' />
</Route>
</Router>
), document.getElementById('app')
);
我們需要讓路由動(dòng)態(tài)加載組件,需要將 component 換成 getComponent
ReactDOM.render(
(
<Router history={browserHistory}>
{/* 主頁(yè) */}
<Route path="/" component={App}>
{/* 默認(rèn) */}
<IndexRoute component={HomePage} />
{/* baidu */}
<Route path="/baidu"
getComponent(nextState, cb)
{ require.ensure([], (require) => { cb(null, require('components/layer/HomePage')) }, 'HomePage')}>
<Route path="result" getComponent... />
<Route path="frequency" getComponent... />
</Route>
{/* 404 */}
<Route path='/404' getComponent... />
{/* 其他重定向到 404 */}
<Redirect path='*' onEnter: (_, replaceState) => replaceState(null, "/404") />
</Route>
</Router>
), document.getElementById('app')
);
getComponent
對(duì)應(yīng)于以前的 component 屬性,但是這個(gè)方法是異步的,也就是當(dāng)路由匹配時(shí),才會(huì)調(diào)用這個(gè)方法。
這里面有個(gè) require.ensure 方法
require.ensure(dependencies, callback, chunkName)
這是 webpack 提供的方法,這也是按需加載的核心方法。第一個(gè)參數(shù)是依賴,第二個(gè)是回調(diào)函數(shù),第三個(gè)就是上面提到的 chunkName,用來(lái)指定這個(gè) chunk file 的 name。
如果需要返回多個(gè)子組件,則使用 getComponents 方法,將多個(gè)組件作為一個(gè)對(duì)象的屬性通過(guò) cb 返回出去即可。這個(gè)在官方示例也有,但是我們這里并不需要,而且根組件是不能返回多個(gè)子組件的,所以使用 getComponent。
當(dāng)改寫之后,我們需要把這個(gè)重定向的路由單獨(dú)拆出來(lái),也就是 * 這個(gè)路由,我們上面已經(jīng)為他創(chuàng)建了一個(gè) redirect 目錄。這里使用到 onEnter 方法,然后在這個(gè)方法里改變路由狀態(tài),調(diào)到另外的路由,實(shí)現(xiàn) redirect :
/redirect/index.js
module.exports = {
path: '*',
onEnter: (_, replaceState) => replaceState(null, "/404")
}
The root route must render a single element
跟著官方示例和上面碼出來(lái)之后,可能頁(yè)面并沒(méi)有渲染出來(lái),而是報(bào) The root route must render a single element 這個(gè)異常,這是因?yàn)?module.exports 和 ES6 里的 export default 有區(qū)別。
如果你是使用 es6 的寫法,也就是你的組件都是通過(guò) export default 導(dǎo)出的,那么在 getComponent 方法里面需要加入.default。
getComponent(nextState, cb) {
require.ensure([], (require) => {
// 在后面加 .default
cb(null, require('components/layer/ReportPage')).default
}, 'ReportPage')
}
如果你是使用 CommonJS 的寫法,也就是通過(guò) module.exports 導(dǎo)出的,那就無(wú)須加 .default 了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
React Grid Layout基礎(chǔ)使用示例教程
React Grid Layout是一個(gè)用于在React應(yīng)用程序中創(chuàng)建可拖拽和可調(diào)整大小的網(wǎng)格布局的庫(kù),通過(guò)使用React Grid Layout,我們可以輕松地創(chuàng)建自適應(yīng)的網(wǎng)格布局,并實(shí)現(xiàn)拖拽和調(diào)整大小的功能,本文介紹了React Grid Layout的基礎(chǔ)使用方法,感興趣的朋友一起看看吧2024-02-02
詳解react使用react-bootstrap當(dāng)輪子造車
本篇文章主要介紹了詳解react使用react-bootstrap當(dāng)輪子造車,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-08-08
react router 4.0以上的路由應(yīng)用詳解
本篇文章主要介紹了react router 4.0以上的路由應(yīng)用詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
react hook使用useState更新數(shù)組,無(wú)法更新問(wèn)題及解決
這篇文章主要介紹了react hook使用useState更新數(shù)組,無(wú)法更新問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
react PropTypes校驗(yàn)傳遞的值操作示例
這篇文章主要介紹了react PropTypes校驗(yàn)傳遞的值操作,結(jié)合實(shí)例形式分析了react PropTypes針對(duì)傳遞的值進(jìn)行校驗(yàn)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2020-04-04
React實(shí)現(xiàn)生成和導(dǎo)出Word文檔的方法詳解
React是一個(gè)流行的JavaScript庫(kù),用于構(gòu)建現(xiàn)代前端應(yīng)用程序,本文將深入探討如何在React中生成和導(dǎo)出Word文檔,感興趣的小伙伴可以學(xué)習(xí)一下2023-09-09
react使用CSS實(shí)現(xiàn)react動(dòng)畫功能示例
這篇文章主要介紹了react使用CSS實(shí)現(xiàn)react動(dòng)畫功能,結(jié)合實(shí)例形式分析了react使用CSS實(shí)現(xiàn)react動(dòng)畫功能具體步驟與實(shí)現(xiàn)方法,需要的朋友可以參考下2020-05-05
解讀useState第二個(gè)參數(shù)的"第二個(gè)參數(shù)"
這篇文章主要介紹了useState第二個(gè)參數(shù)的"第二個(gè)參數(shù)",具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03

