6

पर लोड होने के तरीके को कैसे बदला जाए, मैं अपनी साइट पर ए/बी परीक्षण करता हूं और मेरा अधिकांश काम जेएस फ़ाइल में है जो किसी और चीज से पहले पृष्ठ के शीर्ष पर लोड होता है लेकिन jQuery के लोड होने के बाद जो कभी-कभी काम में आता है।एचटीएमएल सामग्री को पेज

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

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

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

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

तो क्या म्यूटेशन ऑब्सर्वर का उपयोग एचटीएमएल सामग्री को ऑन-द-फ्लाई बदलने के लिए करना संभव है क्योंकि पृष्ठ लोड/पार्स किया जा रहा है?

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

सादर, निक

+0

हैलो @ wOxxOm - सबसे पहले, आपको रविवार को चिंता करने के लिए क्षमा करें लेकिन आपके उत्तर के लिए धन्यवाद। दूसरा, क्या आप साझा कर सकते हैं विशेष रूप से आप किस बारे में चिंतित हैं? तीसरा, एक से दस के बीच पैमाने पर, आप कितने चिंतित थे? और आखिरकार, यदि आपके पास आसानी से Google के उदाहरणों में से एक से एक उपयुक्त संसाधन है, तो शायद आप इसे एक उत्तर के रूप में साझा कर सकते हैं और यदि यह सही है तो मैं इस तरह चिह्नित करूंगा। आपकी सहायता के लिए धन्यवाद. –

+0

मुझे इसके उत्तर के बारे में सुनने में दिलचस्पी होगी, मैं इसे बहुत पहले नहीं देख रहा था, लेकिन इसे समाप्त करने के लिए समाप्त हो गया क्योंकि समय नहीं था या इसे पूरा करने की आवश्यकता नहीं थी। – osouthgate

+0

आपकी प्रतिक्रिया @wOxxOm के लिए धन्यवाद - वास्तव में बहुत उपयोगी है हालांकि पहले दो पृष्ठों पर किसी भी लिंक ने वैध उत्तर प्रदान नहीं किया है, हालांकि कुछ अच्छे लेख हैं। यदि आप स्टैक ओवरफ्लो पर डुप्लिकेट थ्रेड से अवगत हैं, तो हम इस प्रश्न को वैध उत्तर के रूप में लिंक कर सकते हैं यदि इसे वैध डुप्लिकेट माना जाता है।हालांकि आपका समय बर्बाद करने के लिए खेद है, आपको जवाब देने से रोकने के लिए बहुत स्वागत है और शायद कहीं और चिंताजनक प्रयासों पर ध्यान केंद्रित करें। मैं आपकी भलाई की कामना करता हूं। –

उत्तर

9

The docs on MDN एक सामान्य अधूरा उदाहरण है और प्रदर्शन नहीं है सामान्य कठिनाइयों। Mutation summary लाइब्रेरी मानव-अनुकूल आवरण प्रदान करती है, लेकिन सभी रैपरों की तरह यह ओवरहेड जोड़ती है। Performance of MutationObserver to detect nodes in entire DOM देखें।

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

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

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

अतिरिक्त नोड्स की निष्क्रिय गणना।

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

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') 
      ); 
    ); 
} 

अतिरिक्त नोड्स की कुशल गणना।

अब कठिन हिस्सा है। एक उत्परिवर्तन रिकॉर्ड में नोड्स कंटेनर हो सकते हैं जबकि एक पृष्ठ लोड किया जा रहा है (पूरे साइट हेडर ब्लॉक की तरह इसके सभी तत्वों को केवल एक जोड़ा नोड के रूप में रिपोर्ट किया गया है): विनिर्देश doesn't require प्रत्येक जोड़ा नोड अलग-अलग सूचीबद्ध होने के लिए, इसलिए हमें 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 और filter और ES2015 for (val of array) तुलना में बहुत धीमी हैं। Performance of MutationObserver to detect nodes in entire DOM देखें।

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

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

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

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'); 
      } 
     } 
    } 
} 
+0

अच्छा, धन्यवाद। मैं इस शाम को देख लूंगा। अच्छी चीज़। –

+0

हाय, इस उत्तर के लिए फिर से धन्यवाद ... मैं अपने सिर को ट्रीवाल्कर के उपयोग के आसपास लाने की कोशिश कर रहा हूं - आपने कहा है कि यह किसी भी घटना श्रोताओं को एच 1 टैग के उप-तत्वों से जुड़ा हुआ है और इसलिए यह ट्रिगर नहीं करता है एक नया उत्परिवर्तन, लेकिन क्या मैं ट्रीवाल्कर के बिना टेक्स्ट नोड के मूल्य को बदलकर सोचने में गलत हूं, यह किसी भी घटना के संचालन के कारण किसी भी नए उत्परिवर्तन को ट्रिगर नहीं करेगा और न ही यह किसी भी ईवेंट हैंडलरों में हस्तक्षेप करेगा - हम बस बदल रहे हैं textNode.nodeValue? चीयर्स –

+0

अनुमान लगाना उन्हें रिकर्सिवली की गणना के बिना जो चाइल्ड नोड सही पाठ नोड है का प्रयास करें: 1) '

पहले दूसरा तीसरे

' और 2) '

पहले दूसरा तीसरे

' – wOxxOm

1

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

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

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

    //Do something 
    } 
}, 50); 

आप एक कड़ाके की धूप चयनकर्ता का उपयोग करके किसी भी डोम तत्व प्राप्त कर सकते हैं जैसे आप document.querySelector, जो कभी कभी केवल एक चीज है साथ jQuery में आप के लिए एक पुस्तकालय की आवश्यकता हो सकती वैसे भी।

वास्तव में हम अपना काम है कि हम एक निर्माण प्रक्रिया और a module library जो एक समारोह बुलाया भी शामिल है पर इतनी बार ऐसा करने जब जो आप के लिए क्या चाहिए, तो करता है। यह विशेष फ़ंक्शन jQuery के साथ-साथ तत्व के लिए जांचता है, लेकिन लाइब्रेरी को संशोधित करने के लिए लाइब्रेरी को संशोधित करना मुश्किल होगा (हम jQuery पर भरोसा करते हैं क्योंकि यह पर हमारे ग्राहक की साइटों के पर है और हम इसे बहुत सारी सामग्री के लिए उपयोग करते हैं) ।

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

+0

इस @ बेउ के लिए धन्यवाद - मैंने पहले इस पैटर्न का उपयोग किया है लेकिन अवसरों पर यह बुलेट प्रूफ नहीं रहा है। मैं इसे इस स्थिति में एक और जाने दूंगा और रिपोर्ट करूंगा, हालांकि, मुझे लगता है कि मैं प्राकृतिक ब्राउज़र कार्यक्रमों का उपयोग करना पसंद कर रहा हूं, भले ही यह लक्षित दर्शकों को थोड़ा कम कर दे। (jQuery - हम विस्फोट नहीं कर रहे हैं कि हमारे स्निपेट के साथ, हमने पहले से लोड किया है)। चीयर्स। –

+0

FYI 50ms पृष्ठों को पेंट करने के लिए ब्राउज़र द्वारा 60fps पर 3 फ्रेम है। यह एक बड़ा अंतर है (वास्तव में 1 फ्रेम अंतर भी ध्यान देने योग्य है)। और यहां तक ​​कि एक बड़ी समस्या भी है: सीपीयू-गहन जटिल पृष्ठ लोड के दौरान टाइमर कॉलबैक को यादृच्छिक रूप से देरी हो सकती है (मैंने 500ms देरी देखी है)। – wOxxOm

संबंधित मुद्दे