Как остановить / # / в браузере с реакции-роутером?

88

Любой способ предотвратить отображение /#/ в адресной строке браузера при использовании реактивного маршрутизатора? Это с ReactJS. Т.е. нажатие на ссылки для перехода на новый маршрут показывает localhost:3000/#/ или localhost:3000/#/about. В зависимости от маршрута.

  • 1
    Это связано с использованием HashHistory iso BrowserHistory . Смотрите также этот вопрос, где я даю много дополнительной информации по этому вопросу.
Теги:
react-router

6 ответов

70

Для версий 1, 2 и 3 реактивного маршрутизатора правильным способом установки маршрута к схеме сопоставления URL является передача реализации истории в параметр history <Router>. Из документации по истории:

В двух словах история знает, как прослушивать адресную строку браузера для изменений и анализирует URL-адрес в объекте местоположения, который маршрутизатор может использовать для соответствия маршрутам и отображать правильный набор компонентов.

Версии 2 и 3

В реакционных маршрутизаторах 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);

Источник: Руководство по обновлению версии 2.0

Версия 4

Для предстоящей версии 4 реактивного маршрутизатора синтаксис сильно изменился, и требуется использовать BrowserRouter в качестве корневого тега маршрутизатора.

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

Источник Документ React Router версии 4

  • 6
    Обратите внимание, что history - это отдельный пакет, который вам нужно установить.
  • 4
    Они изменили browserHistory в v2.x: import { browserHistory } from 'react-router' <Router history={browserHistory} /> Ознакомьтесь с руководством по обновлению реакции-маршрутизатора
Показать ещё 4 комментария
40
Router.run(routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler/>, document.body);
});

Для текущей версии 0.11 и переслать вам нужно добавить Router.HistoryLocation в Router.run(). <Routes> теперь устарели. См. Руководство по обновлению для реализации версии 0.12.x HistoryLocation.

  • 1
    это полностью разрушило мое приложение. похоже их текущая реализация глючит?
  • 2
    @Ninja, возможно, опубликует новый вопрос с точными номерами версий для реакции и реакции-маршрутизатора, с ошибками кода и полученными ошибками.
Показать ещё 2 комментария
19

Если вам не нужно поддерживать IE8, вы можете использовать историю браузера, а реакция-маршрутизатор будет использовать window.pushState вместо установки хеша.

Как именно это сделать, зависит от версии используемого вами React Router:

  • 0
    Спасибо, Бен-Альперт, теперь я понял.
  • 1
    Я добавил <Routes location="history"> все работает нормально, пока вы не обновите браузер на маршруте, т.е. localhost:3000/about тогда я получу ошибку 404. Ожидается ли это, я использую python -m SimpleHTTPServer 3000 ?
Показать ещё 6 комментариев
8

Фактически вы можете использовать .htaccess для этого. Обычно для браузера требуется разделитель строки запроса ? или #, чтобы определить, где начинается строка запроса, и пути каталога заканчиваются. Конечный результат: www.mysite.com/dir Поэтому нам нужно поймать проблему, прежде чем веб-сервер будет искать каталог, который, по его мнению, мы запросили для /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-адресом и историей браузера, если хотите. Надеюсь, это поможет кому-то...

  • 0
    Какой эквивалент для Jboss?
5

Установите пакет истории

npm install history --save

Далее import createHistory и useBasename из истории

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

если ваш URL-адрес приложения - www.example.com/myApp, тогда /root должен быть /myApp.

передать переменную истории в маршрутизатор

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

Теперь для всех ваших тегов ссылок добавьте "/" перед всеми путями.

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

Вдохновение решения взято из Пример React-Router К сожалению, в их API не было должным образом зарегистрировано.

  • 0
    это требует сервера узла? Я пытаюсь достичь того же стиля URL, но только через клиентскую часть. Является ли это возможным?
  • 1
    Нет, вам не нужен сервер узла. На самом деле я работаю на бэкэнде Django. Но вам, вероятно, нужен узел для инструментов.
Показать ещё 3 комментария
3

Другой способ обработки отображаемого после хеша (так что если вы не используете pushState!), это создать свой CustomLocation и загрузить его при создании ReactRouter.

Например, если вы хотите иметь hashbang url (так что С#!), чтобы соответствовать спецификациям google для обхода, вы можете создать файл 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 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})

И что он: -)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню