javascript - पृष्ठ पर लोड होते ही HTML सामग्री कैसे बदलें




ab-testing mutation-observers (2)

मैं हमारी साइट पर ए / बी टेस्टिंग करता हूं और मैं अपना ज्यादातर काम एक जेएस फाइल में करता हूं, जो पेज के शीर्ष पर लोड होता है, इससे पहले कि कुछ और प्रदान किया जाए, लेकिन jQuery लोड होने के बाद जो समय पर काम आता है।

H1 टैग को बदलने का एक बहुत ही सरल उदाहरण लेते हुए, मैं आमतौर पर H1 अपारदर्शिता को 0 पर सेट करने के लिए सिर में एक शैली इंजेक्ट करूँगा और फिर DOMContentLoaded पर, मैं H1 सामग्री को हेरफेर करूँगा और फिर 1. करने के लिए अस्पष्टता सेट करूँगा। परिवर्तन होने से पहले पुरानी सामग्री के फ्लैश से बचने के लिए - पूरी वस्तु को छिपाना आंख पर अधिक सुंदर है।

मैंने MutationObserver API देखना शुरू कर दिया है। मैंने ओवरले डायलॉग बॉक्स में सामग्री बदलने से पहले इसका उपयोग किया है जो कि उपयोगकर्ता खोल सकता है जो काफी शांत दृष्टिकोण प्रतीत होता है और मैं सोच रहा हूं कि क्या कोई दस्तावेज़ को सुनने के लिए किसी MutationObserver का उपयोग करने में कामयाब रहा है क्योंकि यह पहली बार लोड हो रहा है / पहले रेंडर करने और DOMContentLoaded से पहले दस्तावेज़ में पार्स करना और परिवर्तन करना

यह दृष्टिकोण तब मुझे H1 सामग्री को छिपाने के बिना, इसे बदलने, फिर इसे दिखाने के लिए बदलने देगा।

मैंने प्रयास किया है, लेकिन अभी तक असफल रहा है और अभी-अभी-तक म्यूटेशन इवेंट के बारे में पढ़ना समाप्त कर दिया है और सोच रहा हूं कि क्या मैं कुछ ऐसा करने की कोशिश कर रहा हूं जो अभी संभव नहीं है। हालाँकि, हमने (मुझ पर नहीं) मंगल पर एक रोबोट लगाने में कामयाबी हासिल की है इसलिए मुझे उम्मीद है कि मैं इसे हल कर सकता हूं।

तो क्या यह संभव है कि पृष्ठ लोड होने / पार्स होने के साथ ही HTML कंटेंट को बदलने के लिए MutationObservers का उपयोग किया जाए?

किसी भी मदद या किसी भी संकेत के लिए धन्यवाद।

सादर, निक


मैं एक जीवित के लिए ए / बी परीक्षण करता हूं और मैं अच्छे परिणामों के साथ काफी बार MutationObservers का उपयोग करता हूं, लेकिन कहीं अधिक बार मैं सिर्फ लंबे समय तक मतदान करता हूं, जो वास्तव में अधिकांश 3 पार्टी प्लेटफॉर्म हुड के तहत करते हैं जब आप उनके WYSIWRG का उपयोग करते हैं (या कभी-कभी यहां तक ​​कि उनके कोड संपादक)। 50 मिलीसेकंड लूप पृष्ठ को धीमा नहीं करना चाहिए या FOUC का कारण नहीं बनना चाहिए।

मैं आमतौर पर एक साधारण पैटर्न का उपयोग करता हूं जैसे:

var poller = setInterval(function(){
  if(document.querySelector('#question-header') !== null) {
    clearInterval(poller);

    //Do something
  }
}, 50);

आप डॉक्यूमेंट के साथ jQuery में sizzle चयनकर्ता का उपयोग करके कोई भी DOM तत्व प्राप्त कर सकते हैं।

वास्तव में हम अपनी नौकरी पर ऐसा अक्सर करते हैं कि हमारे पास एक निर्माण प्रक्रिया और एक मॉड्यूल लाइब्रेरी है जिसमें एक फ़ंक्शन शामिल होता है जिसे व्हेन कहा जाता है जो वास्तव में वही दिखता है जो उसे ढूंढता है। यह विशेष रूप से फ़ंक्शन jQuery के साथ-साथ तत्व के लिए जाँच करता है, लेकिन यह पुस्तकालय को संशोधित करने के लिए तुच्छ होगा कि jQuery पर भरोसा न करें (हम jQuery पर भरोसा करते हैं क्योंकि यह हमारे ग्राहक की अधिकांश साइटों पर है और हम इसे बहुत सारे सामान के लिए उपयोग करते हैं)।

