जावास्क्रिप्ट में हैश के बाद URL बदल गया है तो कैसे पता करें


160

यदि कोई URL जावास्क्रिप्ट में बदल गया है तो मैं कैसे जांच सकता हूं? उदाहरण के लिए, GitHub जैसी वेबसाइटें, जो AJAX का उपयोग करती हैं, पृष्ठ को पुनः लोड किए बिना एक अद्वितीय URL बनाने के लिए # प्रतीक के बाद पृष्ठ की जानकारी को जोड़ देंगी। यह पता लगाने का सबसे अच्छा तरीका है कि क्या यह URL बदलता है?

  • क्या onloadघटना को फिर से बुलाया जाता है?
  • क्या URL के लिए कोई ईवेंट हैंडलर है?
  • या परिवर्तन का पता लगाने के लिए URL को हर सेकंड चेक किया जाना चाहिए?

1
भविष्य के आगंतुकों के लिए, 2018 से @aljgom का एक नया उत्तर सबसे अच्छा समाधान है: stackoverflow.com/a/52809105/151503
Redzarf

जवाबों:


106

आधुनिक ब्राउज़रों (IE8 +, FF3.6 +, Chrome) में, आप केवल hashchangeईवेंट को सुन सकते हैं window

कुछ पुराने ब्राउज़रों में, आपको एक टाइमर की आवश्यकता होती है जो लगातार जांचता है location.hash। यदि आप jQuery का उपयोग कर रहे हैं, तो एक प्लगइन है जो वास्तव में ऐसा करता है।


132
यह, जैसा कि मैं समझता हूं, केवल # चिह्न (इसलिए घटना का नाम) के बाद भाग के परिवर्तन के लिए काम करता है? और पूर्ण URL परिवर्तन के लिए नहीं, जैसा कि प्रश्न के शीर्षक से निहित है।
एनपीसी

13
@ एनपीसी पूर्ण URL परिवर्तन (लंगर टैग के बिना) के लिए कोई भी हैंडलर?
नेहा चौधरी

आपको समय-समय पर इवेंट की आवश्यकता होती है: जाँच के लिए माउस और कीबोर्ड का उपयोग करें।
सिजिती

क्या होगा अगर रास्ता बदल जाए, हैश नहीं?
सुपरब्यूपरडू

@SuperUberDuper यदि पथ परिवर्तित हो जाता है क्योंकि उपयोगकर्ता ने एक नेविगेशन शुरू किया / एक लिंक आदि पर क्लिक किया है, तो आप केवल एक beforeunloadघटना देखेंगे । यदि आपके कोड ने URL परिवर्तन आरंभ किया है, तो यह सबसे अच्छा जानता है।
फ़िहग

92

मैं locationchangeइवेंट श्रोताओं को जोड़ना चाहता था । नीचे संशोधन के बाद, हम इसे इस तरह कर पाएंगे

window.addEventListener('locationchange', function(){
    console.log('location changed!');
})

इसके विपरीत, window.addEventListener('hashchange',()=>{})केवल तब आग लग जाएगी जब एक url में हैशटैग के बाद वाला हिस्सा बदल जाता है, और window.addEventListener('popstate',()=>{})हमेशा काम नहीं करता है।

यह संशोधन, ईसाई के उत्तर के समान है , कुछ कार्यक्षमता जोड़ने के लिए इतिहास वस्तु को संशोधित करता है।

डिफ़ॉल्ट रूप से, एक popstateईवेंट है, लेकिन इसके लिए कोई ईवेंट नहीं हैं pushstate, और replacestate

इस संशोधित इन तीन कार्यों ताकि सभी आग एक कस्टम locationchangeआप के लिए उपयोग करने के लिए, और भी घटना pushstateऔर replacestateघटनाओं आप उन का उपयोग करना चाहते हैं:

/* These are the modifications: */
history.pushState = ( f => function pushState(){
    var ret = f.apply(this, arguments);
    window.dispatchEvent(new Event('pushstate'));
    window.dispatchEvent(new Event('locationchange'));
    return ret;
})(history.pushState);

history.replaceState = ( f => function replaceState(){
    var ret = f.apply(this, arguments);
    window.dispatchEvent(new Event('replacestate'));
    window.dispatchEvent(new Event('locationchange'));
    return ret;
})(history.replaceState);

