บน - window.location.hash - เปลี่ยนหรือไม่


558

ฉันใช้อาแจ็กซ์และแฮสำหรับการนำทาง

มีวิธีตรวจสอบการwindow.location.hashเปลี่ยนแปลงเช่นนี้หรือไม่?

http://example.com/blah # 123ถึงhttp://example.com/blah # 456

มันทำงานได้ถ้าฉันตรวจสอบเมื่อเอกสารโหลด

แต่ถ้าฉันใช้การนำทาง #hash จะไม่ทำงานเมื่อฉันกดปุ่มย้อนกลับบนเบราว์เซอร์ (ดังนั้นฉันจึงข้ามจาก blah # 456 ไปยัง blah # 123)

มันแสดงอยู่ข้างในกล่องที่อยู่ แต่ฉันไม่สามารถจับมันด้วย JavaScript


6
ชำระเงินปลั๊กอิน jquery นี้: github.com/cowboy/jquery-hashchange
Xavi

9
History.jsรองรับฟังก์ชั่นการจัดการสถานะ HTML5 (ดังนั้นคุณไม่จำเป็นต้องใช้แฮชอีกต่อไป!) และลดระดับลงอย่างเบราว์เซอร์เป็น HTML4 เบราว์เซอร์โดยใช้แฮชชี่ รองรับ jQuery, MooTools และ Prototype นอกกรอบ
balupton

@ balupton ที่จริงแล้วเรายังคงต้องใช้แฮชเพื่อให้ข้อเสนอแนะแก่ผู้ใช้ว่ามีการแทรก "หน้าใหม่" ในประวัติของเขาเว้นแต่คุณจะใช้การเปลี่ยน URL เป็นข้อเสนอแนะ
Pacerier


อืม ... ฉันคิดว่าคุณต้องการ moar jQuery
RaisingAgent

คำตอบ:


617

วิธีเดียวที่จะทำสิ่งนี้ได้อย่างแท้จริง (และเป็นวิธีการที่ 'realsimplehistory' ทำอย่างนี้) คือการกำหนดช่วงเวลาที่คอยตรวจสอบแฮชปัจจุบันและเปรียบเทียบกับสิ่งที่เคยเป็นมาก่อนเราทำสิ่งนี้และให้สมาชิกสมัครสมาชิกเพื่อเปลี่ยน เหตุการณ์ที่เราเริ่มต้นหากแฮชเปลี่ยนไป .. มันไม่สมบูรณ์ แต่เบราว์เซอร์ไม่รองรับเหตุการณ์นี้โดยกำเนิด


อัปเดตเพื่อให้คำตอบใหม่อยู่เสมอ:

หากคุณกำลังใช้ jQuery (ซึ่งวันนี้ควรจะเป็นพื้นฐานสำหรับคนส่วนใหญ่) วิธีแก้ปัญหาที่ดีก็คือการใช้ abstraction ที่ jQuery ให้คุณโดยใช้ระบบกิจกรรมเพื่อฟังเหตุการณ์ hashchange บนวัตถุหน้าต่าง

$(window).on('hashchange', function() {
  //.. work ..
});

สิ่งที่ดีที่นี่คือคุณสามารถเขียนโค้ดที่ไม่จำเป็นต้องกังวลเกี่ยวกับการสนับสนุน hashchange แต่คุณต้องทำเวทมนต์ในรูปแบบของคุณสมบัติ jQuery ที่รู้จักกันน้อยกว่าjQuery กิจกรรมพิเศษกิจกรรมพิเศษ

ด้วยคุณสมบัตินี้คุณจะต้องเรียกใช้รหัสการตั้งค่าสำหรับเหตุการณ์ใด ๆ เป็นครั้งแรกที่มีคนพยายามใช้เหตุการณ์ในลักษณะใด ๆ (เช่นผูกกับเหตุการณ์)

ในรหัสการตั้งค่านี้คุณสามารถตรวจสอบการสนับสนุนเบราว์เซอร์ดั้งเดิมและหากเบราว์เซอร์ไม่ได้ใช้สิ่งนี้คุณสามารถตั้งค่าตัวจับเวลาเดี่ยวเพื่อสำรวจความเปลี่ยนแปลงและเรียกใช้เหตุการณ์ jQuery