तीसरे पक्ष के परीक्षण प्लेटफार्मों और जावास्क्रिप्ट पुस्तकालयों की बात करें, तो वहां बहुत सारे प्लेटफार्मों के कार्यान्वयन पर निर्भर करता है (जैसे ऑप्टिमाइज़ली, क्यूबिट, और मुझे लगता है कि मोनेटेट) jQuery के एक संस्करण को बंडल करता है (कुछ समय नीचे ट्रिम हो जाता है जो आपके कोड को निष्पादित करते समय तुरंत उपलब्ध होता है। , तो यह देखने के लिए कुछ है कि क्या आप तीसरे पक्ष के मंच का उपयोग कर रहे हैं।


MDN पर डॉक्स एक सामान्य अधूरा उदाहरण है और आम नुकसान नहीं दिखाते हैं। म्यूटेशन सारांश लाइब्रेरी मानव-अनुकूल आवरण प्रदान करती है, लेकिन सभी आवरणों की तरह यह ओवरहेड जोड़ता है। पूरे DOM में नोड्स का पता लगाने के लिए MutationObserver का प्रदर्शन देखें।

पर्यवेक्षक बनाएं और शुरू करें।

चलो एक पुनरावर्ती दस्तावेज़ चौड़ा MutationObserver का उपयोग करें जो सभी जोड़े / हटाए गए नोड्स की रिपोर्ट करता है।

var observer = new MutationObserver(onMutation);
observer.observe(document, {
    childList: true, // report added/removed nodes
    subtree: true,   // observe any descendant elements
});

जोड़ा नोड्स के Naive गणन।

बहुत बड़े / जटिल पृष्ठों को लोड करना धीमा कर देता है, प्रदर्शन देखें।
कभी-कभी माता-पिता कंटेनर में जमा हुए H1 तत्वों को याद करते हैं, अगला भाग देखें।

function onMutation(mutations) {
    mutations.forEach(mutation, mutation =>
        Array.prototype
            .filter.call(mutation.addedNodes, added =>
                added.localName == 'h1' && added.textContent.match(/foo/)
            ).forEach(h1 =>
                h1.innerHTML = h1.innerHTML.replace(/foo/, 'bar')
            );
    );
}

जोड़ा नोड्स के कुशल गणना।

अब कठिन हिस्सा। एक म्यूटेशन रिकॉर्ड में नोड्स कंटेनर हो सकते हैं जबकि एक पेज लोड किया जा रहा है (जैसे पूरी साइट हेडर ब्लॉक अपने सभी तत्वों के साथ, जो केवल एक जोड़ा नोड के रूप में रिपोर्ट किया गया है): विनिर्देश में प्रत्येक जोड़े गए नोड को व्यक्तिगत रूप से सूचीबद्ध करने की आवश्यकता नहीं है , इसलिए हम ' आपको प्रत्येक तत्व का उपयोग करना होगा querySelectorAll (अत्यंत धीमा) या getElementsByTagName (अत्यंत तेज़) का उपयोग करना होगा।

function onMutation(mutations) {
    for (var i = 0, len = mutations.length; i < len; i++) {
        var added = mutations[i].addedNodes;
        for (var j = 0, lenAdded = added.length; j < lenAdded; j++) {
            var node = added[j];
            var found;
            if (node.localName === 'h1') {
                found = [node];
            } else if (node.children && node.children.length) {
                found = node.getElementsByTagName('h1');
            } else {
                continue;
            }
            for (var k = 0, lenFound = found.length; k < lenFound; k++) {
                var h1 = found[k];
                if (!h1.parentNode || !h1.textContent.match(/foo/)) {
                    // either removed in another mutation or has no text to replace
                    continue;
                }
                var walker = document.createTreeWalker(h1, NodeFilter.SHOW_TEXT);
                while (walker.nextNode()) {
                    var textNode = walker.currentNode;
                    var text = textNode.nodeValue;
                    if (text.match(/foo/)) {
                        textNode.nodeValue = text.replace(/foo/, 'bar');
                    }
                }
            }
        }
    }
}

लूप के for बदसूरत वेनिला क्यों? क्योंकि forEach and filter और ES2015 for (val of array) तुलना में बहुत धीमे हैं। पूरे DOM में नोड्स का पता लगाने के लिए MutationObserver का प्रदर्शन देखें।

TreeWalker क्यों? उप-तत्वों से जुड़े किसी भी घटना श्रोताओं को संरक्षित करने के लिए। केवल Text नोड्स को बदलने के लिए: उनके पास चाइल्ड नोड्स नहीं हैं, और उन्हें बदलने से नया उत्परिवर्तन नहीं होता है क्योंकि हमने childList: true उपयोग किया है childList: true , characterData: true नहीं characterData: true

उत्परिवर्तन उत्परिवर्तन के बिना लाइव HTMLCollection के माध्यम से अपेक्षाकृत दुर्लभ तत्वों को संसाधित करना।

इसलिए हम एक ऐसे तत्व की तलाश करते हैं, जिसका उपयोग शायद ही कभी किया जाता है जैसे कि H1 टैग, या IFRAME, आदि। इस मामले में हम पर्यवेक्षक कॉलबैक को सरल कर सकते हैं और स्वचालित रूप से अपडेट किए गए HTMLCollection के साथ getElementsByGagName द्वारा लौटा सकते हैं।

var h1s = document.getElementsByTagName('h1');
function onMutation(mutations) {
    if (mutations.length == 1) {
        // optimize the most frequent scenario: one element is added/removed
        var added = mutations[0].addedNodes[0];
        if (!added || (added.localName !== 'h1' && !added.children.length)) {
            // so nothing was added or non-H1 with no child elements
            return;
        }
    }
    // H1 is supposed to be used rarely so there'll be just a few elements
    for (var i = 0, len = h1s.length; i < len; i++) {
        var h1 = h1s[i];
        if (!h1.textContent.match(/foo/)) {
            continue;
        }
        var walker = document.createTreeWalker(h1, NodeFilter.SHOW_TEXT);
        while (walker.nextNode()) {
            var textNode = walker.currentNode;
            var text = textNode.nodeValue;
            if (text.match(/foo/)) {
                textNode.nodeValue = text.replace(/foo/, 'bar');
            }
        }
    }
}





optimizely