window.addEventListener('popstate',()=>{
    window.dispatchEvent(new Event('locationchange'))
});

2
महान, मुझे क्या ज़रूरत थी धन्यवाद
अनुलोम

धन्यवाद, वास्तव में उपयोगी!
थॉमस लैंग

1
क्या IE में ऐसा करने का कोई तरीका है? जैसा कि यह समर्थन नहीं करता है =>
joshuascotton

1
@joshuacotton => एक एरो फंक्शन है, आप f => फंक्शन fname () {...} को फंक्शन (f) {रिटर्न फंक्शन fname () {...}} से बदल सकते हैं
aljgom

1
यह बहुत मददगार है और आकर्षण की तरह काम करता है। यह स्वीकृत उत्तर होना चाहिए।
कुणाल पारेख

77

इस कोड का उपयोग करें

window.onhashchange = function() { 
     //code  
}

jQuery के साथ

$(window).bind('hashchange', function() {
     //code
});

7
यह उत्तर चिह्नित किया जाना चाहिए। यह एक पंक्ति है, ब्राउज़र इवेंट मॉडल का उपयोग करता है और
निक मिशेल

1
यह मेरी राय में यहाँ सबसे अच्छा जवाब है। कोई प्लगइन और कम से कम कोड
agDev

14
गैर-हैश url परिवर्तनों पर काम नहीं करता है जो बहुत लोकप्रिय लगता है जैसे कि स्लैक द्वारा कार्यान्वित किया गया
NycCompSci

26
यह कैसे सबसे अच्छा जवाब है अगर यह केवल तब ट्रिगर होता है जब यूआरएल में एक हैश होता है?
हारून

1
यदि आप कुछ और भी सुनना चाहते हैं, तो आपको सीधे onhashchange मूल्य को बदलने के बजाय addEventListener का उपयोग करना चाहिए।
टूटा-ए

55

थोड़ा शोध के बाद संपादित करें:

यह किसी भी तरह से लगता है कि मुझे मोज़िला डॉक्स पर मौजूद प्रलेखन द्वारा मूर्ख बनाया गया है। जब भी popstateघटना (और इसके कॉलबैक फ़ंक्शन onpopstate) को ट्रिगर नहीं किया जाता हैpushState() या replaceState()कोड में कहा जाता है। इसलिए सभी मामलों में मूल उत्तर लागू नहीं होता है।

हालाँकि, इसे @ Alpha123 के अनुसार कार्यों को बंदर-पैचिंग द्वारा दरकिनार करने का एक तरीका है :

var pushState = history.pushState;
history.pushState = function () {
    pushState.apply(history, arguments);
    fireEvents('pushState', arguments);  // Some event-handling function
};

मूल उत्तर

यह देखते हुए कि इस प्रश्न का शीर्षक " URL परिवर्तन का पता कैसे लगाएं " उत्तर है, जब आप जानना चाहते हैं कि पूर्ण पथ कब बदलता है (और सिर्फ हैश लंगर नहीं), तो आप इस popstateघटना को सुन सकते हैं :

window.onpopstate = function(event) {
  console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
};

मोज़िला डॉक्स में आबादी के लिए संदर्भ

वर्तमान में (जनवरी 2017) दुनिया भर में 92% ब्राउज़रों से पॉपस्टेट के लिए समर्थन है।


11
अविश्वसनीय है कि हमें अभी भी 2018 में इस तरह के हैक का सहारा लेना चाहिए।
बकरी

1
यह मेरे उपयोग के मामले के लिए काम करता है - लेकिन जैसे @goat कहता है - यह अविश्वसनीय है कि इसके लिए कोई देशी समर्थन नहीं है ...
wasddd_

1
क्या तर्क? मैं आग कैसे लगाऊंगा?
सीनएमसी

2
ध्यान दें कि यह कई मामलों में अविश्वसनीय भी है। उदाहरण के लिए, जब आप विभिन्न अमेज़न उत्पाद विविधताओं (कीमत के नीचे की टाइलें) पर क्लिक करते हैं, तो यह URL परिवर्तन का पता नहीं लगाएगा।
22

2
यदि
लोकेशन

53

Jquery (और एक प्लग-इन) के साथ आप कर सकते हैं

$(window).bind('hashchange', function() {
 /* things */
});

