如何使用react-router在浏览器中停止/#/?

时间:2014-08-01 18:53:42

标签: reactjs react-router

使用react-router时,有什么方法可以阻止/#/在浏览器的地址栏中显示?这与ReactJS有关。即点击链接转到新路线显示localhost:3000/#/localhost:3000/#/about。视路线而定。

6 个答案:

答案 0 :(得分:74)

对于react-router的版本1,2和3,将路由设置为URL映射方案的正确方法是将历史记录实现传递到history <Router>参数。来自histories documentation

  

简而言之,历史记录知道如何监听浏览器的地址栏以进行更改,并将URL解析为路由器可用于匹配路由并呈现正确组件集的位置对象。

版本2和3

在react-router 2和3中,您的路由配置代码如下所示:

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);

来源:Version 2.0 Upgrade Guide

第4版

对于即将发布的react-router版本4,语法已经发生了很大变化,并且需要使用BrowserRouter作为路由器根标记。

import BrowserRouter from 'react-router/BrowserRouter'
ReactDOM.render (( 
  <BrowserRouter>
   ...
 <BrowserRouter> 
), document.body);

来源React Router Version 4 Docs

答案 1 :(得分:40)

Router.run(routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler/>, document.body);
});

对于当前版本0.11和转发版,您需要将Router.HistoryLocation添加到Router.run()<Routes>现已弃用。 See the Upgrade Guide用于0.12.x HistoryLocation实现。

答案 2 :(得分:21)

如果您不需要支持IE8,您可以使用浏览器历史记录和react-router将使用window.pushState而不是设置哈希值。

如何准确地执行此操作取决于您使用的React Router的版本:

答案 3 :(得分:9)

您实际上可以使用.htaccess来完成此任务。浏览器通常需要查询字符串分隔符?#来确定查询字符串的开始位置和目录路径的结束位置。 我们想要的最终结果是www.mysite.com/dir 因此,我们需要在Web服务器搜索它认为我们要求/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

获取查询参数

如果需要,您可以避免使用react路由,如果您愿意,也可以只操作URL和浏览器历史记录。 希望这有助于某人...

答案 4 :(得分:5)

安装历史记录包

npm install history --save

接下来从历史记录中导入createHistory和useBasename

import { createHistory, useBasename } from 'history';
...
const history = useBasename(createHistory)({
  basename: '/root' 
});

如果您的应用网址是www.example.com/myApp,那么/ root应该是/ myApp。

将历史记录变量传递给路由器

render((
  <Router history={history}>
    ...
  </Router>
), document.getElementById('example'));

现在,您的所有链接标记都会在所有路径前添加“/”。

<Link to="/somewhere">somewhere</Link>

解决方案的灵感来自React-Router Example 遗憾的是,他们的API没有正确记录。

答案 5 :(得分:3)

处理散列后显示内容的另一种方法(如果你不使用pushState!)是创建你的CustomLocation并在创建ReactRouter时加载它。

例如,如果你想使用hashbang url(使用#!)来遵守google规范进行抓取,你可以创建一个主要复制原始HashLocation的HashbangLocation.js文件,例如:

'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})

就是这样: - )