React-router ile tarayıcıda / # / nasıl durdurulur?


103

/#/React-router kullanırken tarayıcının adres çubuğunda gösterilmesini engellemenin herhangi bir yolu var mı? Bu ReactJS ile. Örneğin, yeni bir rota gösterisine gitmek için bağlantılara tıklamak localhost:3000/#/veya localhost:3000/#/about. Rotaya bağlı olarak.


1
HashHistoryISO kullanmaktan kaynaklanıyor BrowserHistory. Bu konu hakkında birçok arka plan bilgisi verdiğim bu SO sorusuna da bakın .
Stijn de Witt

Yanıtlar:


78

React-router'ın 1, 2 ve 3 sürümleri için, URL eşleme şemasına giden yolu ayarlamanın doğru yolu, historyparametresine bir geçmiş uygulaması geçirmektir <Router>. Gönderen geçmişleri belgeler :

Özetle, bir geçmiş, değişiklikler için tarayıcının adres çubuğunun nasıl dinleneceğini bilir ve URL'yi yönlendiricinin yolları eşleştirmek ve doğru bileşen kümesini oluşturmak için kullanabileceği bir konum nesnesine ayrıştırır.

Sürüm 2 ve 3

React-router 2 ve 3'te, rota yapılandırma kodunuz aşağıdaki gibi görünecektir:

import { browserHistory } from 'react-router'
ReactDOM.render (( 
 <Router history={browserHistory} >
   ...
 </Router> 
), document.body);

Versiyon 1

1.x sürümünde, bunun yerine aşağıdakileri kullanacaksınız:

import createBrowserHistory from 'history/lib/createBrowserHistory'
ReactDOM.render (( 
  <Router history={createBrowserHistory()} >
   ...
  </Router> 
), document.body);

Kaynak: Sürüm 2.0 Yükseltme Kılavuzu

Sürüm 4

React-router'ın yaklaşan 4. sürümü için sözdizimi büyük ölçüde değişti BrowserRouterve yönlendirici kök etiketi olarak kullanılması gerekiyor .

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

Kaynak React Router Sürüm 4 Belgeleri


6
Bunun history, yüklemeniz gereken bağımsız bir paket olduğunu unutmayın.
Jan Klimo

4
browserHistoryV2.x sürümünde değişiklik yaptılar : React -yönlendirici yükseltme kılavuzunuimport { browserHistory } from 'react-router' <Router history={browserHistory} /> kontrol edin
pistou

Teşekkürler @pistou, cevabı 2.0 sürümüne güncelledim!
Adam Brown

1
Çünkü hashHistorysonunda bu sorgu parametresinden kurtulmanın bir yolu var mı? http://localhost:8080/#/dashboard?_k=yqwtyu
Con Antonakos

2
@Matt Çalışıyor, ancak sunucuda destek gerektiriyor. Bunun nedeni, yenilediğinizde, sunucuya yol içeren bir URL ile ulaşmanızdır.
Stijn de Witt

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

Geçerli sürüm 0.11 ve sonrası için eklemeniz Router.HistoryLocationgerekir Router.run(). <Routes>artık kullanımdan kaldırıldı. 0.12.x HistoryLocation uygulaması için Yükseltme Kılavuzuna bakın .


1
bu, uygulamamı tamamen mahvetti. mevcut uygulamaları hatalı gibi görünüyor?
ninjaneer

2
@Ninja, react ve react-router için tam sürüm numaraları, başarısız kod ve alınan hatalar içeren yeni bir soru gönderebilir.
pxwise

@Chet React-yönlendirici belgeleri karıştırılmış gibi görünüyor. Yükseltme Kılavuzunda bulunan HistoryLocation için tek referansa bağlantı güncellendi.
pxwise

21

IE8'i desteklemeniz gerekmiyorsa, Tarayıcı Geçmişini kullanabilirsiniz ve react-router window.pushState, hash'i ayarlamak yerine kullanacaktır .

Bunun tam olarak nasıl yapılacağı, kullanmakta olduğunuz React Router sürümüne bağlıdır:


Teşekkürler @ ben-alpert, şimdi anladım.
Dev Elk

