pushState डुप्लिकेट इतिहास प्रविष्टियों और पिछले लोगों को अधिलेखित करना


15

मैंने एक वेब ऐप बनाया है जो इतिहास को अपडेट करने के दौरान पृष्ठों के माध्यम से नेविगेट करने के लिए history pushStateऔर replaceStateतरीकों का उपयोग करता है ।

स्क्रिप्ट स्वयं लगभग पूरी तरह से काम करती है; यह पृष्ठों को सही ढंग से लोड करेगा, और जब उन्हें फेंकने की आवश्यकता होती है तो पृष्ठ त्रुटियों को फेंक देंगे। हालाँकि, मैंने एक विचित्र समस्या पर ध्यान दिया है जहाँ pushStateइतिहास में कई, डुप्लिकेट प्रविष्टियों (और इससे पहले की प्रविष्टियों को प्रतिस्थापित करें) को धकेल दिया जाएगा।

उदाहरण के लिए, मान लें कि मैं निम्नलिखित (क्रम में) करता हूं:

  1. Index.php को लोड करें (इतिहास होगा: इंडेक्स)

  2. प्रोफाइल पर जाएं। पीपी (इतिहास होगा: प्रोफाइल, इंडेक्स)

  3. Search.php पर जाएँ (इतिहास होगा: खोज, खोज, अनुक्रमणिका)

  4. डैशबोर्ड पर जाएँ

फिर अंत में, यह वही है जो मेरे इतिहास में आएगा (सबसे पुराने सबसे हाल के क्रम में):

डैशबोर्ड
डैशबोर्ड
डैशबोर्ड
सर्च
इंडेक्स

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

अभी तक मेरे पास इतना ही है:

var Traveller = function(){
    this._initialised = false;

    this._pageData = null;
    this._pageRequest = null;

    this._history = [];
    this._currentPath = null;
    this.abort = function(){
        if(this._pageRequest){
            this._pageRequest.abort();
        }
    };
    // initialise traveller (call replaceState on load instead of pushState)
    return this.init();
};

/*1*/Traveller.prototype.init = function(){
    // get full pathname and request the relevant page to load up
    this._initialLoadPath = (window.location.pathname + window.location.search);
    this.send(this._initialLoadPath);
};
/*2*/Traveller.prototype.send = function(path){
    this._currentPath = path.replace(/^\/+|\/+$/g, "");

    // abort any running requests to prevent multiple
    // pages from being loaded into the DOM
    this.abort();

    return this._pageRequest = _ajax({
        url: path,
        dataType: "json",
        success: function(response){
            // render the page to the dom using the json data returned
            // (this part has been skipped in the render method as it
            // doesn't involve manipulating the history object at all
            window.Traveller.render(response);
        }
    });
};
/*3*/Traveller.prototype.render = function(data){
    this._pageData = data;
    this.updateHistory();
};
/*4*/Traveller.prototype.updateHistory = function(){
    /* example _pageData would be:
    {
        "page": {
            "title": "This is a title",
            "styles": [ "stylea.css", "styleb.css" ],
            "scripts": [ "scripta.js", "scriptb.js" ]
        }
    }
    */
    var state = this._pageData;
    if(!this._initialised){
        window.history.replaceState(state, state.title, "/" + this._currentPath);
        this._initialised = true;
    } else {
        window.history.pushState(state, state.title, "/" + this._currentPath);  
    }
    document.title = state.title;
};

Traveller.prototype.redirect = function(href){
    this.send(href);
};

// initialise traveller
window.Traveller = new Traveller();

document.addEventListener("click", function(event){
    if(event.target.tagName === "a"){
        var link = event.target;
        if(link.target !== "_blank" && link.href !== "#"){
            event.preventDefault();
            // example link would be /profile.php
            window.Traveller.redirect(link.href);
        }
    }
});

सभी मदद की सराहना की है,
चीयर्स।


तो आप केवल एक इतिहास परिवर्तन का प्रचार करना चाहते हैं यदि लक्ष्य अंतिम प्रविष्टि से अलग है?
— अलुआन हदद

क्या यह बेतरतीब ढंग से प्रतीत हो रहा है? या विशिष्ट पृष्ठ हमेशा ऐसे होते हैं जो डुप्लिकेट इतिहास प्रविष्टियों का कारण बनते हैं।
— सैमवीके

@AluanHaddad नहीं मैं केवल एक इतिहास परिवर्तन का प्रचार करना चाहता हूं यदि कोई इतिहास परिवर्तन है (यानी जब कोई उपयोगकर्ता साइट के माध्यम से नेविगेट कर रहा है)। एक सामान्य स्थिति में क्या होगा ... इसी तरह (StackOverflow पर खोज करने के लिए इंडेक्स से प्रोफाइल पर जाना) मेरे इतिहास में ठीक वैसा ही लौटेगा
— ग्रोवर।

@SamVK प्रारंभिक लोड अप पृष्ठ (यानी। Index.php) के आसपास नेविगेट करने के बाद, कोई भी बात नहीं करता है, प्रविष्टियां स्वयं डुप्लिकेट होंगी।
— ग्रोवर।