http://benalman.com/projects/jquery-hashchange-plugin/

अन्यथा हां, आपको सेट का उपयोग करना होगा और हैश इवेंट (window.location.hash) में बदलाव के लिए जांच करें

अपडेट करें! एक साधारण ड्राफ्ट

function hashHandler(){
    this.oldHash = window.location.hash;
    this.Check;

    var that = this;
    var detect = function(){
        if(that.oldHash!=window.location.hash){
            alert("HASH CHANGED - new has" + window.location.hash);
            that.oldHash = window.location.hash;
        }
    };
    this.Check = setInterval(function(){ detect() }, 100);
}

var hashDetection = new hashHandler();

क्या मैं (window.location) के परिवर्तन का पता लगा सकता हूं और इसे संभाल सकता हूं? (बिना jquery के)
बर्गप १३'१३

6
आप @BergP, सादे जावास्क्रिप्ट श्रोता का उपयोग कर सकते हैं: window.addEventListener("hashchange", hashChanged);
Ron

1
क्या ऐप के लिए इतना कम समय अंतराल अच्छा है? यही है, यह ब्राउज़र को detect()फ़ंक्शन निष्पादित करने में बहुत व्यस्त नहीं रखता है ?
हसीब महमूद

4
@ हसीब महमूद, उस कोड को हर 100ms पर 1 समानता की जाँच कर रहा है। मैंने अभी अपने ब्राउज़र में बेंचमार्क किया कि मैं 1ms से कम में 500 समानता की जांच कर सकता हूं। इसलिए वह कोड मेरी प्रोसेसिंग पावर का 1/50000 वां उपयोग कर रहा है। मुझे बहुत चिंता नहीं होगी।
z5h

24

एक हैश परिवर्तन ईवेंट श्रोता जोड़ें!

window.addEventListener('hashchange', function(e){console.log('hash changed')});

या, सभी URL परिवर्तनों को सुनने के लिए:

window.addEventListener('popstate', function(e){console.log('url changed')});

यह नीचे दिए गए कोड की तरह कुछ से बेहतर है क्योंकि window.onhashchange में केवल एक चीज मौजूद हो सकती है और आप संभवतः किसी और के कोड को ओवरराइट कर रहे होंगे।

// Bad code example

window.onhashchange = function() { 
     // Code that overwrites whatever was previously in window.onhashchange  
}

1
जब आप किसी राज्य को पॉप करते हैं, तो पॉप स्टेट केवल ट्रिगर होता है, न कि एक को धक्का
सीनएमसी

8

इस समाधान ने मेरे लिए काम किया:

var oldURL = "";
var currentURL = window.location.href;
function checkURLchange(currentURL){
    if(currentURL != oldURL){
        alert("url changed!");
        oldURL = currentURL;
    }

    oldURL = window.location.href;
    setInterval(function() {
        checkURLchange(window.location.href);
    }, 1000);
}

checkURLchange();

18
यह एक अल्पविकसित विधि है, मुझे लगता है कि हम उच्च लक्ष्य रख सकते हैं।
कारल्स अल्कोली

8
हालांकि मैं @CarlesAlcolea से सहमत हूं कि यह पुराना लगता है, मेरे अनुभव में यह अभी भी सभी url परिवर्तनों के 100% को पकड़ने का एकमात्र तरीका है।
ट्रेव 14

5
@ahofmann पता चलता है (एक संपादन कि एक टिप्पणी किया जाना चाहिए था में) को बदलने setIntervalके लिए setTimeout:। "setInterval () का उपयोग कर कुछ समय के बाद एक पड़ाव ब्राउज़र लाएगा, क्योंकि यह checkURLchange () हर दूसरे के लिए एक नया कॉल पैदा करेगा setTimeout () सही एकांत है, क्योंकि इसे केवल एक बार कहा जाता है। "
डिविबिसन

सभी URL परिवर्तनों को पकड़ने के लिए यह एकमात्र समाधान रहा है, लेकिन उपभोग करने वाला संसाधन मुझे कुछ अन्य समाधानों की तलाश करने के लिए मजबूर कर रहा है।
लौटते समय

3
या setTimeout@divibisan की तरह उपयोग करने के बजाय , setIntervalफ़ंक्शन के बाहर ले जाएँ । checkURLchange();वैकल्पिक भी हो जाता है।
aristidesfl

