国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

關(guān)于性能優(yōu)化的那點(diǎn)事——BigRender首屏渲染優(yōu)化

Markxu / 3311人閱讀

摘要:首屏渲染優(yōu)化背景一個(gè)龐大的頁(yè)面有時(shí)我們并不會(huì)滾動(dòng)去看下面的內(nèi)容這樣就造成了非首屏部分的渲染這些無(wú)用的渲染不僅包括圖片還包括其他元素甚至一些某些根據(jù)模塊請(qǐng)求比如理論上每增加一個(gè)都會(huì)增加渲染的時(shí)間并且影響著頁(yè)面打開的加載速度這時(shí)就需要一種辦法使

BigRender首屏渲染優(yōu)化 背景

一個(gè)龐大的頁(yè)面, 有時(shí)我們并不會(huì)滾動(dòng)去看下面的內(nèi)容, 這樣就造成了非首屏部分的渲染, 這些無(wú)用的渲染不僅包括圖片還包括其他DOM元素, 甚至一些js/css(某些js/css根據(jù)模塊請(qǐng)求,比如ajax), 理論上每增加一個(gè)DOM, 都會(huì)增加渲染的時(shí)間, 并且影響著頁(yè)面打開的加載速度.這時(shí)就需要一種辦法使得html, js, css實(shí)現(xiàn)按需加載.

案例

新浪, 美團(tuán), 途牛旅行網(wǎng), 360網(wǎng)址導(dǎo)航, 淘寶商品詳情頁(yè)等等.查看它們的源代碼(ctrl+u), ctrl+f 搜索 textarea 關(guān)鍵字, 很容易可以看到一些被textarea標(biāo)簽包裹的HTML代碼.

原理

使用textarea標(biāo)簽包裹HTML/JS/CSS代碼, 當(dāng)作textarea的value值, 在頁(yè)面渲染的時(shí)候?qū)嶋H并沒有渲染到DOM樹上, 而是與圖片懶加載類似, 當(dāng)textarea標(biāo)簽出現(xiàn)或即將出現(xiàn)在用戶視野時(shí), 將textarea中的HTML代碼取出, 用innerHTML動(dòng)態(tài)插入到DOM樹中, 如有必要使用正則取出js/css代碼動(dòng)態(tài)執(zhí)行.

玉伯指出:
頁(yè)面下載完畢后, 要經(jīng)過(guò)Tokenization - Tree Construction - Rendering. 要讓首屏盡快出來(lái), 得給瀏覽器減輕渲染首屏的工作量. 可以從兩方面入手:

減少DOM節(jié)點(diǎn)數(shù), 節(jié)點(diǎn)數(shù)越少, 意味著Tokenization, Rendering等操作耗費(fèi)的時(shí)間越少.(對(duì)于典型的淘寶商品詳情頁(yè),經(jīng)測(cè)試發(fā)現(xiàn), 每增加一個(gè)DOM節(jié)點(diǎn), 會(huì)導(dǎo)致首屏渲染時(shí)間延遲約0.5ms)

減少腳本執(zhí)行時(shí)間. 腳本執(zhí)行和UI Update共享一個(gè)thread, 腳本耗的時(shí)間約少, UI Update就能越發(fā)提前.

優(yōu)點(diǎn)
* 減少首屏DOM渲染,
* 加快首屏加載速度
* 分塊加載js/css(使用于模塊區(qū)分度高的網(wǎng)站)
缺點(diǎn)
* 需要更改DOM結(jié)構(gòu)
* 可能引起一些重排和重繪
* 沒有開啟js功能的用戶將看不到延遲加載的內(nèi)容
* 額外性能損耗(渲染前的textarea里面的html代碼,在服務(wù)端把html代碼保存在隱藏的textarea里面
  所以在服務(wù)端會(huì)把html代碼轉(zhuǎn)義, 尖括號(hào)等都被轉(zhuǎn)義了, 會(huì)增加服務(wù)端的壓力, 而且這個(gè)改造只是前端
  的渲染, 服務(wù)器依舊是一次計(jì)算所有的數(shù)據(jù), 輸出所有的數(shù)據(jù). 一般使用都是由后端拼接成html字符串
  然后塞入textarea標(biāo)簽, 吐給前端)
