การแก้ไขสตริงแบบสอบถามโดยไม่ต้องโหลดหน้าซ้ำ


114

ฉันกำลังสร้างแกลเลอรีรูปภาพและต้องการที่จะเปลี่ยนสตริงการสืบค้นและชื่อเรื่องเมื่อมีการเรียกดูรูปภาพ

พฤติกรรมที่ฉันกำลังมองหามักจะเห็นได้จากการใช้งานเพจต่อเนื่อง / ไม่มีที่สิ้นสุดโดยที่ในขณะที่คุณเลื่อนสตริงการค้นหาลงจะเพิ่มหมายเลขหน้า ( http://x.com?page=4 ) เป็นต้นซึ่งควรจะเป็น ตามหลักทฤษฎี แต่ฉันต้องการสิ่งที่ปลอดภัยในเบราว์เซอร์หลัก ๆ

ฉันพบโพสต์ที่ยอดเยี่ยมนี้และพยายามทำตามตัวอย่างด้วยwindow.history.pushstateแต่ดูเหมือนจะไม่ได้ผลสำหรับฉัน และฉันไม่แน่ใจว่าจะเหมาะหรือไม่เพราะฉันไม่สนใจเกี่ยวกับการแก้ไขประวัติเบราว์เซอร์

ฉันแค่ต้องการให้สามารถบุ๊กมาร์กรูปภาพที่ดูอยู่ในปัจจุบันโดยไม่ต้องโหลดหน้าซ้ำทุกครั้งที่มีการเปลี่ยนแปลงรูปภาพ

นี่คือตัวอย่างของเพจที่ไม่มีที่สิ้นสุดที่แก้ไขสตริงการสืบค้น: http://tumbledry.org/

UPDATEพบวิธีนี้:

window.location.href = window.location.href + '#abc';

ดูเหมือนว่าจะใช้ได้สำหรับฉัน แต่ฉันใช้ Chrome ใหม่ .. มันอาจจะทำให้เกิดปัญหากับเบราว์เซอร์รุ่นเก่าหรือไม่


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



อาจซ้ำกันได้เหตุใดเว็บใหม่ Dropbox จึงสามารถเปลี่ยน URL ได้โดยไม่ต้องรีเฟรชหน้า? และคำถามสามข้อถูกทำเครื่องหมายว่าซ้ำกัน
Quentin

@ เควนติน. คุณสามารถโหวตได้เพียงครั้งเดียวเท่านั้น ...:)
gdoron สนับสนุน Monica

คำตอบ:


185

หากคุณกำลังมองหาการปรับเปลี่ยนแฮชโซลูชันของคุณก็ใช้ได้ อย่างไรก็ตามหากคุณต้องการเปลี่ยนแบบสอบถามคุณสามารถใช้ pushState ได้ตามที่คุณกล่าว นี่คือตัวอย่างที่อาจช่วยให้คุณนำไปใช้ได้อย่างถูกต้อง ฉันทดสอบแล้วและใช้งานได้ดี:

if (history.pushState) {
    var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?myNewUrlQuery=1';
    window.history.pushState({path:newurl},'',newurl);
}

ไม่โหลดหน้าซ้ำ แต่อนุญาตให้คุณเปลี่ยนแบบสอบถาม URL เท่านั้น คุณจะไม่สามารถเปลี่ยนโปรโตคอลหรือค่าโฮสต์ได้ และแน่นอนว่าต้องใช้เบราว์เซอร์สมัยใหม่ที่สามารถประมวลผล HTML5 History API ได้

สำหรับข้อมูลเพิ่มเติม:

http://diveintohtml5.info/history.html

https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history


6
ฉันเชื่อว่าคุณสามารถย่อwindow.location.protocol + '//' + window.location.hostให้เหลือเพียง: window.location.origin.
Garrett

4
history.pushState()นอกจากนี้สำหรับบิตนอกเหนือจากข้อมูลทางญาติทำงานเป็นอย่างดีด้วย ไม่stateจำเป็นต้องมีอาร์กิวเมนต์ที่แท้จริง ทั้งสองอย่างนี้หมายความว่าคุณสามารถทำอะไรง่ายๆเช่นhistory.pushState(null, '', '/foo?bar=true')ถ้า url ใหม่ของคุณอยู่บนโฮสต์ / พอร์ตเดียวกัน
Blaskovicz

23
โปรดทราบว่าหากคุณไม่ต้องการให้สถานะใหม่ปรากฏในประวัติของเบราว์เซอร์คุณสามารถใช้history.replaceState()กับอาร์กิวเมนต์เดียวกันได้
Blackus

6
ใช้ history.replaceState () มิฉะนั้นคุณต้องคลิกปุ่มย้อนกลับสองครั้งในเบราว์เซอร์ของคุณ
Zhenya

4
ในเบราว์เซอร์สมัยใหม่คุณสามารถทำได้:if (window.history.pushState) { const newURL = new URL(window.location.href); newURL.search = '?myNewUrlQuery=1'; window.history.pushState({ path: newURL.href }, '', newURL.href); }
Allan Baptista

8

จากคำตอบของ Fabio ฉันได้สร้างฟังก์ชันสองอย่างที่อาจเป็นประโยชน์สำหรับทุกคนที่สะดุดกับคำถามนี้ ด้วยฟังก์ชันทั้งสองนี้คุณสามารถเรียกinsertParam()ใช้คีย์และค่าเป็นอาร์กิวเมนต์ได้ มันจะเพิ่มพารามิเตอร์ URL หรือหากมีพารามิเตอร์เคียวรีที่มีคีย์เดียวกันอยู่แล้วก็จะเปลี่ยนพารามิเตอร์นั้นเป็นค่าใหม่:

//function to remove query params from a URL
function removeURLParameter(url, parameter) {
    //better to use l.search if you have a location/link object
    var urlparts= url.split('?');   
    if (urlparts.length>=2) {

        var prefix= encodeURIComponent(parameter)+'=';
        var pars= urlparts[1].split(/[&;]/g);

        //reverse iteration as may be destructive
        for (var i= pars.length; i-- > 0;) {    
            //idiom for string.startsWith
            if (pars[i].lastIndexOf(prefix, 0) !== -1) {  
                pars.splice(i, 1);
            }
        }

        url= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : "");
        return url;
    } else {
        return url;
    }
}

//function to add/update query params
function insertParam(key, value) {
    if (history.pushState) {
        // var newurl = window.location.protocol + "//" + window.location.host + search.pathname + '?myNewUrlQuery=1';
        var currentUrlWithOutHash = window.location.origin + window.location.pathname + window.location.search;
        var hash = window.location.hash
        //remove any param for the same key
        var currentUrlWithOutHash = removeURLParameter(currentUrlWithOutHash, key);

        //figure out if we need to add the param with a ? or a &
        var queryStart;
        if(currentUrlWithOutHash.indexOf('?') !== -1){
            queryStart = '&';
        } else {
            queryStart = '?';
        }

        var newurl = currentUrlWithOutHash + queryStart + key + '=' + value + hash
        window.history.pushState({path:newurl},'',newurl);
    }
}

ฟังก์ชั่นของคุณดีกว่าnew URLSearchParams()ด้วยวิธีดั้งเดิมตามที่ตั้งไว้และลบอย่างไร? ในทั้งสองกรณีเราจะต้องนำมันไปสู่ประวัติศาสตร์ด้วยhistory.pushState()
AlexNikonov

1
new URLSearchParams()ไม่รองรับ IE เวอร์ชันใด ๆ
jmona789

ขอบคุณ @ jmona789 สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับฉันและเป็นสิ่งที่ฉันกำลังมองหา
mknopf

7

ฉันใช้ไลบรารี JavaScript ต่อไปนี้และประสบความสำเร็จอย่างมาก:

https://github.com/balupton/jquery-history

รองรับ HTML5 history API ตลอดจนวิธีการสำรอง (โดยใช้ #) สำหรับเบราว์เซอร์รุ่นเก่า

ไลบรารีนี้มีลักษณะเป็น polyfill รอบ ๆ `history.pushState '


สุดยอด! คุณทดสอบกับเบราว์เซอร์ทั้งหมดหรือไม่ ??
Sonic Soul

การใช้งานของฉันได้รับการทดสอบใน IE7 +, Firefox 3.6+, Safari 5 และ Chrome 16+ อาจใช้งานได้กับเบราว์เซอร์อื่น ๆ ด้วย แต่ฉันไม่มีข้อร้องเรียนใด ๆ ในระบบต่างๆที่ใช้งานได้
Ian Newson

เยี่ยมมาก ตอนนี้ .. เพียงแค่ใส่ # แทน & เมื่อเขียนลงใน window.location.href ก็ใช้ได้ผลสำหรับฉัน โดยจะไม่โหลดหน้าซ้ำ ฉันแน่ใจว่ามันจะพังเมื่อฉันทดสอบใน IE .. ณ จุดนั้นฉันจะไปกับไลบรารีที่คุณแนะนำ ขอบคุณ
Sonic Soul

วิธีการ # เป็นวิธีที่ดีเนื่องจากมีการรองรับเบราว์เซอร์ที่กว้างมาก สิ่งต่างๆอาจมีความซับซ้อนเมื่อคุณต้องรวมข้อมูลนั้นในคำขอไปยังเซิร์ฟเวอร์เนื่องจากเบราว์เซอร์ไม่ได้ส่งส่วน # ของ URL มีหลายวิธีที่รวมถึงไลบรารีที่ฉันอ้างถึง นอกจากนี้การใช้ API ประวัติ HTML5 ยังช่วยให้ URL ของคุณโดยรวมสั้นลงและต้องใช้งานฝั่งไคลเอ็นต์น้อยลงในการกู้คืนสถานะ
Ian Newson

วิธี # ยังเป็นปัญหาสำหรับการแชร์บนโซเชียลมีเดีย Twitter, Facebook และอื่น ๆ อาจเล่นได้ไม่ดีกับแท็ก Anchor เมื่อสร้างตัวอย่างหรือลิงก์กลับไปที่การแชร์
mirth23

5

ฉันต้องการปรับปรุงคำตอบของ Fabio และสร้างฟังก์ชันที่เพิ่มคีย์ที่กำหนดเองให้กับสตริง URL โดยไม่ต้องโหลดหน้าซ้ำ

function insertUrlParam(key, value) {
    if (history.pushState) {
        let searchParams = new URLSearchParams(window.location.search);
        searchParams.set(key, value);
        let newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + searchParams.toString();
        window.history.pushState({path: newurl}, '', newurl);
    }
}

0

จากนั้น API ประวัติคือสิ่งที่คุณกำลังมองหา หากคุณต้องการสนับสนุนเบราว์เซอร์เดิมด้วยให้มองหาไลบรารีที่กลับมาจัดการแฮชแท็กของ URL หากเบราว์เซอร์ไม่ได้ให้ประวัติ API

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