4

हालांकि एक पुराना सवाल है, स्थान-बार परियोजना बहुत उपयोगी है।

var LocationBar = require("location-bar");
var locationBar = new LocationBar();

// listen to all changes to the location bar
locationBar.onChange(function (path) {
  console.log("the current url is", path);
});

// listen to a specific change to location bar
// e.g. Backbone builds on top of this method to implement
// it's simple parametrized Backbone.Router
locationBar.route(/some\-regex/, function () {
  // only called when the current url matches the regex
});

locationBar.start({
  pushState: true
});

// update the address bar and add a new entry in browsers history
locationBar.update("/some/url?param=123");

// update the address bar but don't add the entry in history
locationBar.update("/some/url", {replace: true});

// update the address bar and call the `change` callback
locationBar.update("/some/url", {trigger: true});

यह नोडज के लिए है, हमें इसे क्लाइंट-साइड का उपयोग करने के लिए ब्राउज़राइज़ का उपयोग करना होगा। क्या हम नहीं?
Hack4mer

1
नहीं, यह नहीं है। ब्राउज़र में काम करता है
रे बोयसेन

3

Url परिवर्तनों को सुनने के लिए, नीचे देखें:

window.onpopstate = function(event) {
  console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
};

यदि आप कुछ निश्चित स्थिति के बाद श्रोता को रोकने / हटाने का इरादा रखते हैं तो इस शैली का उपयोग करें।

window.addEventListener('popstate', function(e) {
   console.log('url changed')
});

2

थोड़ा क्रोम एक्सटेंशन करते समय, मुझे एक समान समस्या का सामना करना पड़ा: कभी-कभी, पृष्ठ बदल जाता है, लेकिन URL नहीं।

उदाहरण के लिए, बस फेसबुक होमपेज पर जाएं, और 'होम' बटन पर क्लिक करें। आप पृष्ठ को फिर से लोड करेंगे, लेकिन URL नहीं बदलेगा (एक-पृष्ठ ऐप शैली)।

99% समय, हम वेबसाइटों को विकसित कर रहे हैं ताकि हम उन घटनाओं जैसे कि कोणीय, प्रतिक्रिया, स्वर आदि से प्राप्त कर सकें।

लेकिन , Chrome एक्सटेंशन (वेनिला JS में) के मेरे मामले में, मुझे एक ऐसी घटना को सुनना पड़ा, जो प्रत्येक "पृष्ठ परिवर्तन" के लिए ट्रिगर होगी, जिसे आमतौर पर URL द्वारा बदला जा सकता है, लेकिन कभी-कभी ऐसा नहीं होता है।

मेरा घर का बना समाधान निम्नलिखित था:

listen(window.history.length);
var oldLength = -1;
function listen(currentLength) {
  if (currentLength != oldLength) {
    // Do your stuff here
  }

  oldLength = window.history.length;
  setTimeout(function () {
    listen(window.history.length);
  }, 1000);
}

तो मूल रूप से लियोनर्ट समाधान, खिड़की के इतिहास पर लागू किया जाता है, जो एक पेज पेज ऐप में बदलने पर बदल जाएगा।

रॉकेट विज्ञान नहीं, लेकिन सबसे साफ समाधान मुझे मिला, यह देखते हुए कि हम केवल एक पूर्णांक समानता की जांच कर रहे हैं, और बड़ी वस्तुओं या पूरे डोम की नहीं।


आप समाधान सरल है और क्रोम एक्सटेंशन के लिए बहुत अच्छी तरह से काम करता है। मैं लंबाई के बजाय YouTube वीडियो आईडी का उपयोग करने का सुझाव देना चाहूंगा। stackoverflow.com/a/3452617/808901
रॉड लीमा

2
आपको सेटइंटरवल का उपयोग नहीं करना चाहिए क्योंकि जब भी आप कॉल सुनते हैं (xy) तो एक नया अंतराल बनाया जाता है और आप हजारों अंतराल के साथ समाप्त हो जाते हैं।
स्टेफ चेसर

1
आप सही हैं मैंने देखा है कि मेरे पोस्ट को बदलने और बदलने के बाद, मैं इसे संपादित नहीं करूंगा। वापस समय में मैं भी RAM लीक की वजह से Google Chrome की एक दुर्घटना का सामना करना पड़ा। टिप्पणी के लिए धन्यवाद
अल्बर्कर