1
खैर, मैं इसके बारे में इतना निश्चित नहीं हूं ताकि टिप्पणियों में लिखा जा सके। मैं देखता हूं कि आप अपने updateHistoryफ़ंक्शन में ब्राउज़र इतिहास की चीजें जोड़ रहे हैं । अब, updateHistoryजब आप ट्रैवलर ( window.Traveller = new Traveller();, constructor-> init-> send-> render-> -> updateHistory) को प्रारंभ कर रहे हैं, तब आपको दो बार कॉल किया जा सकता है , फिर इवेंटलिस्ट redirectसे भी click। मैंने इसका परीक्षण नहीं किया है, केवल जंगली अनुमान लगा रहा हूं, इसलिए इसे टिप्पणी के रूप में जोड़ रहा हूं और उत्तर नहीं।
— अक्षित अरोरा

जवाबों:


3

क्या आपके पास एक onpopstate हैंडलर है?

यदि हाँ, तो वहाँ भी जाँच करें यदि आप इतिहास पर जोर नहीं दे रहे हैं। इतिहास सूची में कुछ प्रविष्टियों को हटा दिया गया है / बदल दिया जा सकता है। वास्तव में, यह एसओ उत्तर देखें :

ध्यान रखें कि history.pushState () एक नया राज्य नवीनतम इतिहास स्थिति के रूप में सेट करता है। और window.onpopstate को कहा जाता है जब आप सेट किए गए राज्यों के बीच नेविगेट (पिछड़े / आगे) करते हैं।

इसलिए window.onpopstate कहते समय धक्का न दें, क्योंकि यह नए राज्य को अंतिम स्थिति के रूप में सेट करेगा और फिर आगे बढ़ने के लिए कुछ भी नहीं है।

जैसा कि आप वर्णन करते हैं, मुझे एक बार ठीक वैसी ही समस्या थी, लेकिन यह वास्तव में बग को समझने की कोशिश करने के लिए मुझे वापस जाने और आगे बढ़ने के कारण हुआ, जो अंततः पॉपस्टैट हैंडलर को ट्रिगर करेगा। उस हैंडलर से, फिर उसे इतिहास कहा जाएगा। इसलिए अंत में, मेरे पास कुछ डुप्लिकेट प्रविष्टियाँ भी थीं, और कुछ गायब थीं, बिना किसी तार्किक विवरण के।

मैंने History.push पर कॉल को हटा दिया, कुछ शर्तों की जाँच के बाद इसे history.replace द्वारा बदल दिया, और इसके बाद यह एक आकर्षण की तरह काम किया :)

EDIT -> टीआईपी

यदि आप यह पता नहीं लगा सकते हैं कि कौन सा कोड इतिहास कह रहा है। PushState:

निम्नलिखित कोड के साथ history.pushState और प्रतिस्थापन कार्यों को अधिलेखित करके देखें:

window.pushStateOriginal = window.history.pushState.bind(window.history);
window.history.pushState = function () {
    var args = Array.prototype.slice.call(arguments, 0);
    let allowPush  = true;
    debugger;
    if (allowPush ) {
        window.pushStateOriginal(...args);
    }
}
//the same for replaceState
window.replaceStateOriginal = window.history.replaceState.bind(window.history);
window.history.replaceState = function () {
    var args = Array.prototype.slice.call(arguments, 0);
    let allowReplace  = true;
    debugger;
    if (allowReplace) {
        window.replaceStateOriginal(...args);
    }
}

फिर हर बार ब्रेकपॉइंट्स को ट्राइगरड किया जाता है, कॉल स्टैक पर एक नज़र डालते हैं।

कंसोल में, यदि आप एक पुशस्टेट को रोकना चाहते हैं, तो बस फिर से शुरू करने से पहले allowPush = false;या प्रवेश करें allowReplace = false;। इस तरह, आप किसी भी history.pushState को याद नहीं करने जा रहे हैं, और ऊपर जाने वाले कोड को ढूंढ सकते हैं :)


मैं करता हूं, लेकिन यह इतिहास को आगे नहीं बढ़ाता या प्रतिस्थापित नहीं करता है: / बस पृष्ठ को
— बढ़ाता है

सचमुच अजीब। निम्नलिखित कोड के साथ history.push फ़ंक्शन को अधिलेखित करने का प्रयास करें: const hP = history.pushState history.pushState = (loc) => {डिबगर; hP (loc)} और history.replaceState के लिए भी ऐसा ही करें। तब हर बार जब ब्रेकपॉइंट्स ट्राइगर होते हैं, तो कॉल स्टैक पर एक नज़र डालते हैं
— बोनजोर123

मैंने कॉल स्टैक की जाँच की और लगता है कि सब कुछ सही ढंग से किया जा रहा है - फिर भी इतिहास काम नहीं करना चाहता है। मोज़िला को सब कुछ इतना मुश्किल क्यों करना चाहिए :(
— ।

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