นี้อย่างสมบูรณ์ unbinds รหัสของคุณจากต้องเข้าใจปัญหานี้สนับสนุนการดำเนินงานของกิจกรรมพิเศษชนิดนี้เป็นที่น่ารำคาญ (ง่ายที่จะได้รับรุ่นที่ทำงาน 98%) แต่ทำไมทำอย่างนั้นเมื่อมีคนอื่นที่มีอยู่แล้ว


7
IE8 ทำ อีกมากมายที่จะมา
Sergey Ilinsky

28
Firefox รุ่นล่าสุด (3.6 อัลฟ่า) รองรับการเปลี่ยนแปลงแฮชดั้งเดิมแล้วด้วย: developer.mozilla.org/en/DOM/window.onhashchange แน่นอนว่ามันคุ้มค่าที่จะตรวจสอบเหตุการณ์นี้ แต่ทราบว่า IE8 จะบอกเหตุการณ์ให้คุณทราบ มีอยู่เมื่อมันทำงานในโหมดที่รองรับ IE7 .. น่าเศร้าที่เหตุการณ์ไม่ทำงาน .. คุณจะต้องตรวจสอบเหตุการณ์และเบราว์เซอร์ไม่ปรากฏว่าเป็น IE7 .. ถอนหายใจ (หรือพยายามที่จะทริกเกอร์เหตุการณ์ ด้วยวิธี fireEvent ของ IE)
meandmycode

8
ในขณะที่เขียน WebKit ก็เริ่มhashchangeเหตุการณ์ขณะที่ Safari (เสถียร) ยังไม่เกิดขึ้น
jholster

51
เพียงแค่เพิ่มการอัปเดตอื่น ๆhashchangeตอนนี้เหตุการณ์ได้รับการสนับสนุนอย่างกว้างขวาง: caniuse.com/#search=hash
Paystey

19
ฉันเป็นคนเดียวที่คิดว่าคำตอบ jQuery ที่ไม่พึงประสงค์เป็นความเจ็บปวดหรือไม่?
ลัค

290

HTML5 ระบุhashchangeเหตุการณ์ เหตุการณ์นี้เป็นที่ตอนนี้ได้รับการสนับสนุนจากเบราว์เซอร์ที่ทันสมัย มีการเพิ่มการสนับสนุนในเบราว์เซอร์เวอร์ชันต่อไปนี้:

  • Internet Explorer 8
  • Firefox 3.6
  • Chrome 5
  • Safari 5
  • Opera 10.6

20
อัปเดต: FF 5, Safari 5 และ Chrome 12 รองรับกิจกรรมนี้ในเดือนมิถุนายน 2554
james.garriss

2
นี่คือหน้า CanIUse สำหรับ hashchange นี่คือhashchange บน quirksmode การรองรับ IE นั้นเป็นเรื่องเกี่ยวกับความไวของตัวเคส
Tobu

3
@ ทุกคนไม่จำเป็นต้องต่อท้ายคำตอบในส่วนความคิดเห็นนั่นคือปุ่ม "แก้ไข" :)
Michael Martin-Smucker

15
การใช้งาน:window.onhashchange = function() { doYourStuff(); }
Chris

4
เอกสาร MDN ของเหตุการณ์ hashchange
Dabowheel

52

โปรดทราบว่าในกรณีของ Internet Explorer 7 และ Internet Explorer 9 สถานะifจะเป็นจริง (สำหรับ "onhashchange" ใน windows) แต่window.onhashchangeจะไม่ทำงานดังนั้นจึงดีกว่าที่จะเก็บแฮชและตรวจสอบทุก ๆ 100 มิลลิวินาทีไม่ว่าจะเปลี่ยนหรือไม่ สำหรับ Internet Explorer ทุกรุ่น

    if (("onhashchange" in window) && !($.browser.msie)) {
         window.onhashchange = function () {
              alert(window.location.hash);
         }
         // Or $(window).bind( 'hashchange',function(e) {
         //       alert(window.location.hash);
         //   });
    }
    else {
        var prevHash = window.location.hash;
        window.setInterval(function () {
           if (window.location.hash != prevHash) {
              prevHash = window.location.hash;
              alert(window.location.hash);
           }
        }, 100);
    }

แก้ไข - ตั้งแต่ jQuery 1.9 $.browser.msieไม่ได้รับการสนับสนุน ที่มา: http://api.jquery.com/jquery.browser/


14