window.historyअधिकतम लंबाई 50 (क्रोम 80 के रूप में कम से कम) है। उस बिंदु के बाद, window.history.lengthहमेशा 50 लौटता है। जब ऐसा होता है, तो यह विधि किसी भी परिवर्तन को पहचानने में विफल हो जाएगी।
कॉलिन क्रॉल

1

JQuery के अनलोड फ़ंक्शन को देखें। यह सभी चीजों को संभालता है।

https://api.jquery.com/unload/

उपयोगकर्ता द्वारा पृष्ठ से दूर जाने पर उतारने की घटना विंडो तत्व को भेजी जाती है। इसका मतलब कई चीजों में से एक हो सकता है। उपयोगकर्ता पृष्ठ छोड़ने के लिए एक लिंक पर क्लिक कर सकता था, या पता बार में एक नए URL में टाइप किया जा सकता था। आगे और पीछे बटन घटना को गति देगा। ब्राउज़र विंडो बंद करने से ईवेंट ट्रिगर हो जाएगा। यहां तक ​​कि एक पृष्ठ पुनः लोड पहले एक अनलोड घटना पैदा करेगा।

$(window).unload(
    function(event) {
        alert("navigating");
    }
);

2
जहां सामग्री में अजाक्स किया गया है, उरेल को खिड़की के बिना उतार दिया जा सकता है। यह स्क्रिप्ट एक url परिवर्तन का पता नहीं लगाती है, हालाँकि यह अभी भी कुछ उपयोगकर्ताओं के लिए मददगार हो सकती है जिनके पास प्रत्येक url परिवर्तन पर एक विंडो अनलोड है।
डेबोरा

@ranbuch प्रश्न के समान, यह केवल उन पृष्ठों के लिए विशिष्ट है जो एकल पृष्ठ अनुप्रयोग नहीं हैं, और यह ईवेंट केवल अनलोड विंडो ईवेंट देख रहा है, url परिवर्तन नहीं।
नूबिका

0
window.addEventListener("beforeunload", function (e) {
    // do something
}, false);

11
यह एकल पृष्ठ अनुप्रयोगों के संदर्भ में काम नहीं करेगा क्योंकि अनलोड घटना कभी भी ट्रिगर नहीं होगी
ncubica

0

नीचे उत्तर यहां से आया है (पुरानी जावास्क्रिप्ट सिंटैक्स (कोई तीर फ़ंक्शन, समर्थन IE 10+) के साथ): https://stackoverflow.com/a/52809105/9168962

(function() {
  if (typeof window.CustomEvent === "function") return false; // If not IE
  function CustomEvent(event, params) {
    params = params || {bubbles: false, cancelable: false, detail: null};
    var evt = document.createEvent("CustomEvent");
    evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
    return evt;
  }
  window.CustomEvent = CustomEvent;
})();

(function() {
  history.pushState = function (f) {
    return function pushState() {
      var ret = f.apply(this, arguments);
      window.dispatchEvent(new CustomEvent("pushState"));
      window.dispatchEvent(new CustomEvent("locationchange"));
      return ret;
    };
  }(history.pushState);
  history.replaceState = function (f) {
    return function replaceState() {
      var ret = f.apply(this, arguments);
      window.dispatchEvent(new CustomEvent("replaceState"));
      window.dispatchEvent(new CustomEvent("locationchange"));
      return ret;
    };
  }(history.replaceState);
  window.addEventListener("popstate", function() {
    window.dispatchEvent(new CustomEvent("locationchange"));
  });
})();

0

ऐसा करने का एक और सरल तरीका यह है कि क्लिक इवेंट जोड़कर, पेज पर एंकर टैग के लिए एक क्लास नाम के माध्यम से यह पता लगाने के लिए कि इसे कब क्लिक किया गया है, तो अब आप url डेटा प्राप्त करने के लिए window.location.href का उपयोग कर सकते हैं आप सर्वर पर अपने ajax अनुरोध को चलाने के लिए उपयोग कर सकते हैं। सरल और आसान।


-1

आप setIntervalप्रत्येक कॉल पर एक नया शुरू कर रहे हैं , पिछले एक को रद्द किए बिना - शायद आपके पास केवल एक होने का मतलब थाsetTimeout

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.