1
Her <Routes location="history">şey yolunda ekledim , tarayıcıyı rotadayken yenileyene kadar, yani localhost:3000/about404 hatası alıyorum. Bu bekleniyor mu, kullanıyorum python -m SimpleHTTPServer 3000?
Dev Elk

5
Sunucu tarafınızın push durumu url'sini işleyebildiğinden emin olmanız gerekir. Bu durumda, muhtemelen uygulamanıza hizmet veren her şeyin her zaman aldığı her url'yi aynı köke gönderdiğinden emin olmanız gerektiği anlamına gelir. Bu /aboutaslında kök sayfanızı yükler /. Aksi takdirde, sunucunuz eşleşen /aboutve hiçbir şey bulamayan bir yol aramaya çalışır (404). Kişisel olarak python kullanmıyorum ama genellikle /*ya /.*-> /çalışır - için manuel bir yol bulursunuz ya da html5Modesunucu ayarlarınızda url denen bir şey olabilir .
Mike Driver

3
IE9 pushState'i de desteklemez - yani bu gerçekten "IE9'u desteklemeniz gerekmiyorsa" değil mi? Keşke yanılmış olsaydım.
Cymen 01

1
Bu github bağlantısı şu anda bulunmayan bir sayfadır.
k00k

9

Bunu gerçekleştirmek için aslında .htaccess'i kullanabilirsiniz. Tarayıcı normalde sorgu dizesi sınırlayıcı ihtiyacı ?veya #sorgu dizesi başlar ve dizin yolları sona yeri belirlemek için. İstediğimiz sonuç şu: www.mysite.com/dir Bu nedenle, web sunucusu istediğimizi düşündüğü dizini aramadan önce sorunu yakalamamız gerekiyor /dir. Bu yüzden .htaccessprojenin köküne bir dosya yerleştiriyoruz .

    # 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

Ardından window.location.pathname ile sorgu parametrelerini elde edersiniz.

Daha sonra, isterseniz tepki yollarını kullanmaktan kaçınabilir ve isterseniz url'yi ve tarayıcı geçmişini de değiştirebilirsiniz. Umarım bu birine yardımcı olur ...


Jboss için eşdeğeri nedir?
Raghavan

5

Geçmiş paketini yükleyin

npm install history --save

Daha sonra, createHistory ve useBasename geçmişini içe aktarın

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

uygulamanızın url'si www.example.com/myApp ise, / root / myApp olmalıdır.

geçmiş değişkenini Yönlendiriciye aktarın

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

Şimdi tüm Bağlantı etiketleriniz için tüm yolların önüne bir "/" ekleyin.

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

Çözümün ilham kaynağı React-Router Örneğinden geldi ve bu maalesef API'lerinde düzgün şekilde belgelenmemişti.


bu bir düğüm sunucusu gerektiriyor mu? Aynı URL stilini elde etmeye çalışıyorum ama sadece istemci tarafında. Mümkün mü?
Sebastialonso

1
hayır, bir düğüm sunucusuna ihtiyacınız yok. Aslında django arka ucunda çalışıyorum. Ama muhtemelen araçlar için düğüme ihtiyacınız var.
Aylık

1
Tamam, bu yaklaşımı denedim. F5'e bastığımda, aldığım tek şey "Bulunamadı". Bu tarihin bununla başa çıkması mümkün mü?
Sebastialonso

u bulunamazsa, bu sunucu tarafından döndürülür. bu, url kalıbının react yönlendiricisinin parçası olmadığı anlamına gelir.
Mox

1
Evet, biraz daha okuduktan sonra her şey netleşti. Anahtarlar olmadan hashHistory ile devam ettim.
Sebastialonso

3

Hash'ten sonra neyin gösterileceğini işlemenin bir başka yolu (bu yüzden pushState'i kullanmıyorsanız!), CustomLocation'ınızı oluşturmak ve ReactRouter oluştururken yüklemektir.

Örneğin, taramaya ilişkin google spesifikasyonlarına uymak için hashbang url'sine (yani #! İle) sahip olmak istiyorsanız, esas olarak orijinal HashLocation'ı kopyalayan bir HashbangLocation.js dosyası oluşturabilirsiniz:

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

Not slashToHashbang fonksiyonunu.

O zaman yapmalısın

ReactRouter.create({location: HashbangLocation})

Ve bu kadar :-)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.