มีเทคนิคมากมายในการจัดการประวัติและ window.location.hash ในเบราว์เซอร์ IE:

  • ตามคำถามเดิมกล่าวว่าถ้าคุณไปจากหน้า a.html # b ถึง a.html # c จากนั้นกดปุ่มย้อนกลับเบราว์เซอร์ไม่ทราบว่าหน้านั้นมีการเปลี่ยนแปลง ให้ฉันพูดด้วยตัวอย่าง: window.location.href จะเป็น 'a.html # c' ไม่ว่าคุณจะอยู่ใน a.html # b หรือ a.html # c

  • ที่จริงแล้ว a.html # b และ a.html # c ถูกเก็บไว้ในประวัติเฉพาะในกรณีที่มีองค์ประกอบ '<a name="#b">' และ '<a name="#c">' มีอยู่ก่อนหน้านี้ในหน้า

  • อย่างไรก็ตามหากคุณใส่ iframe ไว้ในหน้าให้นำทางจาก a.html # b ไปยัง a.html # c ใน iframe นั้นแล้วกดปุ่มย้อนกลับ iframe.contentWindow.document.location.href จะเปลี่ยนตามที่คาดไว้

  • หากคุณใช้ 'document.domain = something ' ในรหัสของคุณคุณจะไม่สามารถเข้าถึง iframe.contentWindow.document.open () '(และผู้จัดการประวัติหลายคนทำเช่นนั้น)

ฉันรู้ว่านี่ไม่ใช่การตอบสนองที่แท้จริง แต่อาจมีบางคนที่เป็นประโยชน์



11

Ben Alman มีปลั๊กอิน jQuery ที่ยอดเยี่ยมสำหรับจัดการกับสิ่งนี้: http://benalman.com/projects/jquery-hashchange-plugin/

หากคุณไม่ได้ใช้ jQuery อาจเป็นข้อมูลอ้างอิงที่น่าสนใจในการตัดทอน


ดูเหมือนว่าปลั๊กอิน Ben Alman จะไม่ได้รับการบำรุงรักษาอีกต่อไป มีส้อมจำนวนมาก
Mnebuerquo

9

คุณสามารถนำผู้สังเกตการณ์ (วิธี "เฝ้าดู") ไปใช้กับคุณสมบัติ "แฮช" ของวัตถุ "window.location" ได้อย่างง่ายดาย

Firefox มีการใช้งานของตัวเองสำหรับการดูการเปลี่ยนแปลงของวัตถุแต่ถ้าคุณใช้การใช้งานอื่น ๆ (เช่นการเปลี่ยนแปลงการดูคุณสมบัติของวัตถุใน JavaScript ) - สำหรับเบราว์เซอร์อื่น ๆ นั่นจะเป็นการหลอกลวง

รหัสจะมีลักษณะดังนี้:

window.location.watch(
    'hash',
    function(id,oldVal,newVal){
        console.log("the window's hash value has changed from "+oldval+" to "+newVal);
    }
);

จากนั้นคุณสามารถทดสอบได้:

var myHashLink = "home";
window.location = window.location + "#" + myHashLink;

และแน่นอนว่าจะเรียกใช้ฟังก์ชันผู้สังเกตการณ์ของคุณ


ใช้งานได้ดีกว่า: window.location.href แทนที่จะเป็น window.location
Codebeat

3
เขากำลังดู window.location.hash ไม่ใช่ window.location
ไม่ได้กำหนด

1
@BrianMortenson: ตามเอกสาร ( developer.mozilla.org/en-US/docs/JavaScript/Reference/ ...... ) คุณต้องใช้watchกับวัตถุที่เป็นเจ้าของทรัพย์สินที่มีการเปลี่ยนแปลงและคุณต้องการที่จะสังเกตเห็น
gion_13

@ gion_13 ใช่นั่นคือสิ่งที่ฉันพยายามชี้ให้เห็น โดย 'เขา' ฉันหมายถึงคุณและมันเป็นความคิดเห็นของ Erwinus ฉันควรจะชัดเจนมากขึ้น ขอบคุณสำหรับความคิดเห็นที่ชัดเจนของคุณ
ไม่ได้กำหนด

7

ฉันใช้สิ่งนี้ในแอปพลิเคชันตอบโต้เพื่อทำให้ URL แสดงพารามิเตอร์ที่แตกต่างกันขึ้นอยู่กับว่าผู้ใช้เปิดดูอะไรอยู่

