ब्राउज़र को जावास्क्रिप्ट में एक सीएसएस परिवर्तन प्रस्तुत करने से रोकें?

मेरे पास कोड का निम्न ब्लॉक है जिसे मुझे जितनी जल्दी हो सके पूरा करने की आवश्यकता है:

//someSpans is an array of spans, with each span containing two child spans inside of it
$.each( someSpans, function (i, span) {
    //Get the span widths, then add them to the style to make them permanent
    var aSpan = span.children[0];
    var bSpan = span.children[1];
    span.style.width = (aSpan.offsetWidth + bSpan.offsetWidth) + 'px';
    aSpan.style.width = aSpan.offsetWidth + 'px';
    bSpan.style.width = bSpan.offsetWidth + 'px';
});

यदि कुछस्पैन एक सरणी है जिसमें 1000 ऑब्जेक्ट्स हैं, तो ऊपर प्रस्तुत किया गया यह लूप 3000 ब्राउज़र रीड्रॉप्स का कारण बनता है, भले ही स्क्रीन पर कुछ भी वास्तव में बदल रहा है, क्योंकि शैली में नई "चौड़ाई" विशेषता मौजूदा "ऑटो" चौड़ाई से मेल खाती है। क्या लूप समाप्त होने तक ब्राउज़र को सीएसएस को फिर से चलाने से रोकने का कोई तरीका है? मुझे लगता है कि यह लूप को पूरा करने में लगने वाले समय को बहुत कम कर देगा।

मुझे लगता है कि मैं requestAnimationFrame कर रहा हूं जो मैं कर रहा हूं खोज रहे हैं, लेकिन शायद मैं आधार से बाहर हूँ।

0
@ मैथलेटिक्स मैं प्रत्येक व्यक्तिगत शब्द को एक छिपी हुई प्रॉक्सी div में अपने स्वयं के काल में एक संतोषजनक div में रख रहा हूं। यह मुझे यह पता लगाने की अनुमति देता है कि किसी भी क्षण में उपयोगकर्ता का माउस किस शब्द/चरित्र पर हो रहा है। जाहिर है जैसे ही उपयोगकर्ता सामग्री बदलता है, परिवर्तनों से मेल खाने के लिए पाठ के पूरे ब्लॉक को राहत दी जानी चाहिए। यही कारण है कि गति बहुत महत्वपूर्ण है।
जोड़ा लेखक AlexZ, स्रोत
@AndrewWalters नहीं, मेरे पास नहीं है, लेकिन यह ठीक वैसे ही लगता है जो मैं ढूंढ रहा हूं।
जोड़ा लेखक AlexZ, स्रोत
@ गीवी, मैंने अभी jquery.each के बिना इसे आजमाया (इसके बजाय लूप के लिए इस्तेमाल किया), और इससे कोई स्पष्ट अंतर नहीं आया। डॉकफ्रैगमेंट के लिए, क्या इसका उपयोग अनिवार्य रूप से एक असुरक्षित दस्तावेज़ ऑब्जेक्ट बनाते हैं, जिसे तब तैयार होने पर मौजूदा दस्तावेज़ में जोड़ा जा सकता है?
जोड़ा लेखक AlexZ, स्रोत
@ गिवी: बस आपको यह बताना चाहता था कि मैं ऑपरेशन की गति को कम करने के लिए दस्तावेज़फ्रेगमेंट्स का उपयोग करने के वैकल्पिक तरीके से गया था। मुझे सही दिशा बताने के लिए धन्यवाद!
जोड़ा लेखक AlexZ, स्रोत
क्या आपने लेआउट थ्रैशिंग पर पढ़ा है? kellegous.com/j/2013/01/26/layout-performance wilsonpage.co.uk/preventing-layout-thrashing
जोड़ा लेखक Andrew Walters, स्रोत
यह पूछने लायक हो सकता है कि आप इसे पहले क्यों कर रहे हैं?
जोड़ा लेखक Mathletics, स्रोत
यदि प्रदर्शन इतना महत्वपूर्ण है कि आप jQuery का उपयोग क्यों करते हैं? शुद्ध जावास्क्रिप्ट के साथ यह बहुत तेज होगा, और यदि आप लूप समाप्त होने से पहले ब्राउज़र प्रतिपादन डीओएम तत्वों को रोकना चाहते हैं तो आप इसे दस्तावेज़फ्रेगमेंट और उसके बाद उन तत्वों को संलग्न करें जहां वे होना चाहिए। Document.createTreeWalker() पर भी देखें
जोड़ा लेखक Givi, स्रोत
हां, jsFiddle देखें
जोड़ा लेखक Givi, स्रोत
या setTimeout jsFiddle के साथ
जोड़ा लेखक Givi, स्रोत

1 उत्तर

जबकि क्यों की टिप्पणियां एक महान बिंदु बनाती हैं, यहां थोड़ा बेहतर उत्तर दिया गया है।

यहां आपकी समस्या का हिस्सा शैली से वैकल्पिक पढ़ता/लिखता है। अर्थात्, span.style.width सेटिंग को अब aSpan.offsetWidth "गंदे" बना दिया गया है और सीएसएस को प्रस्तुत किया जाना चाहिए। हालांकि, इस पर विचार करें:

var aWidth = aSpan.offsetWidth;
var bWidth = bSpan.offsetWidth;
span.style.width = (aWidth + bWidth) + 'px';
aSpan.style.width = aWidth + 'px';
bSpan.style.width = bWidth + 'px';

प्रतिपादन अब प्रति लूप एक बार में कटौती की जाती है। अधिक विशेष रूप से, यह अगले पुनरावृत्ति के कारण अगला पुनरावृत्ति पर ऑफसेट विड्थ पढ़ने में है।

Exercise: While it can make code a little more obtuse, sometimes unnecessarily so, I have sometimes written code like this to loop twice. The first time collects the operations into an array, and the second loop is able to combine all the "setting" operations without accessing any layout values.

MSDN has some great documents on JavaScript performance with the most applicable here being "Managing layout efficiently"

0
जोड़ा