如何停止/#/浏览器与react-router?
在使用react-router时,有什么办法可以防止/#/
在浏览器地址栏中显示? 这是与ReactJS。 即点击链接转到一个新的路线显示localhost:3000/#/
或localhost:3000/#/about
。 取决于路线。
对于react-router的版本1,2和3,将路由设置为URL映射scheme的正确方法是将历史实现传递给<Router>
的history
参数。 从历史文档 :
简而言之,历史知道如何侦听浏览器的地址栏进行更改,并将URLparsing为路由器可用来匹配路由并呈现正确组件的位置对象。
版本2和3
在react-router 2和3中,你的路由configuration代码如下所示:
import { browserHistory } from 'react-router' ReactDOM.render (( <Router history={browserHistory} > ... </Router> ), document.body);
版本1
在版本1.x中,您将改为使用以下内容:
import createBrowserHistory from 'history/lib/createBrowserHistory' ReactDOM.render (( <Router history={createBrowserHistory()} > ... </Router> ), document.body);
来源: 2.0版升级指南
版本4
对于即将到来的第4版react-router,语法已经发生了很大的变化,需要使用BrowserRouter
作为路由器的根标签。
import BrowserRouter from 'react-router/BrowserRouter' ReactDOM.render (( <BrowserRouter> ... <BrowserRouter> ), document.body);
源反应路由器版本4文档
Router.run(routes, Router.HistoryLocation, function (Handler) { React.render(<Handler/>, document.body); });
对于当前版本0.11和转发,您需要将Router.HistoryLocation
添加到Router.run()
。 现在不推荐使用<Routes>
。 请参阅 0.12.x HistoryLocation实施的升级指南 。
如果您不需要支持IE8,则可以使用浏览器历史logging,并且反应路由器将使用window.pushState
而不是设置哈希。
如何做到这一点取决于您正在使用的React路由器的版本:
- v4: https : //reacttraining.com/react-router/web/api/BrowserRouter
- v3: https : //github.com/ReactTraining/react-router/blob/v3/docs/guides/Histories.md
- v2: https : //github.com/ReactTraining/react-router/blob/v2.0.0/docs/guides/Histories.md
- v1: https : //github.com/ReactTraining/react-router/blob/1.0.x/docs/guides/basics/Histories.md
你可以使用.htaccess来实现这个function。 浏览器通常需要查询string分隔符?
或#
来确定查询string在哪里开始,目录path结束。 我们需要的最终结果是www.mysite.com/dir
因此,我们需要在Web服务器search它认为我们要求的目录/dir
。 所以我们把.htaccess
文件放在项目的根目录下。
# Setting up apache options AddDefaultCharset utf-8 Options +FollowSymlinks -MultiViews -Indexes RewriteEngine on # Setting up apache options (Godaddy specific) #DirectoryIndex index.php #RewriteBase / # Defining the rewrite rules RewriteCond %{SCRIPT_FILENAME} !-d RewriteCond %{SCRIPT_FILENAME} !-f RewriteRule ^.*$ ./index.html
然后用window.location.pathname获得查询参数
如果你愿意的话,你可以避免使用反应路线,如果你想要的话,只是操纵url和浏览器的历史。 希望这可以帮助别人…
安装历史包
npm install history --save
接下来从历史logging导入createHistory和useBasename
import { createHistory, useBasename } from 'history'; ... const history = useBasename(createHistory)({ basename: '/root' });
如果您的应用程序url是www.example.com/myApp,那么/ root应该是/ myApp。
将历史variables传递给路由器
render(( <Router history={history}> ... </Router> ), document.getElementById('example'));
现在所有的链接标签在所有的path前面添加一个“/”。
<Link to="/somewhere">somewhere</Link>
该解决scheme的灵感来自React-Router Example不幸的是,在他们的API中没有正确logging。
另一种处理散列之后显示内容的方法(所以如果你不使用pushState!)就是创build你的CustomLocation并在ReactRouter创build时加载它。
举个例子,如果你想要hashbang url(所以用#!)来符合谷歌规范的抓取,你可以创build一个HashbangLocation.js文件,主要是拷贝原始的HashLocation,比如:
'use strict'; var LocationActions = require('../../node_modules/react-router/lib/actions/LocationActions'); var History = require('../../node_modules/react-router/lib/History'); var _listeners = []; var _isListening = false; var _actionType; function notifyChange(type) { if (type === LocationActions.PUSH) History.length += 1; var change = { path: HashbangLocation.getCurrentPath(), type: type }; _listeners.forEach(function (listener) { listener.call(HashbangLocation, change); }); } function slashToHashbang(path) { return "!" + path.replace(/^\//, ''); } function ensureSlash() { var path = HashbangLocation.getCurrentPath(); if (path.charAt(0) === '/') { return true; }HashbangLocation.replace('/' + path); return false; } function onHashChange() { if (ensureSlash()) { // If we don't have an _actionType then all we know is the hash // changed. It was probably caused by the user clicking the Back // button, but may have also been the Forward button or manual // manipulation. So just guess 'pop'. var curActionType = _actionType; _actionType = null; notifyChange(curActionType || LocationActions.POP); } } /** * A Location that uses `window.location.hash`. */ var HashbangLocation = { addChangeListener: function addChangeListener(listener) { _listeners.push(listener); // Do this BEFORE listening for hashchange. ensureSlash(); if (!_isListening) { if (window.addEventListener) { window.addEventListener('hashchange', onHashChange, false); } else { window.attachEvent('onhashchange', onHashChange); } _isListening = true; } }, removeChangeListener: function removeChangeListener(listener) { _listeners = _listeners.filter(function (l) { return l !== listener; }); if (_listeners.length === 0) { if (window.removeEventListener) { window.removeEventListener('hashchange', onHashChange, false); } else { window.removeEvent('onhashchange', onHashChange); } _isListening = false; } }, push: function push(path) { _actionType = LocationActions.PUSH; window.location.hash = slashToHashbang(path); }, replace: function replace(path) { _actionType = LocationActions.REPLACE; window.location.replace(window.location.pathname + window.location.search + '#' + slashToHashbang(path)); }, pop: function pop() { _actionType = LocationActions.POP; History.back(); }, getCurrentPath: function getCurrentPath() { return decodeURI( // We can't use window.location.hash here because it's not // consistent across browsers - Firefox will pre-decode it! "/" + (window.location.href.split('#!')[1] || '')); }, toString: function toString() { return '<HashbangLocation>'; } }; module.exports = HashbangLocation;
请注意slashToHashbang函数。
那么你有必要这样做
ReactRouter.create({location: HashbangLocation})
就是这样:-)