ฉันดูพารามิเตอร์แฮชโดยใช้

window.addEventListener('hashchange', doSomethingWithChangeFunction());

แล้วก็

doSomethingWithChangeFunction () { 
    // Get new hash value
    let urlParam = window.location.hash;
    // Do something with new hash value
};

ใช้การรักษาทำงานกับปุ่มเบราว์เซอร์ไปข้างหน้าและย้อนกลับ


1
ในการaddEventListenerโทรของคุณคุณควรลบออก()จากdoSomethingWithChangeFunction
Jason S

คุณสามารถให้เหตุผลในการลบ () หรือไม่ ฉันรู้ว่ามันจะทำงานร่วมกับอย่างใดอย่างหนึ่งและรหัสน้อยลงเป็นตัวเลือกที่ดีกว่าส่วนใหญ่ แต่นี่ดูเหมือนจู้จี้จุกจิกเว้นแต่จะมีเหตุผลมากมายที่จะสำรองข้อมูลนี้
Sprose

6
? ()มันไม่ควรทำงานร่วมกับ addEventListenerฟังก์ชั่นคุณจะต้องผ่านในฟังก์ชั่น doSomethingWithChangeFunctionเป็นฟังก์ชั่น doSomethingWithChangeFunction()คือค่าส่งคืนของฟังก์ชันนั้นซึ่งในกรณีนี้ไม่ใช่ฟังก์ชัน
Jason S

6

มีการใช้งานที่เหมาะสมที่http://code.google.com/p/reallysimplehistory/ http://code.google.com/p/reallysimplehistory/ปัญหา (และเท่านั้น) เท่านั้นและข้อผิดพลาดที่มีคือ: ใน Internet Explorer การแก้ไขแฮชตำแหน่งด้วยตนเองจะรีเซ็ตสแต็คประวัติทั้งหมด (นี่เป็นปัญหาเบราว์เซอร์และไม่สามารถแก้ไขได้)

หมายเหตุ Internet Explorer 8 รองรับกิจกรรม "hashchange" และเนื่องจากกำลังเป็นส่วนหนึ่งของ HTML5 คุณอาจคาดว่าเบราว์เซอร์อื่น ๆ


1

การใช้งานที่ยอดเยี่ยมอีกอย่างหนึ่งคือประวัติ jQueryซึ่งจะใช้เนทีฟ onhashchange ถ้ามันรองรับเบราว์เซอร์ถ้าไม่ใช่มันจะใช้ iframe หรือช่วงเวลาที่เหมาะสมสำหรับเบราว์เซอร์ นอกจากนี้ยังมีอินเทอร์เฟซที่ดีในการผูกกับบางสถานะ

อีกหนึ่งโครงการที่น่าสังเกตก็คือjQuery Ajaxyซึ่งเป็นส่วนเสริมสำหรับประวัติ jQuery เพื่อเพิ่ม ajax ให้กับการผสมผสาน เมื่อคุณเริ่มใช้ Ajax กับแฮชมันค่อนข้างซับซ้อน !


1
var page_url = 'http://www.yoursite.com/'; // full path leading up to hash;
var current_url_w_hash = page_url + window.location.hash; // now you might have something like: http://www.yoursite.com/#123

function TrackHash() {
    if (document.location != page_url + current_url_w_hash) {
        window.location = document.location;
    }
    return false;
}
var RunTabs = setInterval(TrackHash, 200);

เพียงเท่านี้ ... ตอนนี้เมื่อใดก็ตามที่คุณกดปุ่มย้อนกลับหรือไปข้างหน้าหน้าจะโหลดใหม่ตามค่าแฮชใหม่


อย่าใช้สตริง eval
Vitim.us

1

ฉันใช้ path.js สำหรับการกำหนดเส้นทางฝั่งไคลเอ็นต์ ฉันพบว่ามันค่อนข้างรัดกุมและมีน้ำหนักเบา (มันถูกเผยแพร่ไปยัง NPM ด้วย) และใช้ประโยชน์จากการนำทางแบบแฮช

path.js NPM

path.js GitHub


0

ฉันใช้ปลั๊กอิน jQuery, HUtilและเขียนประวัติยูอิเช่นอินเทอร์เฟซที่อยู่ด้านบน

ลองดูสักครั้ง หากคุณต้องการความช่วยเหลือฉันสามารถช่วย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.