* 不利于SEO(在搜索引擎看來(lái)網(wǎng)頁(yè)也缺少了關(guān)鍵的DOM節(jié)點(diǎn), 原本信息量豐富的網(wǎng)頁(yè)內(nèi)容被放入單個(gè)的
  
    
js:
;(function(win, doc) {

    // 兼容低版本 IE
    Function.prototype.bind = Function.prototype.bind || function(context) {
        var that = this;
        return function() {
            return that.apply(context, arguments);
        };
    };

    // 工具方法 begin
    var Util = {
        getElementsByClassName: function(cls) {
            if (doc.getElementsByClassName) {
                return doc.getElementsByClassName(cls);
            }

            var o = doc.getElementsByTagName("*"),
                rs = [];

            for (var i = 0, t, len = o.length; i < len; i++) {
                (t = o[i]) && ~t.className.indexOf(cls) && rs.push(t);
            }

            return rs;
        },
        addEvent: function(ele, type, fn) {
            ele.attachEvent ? ele.attachEvent("on" + type, fn) : ele.addEventListener(type, fn, false);
        },
        removeEvent: function(ele, type, fn) {
            ele.detachEvent ? ele.detachEvent("on" + type, fn) : ele.removeEventListener(type, fn, false);
        },
        getPos: function(ele) {
            var pos = {
                x: 0,
                y: 0
            };

            while (ele.offsetParent) {
                pos.x += ele.offsetLeft;
                pos.y += ele.offsetTop;
                ele = ele.offsetParent;
            }

            return pos;
        },
        getViewport: function() {
            var html = doc.documentElement;

            return {
                w: !window.innerWidth ? html.clientHeight : window.innerWidth,
                h: !window.innerHeight ? html.clientHeight : window.innerHeight
            };
        },
        getScrollHeight: function() {
            html = doc.documentElement, bd = doc.body;
            return Math.max(window.pageYOffset || 0, html.scrollTop, bd.scrollTop);
        },
        getEleSize: function(ele) {
            return {
                w: ele.offsetWidth,
                h: ele.offsetHeight
            };
        }
    };
    // 工具方法 end

    var Datalazyload = {
        threshold: 0,  // {number} 閾值,預(yù)加載高度,單位(px)
        els: null,  // {Array} 延遲加載元素集合(數(shù)組)
        fn: null,   // {Function} scroll、resize、touchmove 所綁定方法,即為 pollTextareas()

        evalScripts: function(code) {
            var head = doc.getElementsByTagName("head")[0],
                js = doc.createElement("script");

            js.text = code;
            head.insertBefore(js, head.firstChild);
            head.removeChild(js);
        },

        evalStyles: function(code) {
            var head = doc.getElementsByTagName("head")[0],
                css = doc.createElement("style");

            css.type = "text/css";

            try {
                css.appendChild(doc.createTextNode(code));
            } catch (e) {
                css.styleSheet.cssText = code;
            }

            head.appendChild(css);
        },

        extractCode: function(str, isStyle) {
            var cata = isStyle ? "style" : "script",
                scriptFragment = "<" + cata + "[^>]*>([Ss]*?)",
                matchAll = new RegExp(scriptFragment, "img"),
                matchOne = new RegExp(scriptFragment, "im"),
                matchResults = str.match(matchAll) || [],
                ret = [];

            for (var i = 0, len = matchResults.length; i < len; i++) {
                var temp = (matchResults[i].match(matchOne) || [ "", "" ])[1];
                temp && ret.push(temp);
            }
            return ret;
        },

        decodeHTML: function(str) {
            return str.replace(//g, ">").replace(/&/g, "&");
        },

        insert: function(ele) {
            var parent = ele.parentNode,
                txt = this.decodeHTML(ele.innerHTML),
                matchStyles = this.extractCode(txt, true),
                matchScripts = this.extractCode(txt);
            // console.log(txt)
            console.log(matchStyles);
            console.log(matchScripts);

            parent.innerHTML = txt
                .replace(new RegExp("]*>([Ss]*?)", "img"), "")
                .replace(new RegExp("]*>([Ss]*?)", "img"), "");

            if (matchStyles.length) {
                for (var i = matchStyles.length; i--;) {
                    this.evalStyles(matchStyles[i]);
                }
            }


            // 如果延遲部分需要做 loading 效果
            parent.className = parent.className.replace("loading", "");

            if (matchScripts.length) {
                for (var i = 0, len = matchScripts.length; i < len; i++) {
                    this.evalScripts(matchScripts[i]);
                }
            }
        },

        inView: function(ele) {
          var top = Util.getPos(ele).y
            , viewVal = Util.getViewport().h
            , scrollVal = Util.getScrollHeight()
            , eleHeight = Util.getEleSize(ele).h;

          if (top >= scrollVal  - eleHeight - this.threshold && top <= scrollVal + viewVal + this.threshold) {
            return true;
          }

          return false;
        },

        pollTextareas: function() {
            // 需延遲加載的元素已經(jīng)全部加載完
            if (!this.els.length) {
                Util.removeEvent(window, "scroll", this.fn);
                Util.removeEvent(window, "resize", this.fn);
                Util.removeEvent(doc.body, "touchMove", this.fn);
                return;
            }

            // 判斷是否需要加載
            for (var i = this.els.length; i--; ) {
                var ele = this.els[i];

                if (!this.inView(ele)) {
                    continue;
                }

                this.insert(ele);
                this.els.splice(i, 1);
            }
        },

        init: function(config) {
            var cls = config.cls;
            this.threshold = config.threshold ? config.threshold : 0;

            this.els = Array.prototype.slice.call(Util.getElementsByClassName(cls));
            this.fn = this.pollTextareas.bind(this);

            this.fn();
            Util.addEvent(window, "scroll", this.fn);
            Util.addEvent(window, "resize", this.fn);
            Util.addEvent(doc.body, "touchMove", this.fn);
        }
    };

    win["datalazyload"] = Datalazyload;
})(window, document);


// demo:
datalazyload.init({
    cls: "datalazyload",    // 需要延遲加載的類,即 textarea 的類名
    threshold: 100          // 距離底部多高,進(jìn)行延遲加載的閾值
});

參考原文

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/80216.html

相關(guān)文章

  • 關(guān)于性能優(yōu)化的那點(diǎn)事——函數(shù)節(jié)流

    摘要:函數(shù)節(jié)流背景中的函數(shù)大多數(shù)情況下都是由用戶主動(dòng)調(diào)用觸發(fā)的除非是函數(shù)本身的實(shí)現(xiàn)不合理否則一般不會(huì)遇到跟性能相關(guān)的問(wèn)題但在少數(shù)情況下函數(shù)的觸發(fā)不是由用戶直接控制的在這些場(chǎng)景下函數(shù)可能被非常頻繁調(diào)用而造成大的性能問(wèn)題場(chǎng)景事件事件滾動(dòng)事件共同的特征 函數(shù)節(jié)流 背景 javascript中的函數(shù)大多數(shù)情況下都是由用戶主動(dòng)調(diào)用觸發(fā)的, 除非是函數(shù)本身的實(shí)現(xiàn)不合理, 否則一般不會(huì)遇到跟性能相關(guān)的問(wèn)題...

    khlbat 評(píng)論0 收藏0
  • 關(guān)于性能優(yōu)化的那點(diǎn)事——函數(shù)防抖

    摘要:函數(shù)防抖場(chǎng)景假設(shè)網(wǎng)站有個(gè)搜索框用戶輸入文本我們會(huì)自動(dòng)聯(lián)想匹配出一些結(jié)果供用戶選擇我們可能首先想到的做法就是監(jiān)聽事件然后異步查詢結(jié)果但是如果用戶快速的輸入了一串字符假設(shè)是個(gè)字符那么就會(huì)在瞬間觸發(fā)次請(qǐng)求這無(wú)疑不是我們想要的我們想要的是用戶停止輸 函數(shù)防抖 場(chǎng)景 假設(shè)網(wǎng)站有個(gè)搜索框, 用戶輸入文本我們會(huì)自動(dòng)聯(lián)想匹配出一些結(jié)果供用戶選擇,我們可能首先想到的做法就是監(jiān)聽keypress事件, 然...

    Stardustsky 評(píng)論0 收藏0
  • 查漏補(bǔ)缺 - 收藏集 - 掘金

    摘要:醞釀許久之后,筆者準(zhǔn)備接下來(lái)撰寫前端面試題系列文章,內(nèi)容涵蓋瀏覽器框架分鐘搞定常用基礎(chǔ)知識(shí)前端掘金基礎(chǔ)智商劃重點(diǎn)在實(shí)際開發(fā)中,已經(jīng)非常普及了。 這道題--致敬各位10年阿里的前端開發(fā) - 掘金很巧合,我在認(rèn)識(shí)了兩位同是10年工作經(jīng)驗(yàn)的阿里前端開發(fā)小伙伴,不但要向前輩學(xué)習(xí),我有時(shí)候還會(huì)選擇另一種方法逗逗他們,拿了網(wǎng)上一道經(jīng)典面試題,可能我連去阿里面試的機(jī)會(huì)都沒有,但是我感受到了一次面試1...

    YuboonaZhang 評(píng)論0 收藏0
  • 關(guān)于localStorage面試的那點(diǎn)事

    摘要:已經(jīng)超出本地存儲(chǔ)限定大小可進(jìn)行超出限定大小之后的操作,如下面可以先清除記錄,再次保存面試官一波素質(zhì)三連對(duì)于只是會(huì)使用的同學(xué)來(lái)說(shuō),肯定是不得其解的。 最近面試的時(shí)候關(guān)于html5API總會(huì)被問(wèn)到localStorage的問(wèn)題, 對(duì)于一般的問(wèn)題很簡(jiǎn)單,無(wú)非就是 localStorage、sessionStorage和cookie這三個(gè)客戶端緩存的區(qū)別 localStorage的API,g...

    timger 評(píng)論0 收藏0
  • 關(guān)于var,let,const的那點(diǎn)事

    摘要:一直使用定義變量,的出現(xiàn)給變量定義增加了兩個(gè)大將,。聲明的變量,塊作用域,不重復(fù)聲明覆蓋,限制了變量的作用域,保證變量不會(huì)去污染全局變量,所以盡量將改為用。 一直使用var定義變量,ES6的出現(xiàn)給變量定義增加了兩個(gè)大將let,const。那它們有什么區(qū)別呢。 1、const關(guān)鍵字它的作用就是定義一個(gè)常量,一旦定義無(wú)法更改,不能重復(fù)聲明覆蓋; showImg(https://segmen...

    KavenFan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<