长列表优化之滚动替换数据方案小记

  最近项目中要用到比较长的列表,在浏览器中打开渲染时比较慢,并占用了较多内存,于是就同事就建议尽量减少节点,在滚动时只是替换数据,于是就决定试试这种方法。

  首先要做的就是添加拖动滚动条时的事件,另外由于UE要求对滚动条进行美化,于是就选用了jscrollpane这个jQuery滚动条插件,主页是:http://jscrollpane.kelvinluck.com/

  基本要求是表头固定,内容可滚动,滚动时只是替换数据,不增减节点。由于要出现滚动条,所以要添加一个空的节点来占位,所以DEMO的HTML结构如下:

<h3>DEMO</h3>

<div class="bookList">

    <table class="bookList_head">

        <thead>

            <tr>

                <th class="book_title">Title</th>

                <th class="book_time">Time</th>

                <th class="book_author">Author</th>

                <th class="book_prize">Prize</th>

            </tr>

        </thead>

    </table>

    <div class="scroll-pane">

        <div id="emptyContainer" class="emptyContainer"></div>

        <table class="bookList_body">

            <tbody id="bookContent">

            </tbody>

        </table>

    </div>

</div>

  然后要做的就是用测试数据填充列表,并给占位节点设置高度,JS代码如下:

    var bookData = [],

        bookMap = [],

        bookCount = 1000,

        showCount = 10,

        bookListBodyNode = $(".bookList_body"),

        bookContentNode = $("#bookContent"),

        itemHeight = 0,

        oFragment = document.createDocumentFragment();



    var emptyContainerNode = $("#emptyContainer");

    for(var i=0;i<bookCount;i++){

        bookData.push({

            "title":"JavaScript高级程序设计第"+(i+1)+"版",

            "time":"2013-1-27",

            "author":"佚名"+i,

            "prize":(i%50+1)+".00"

        });

    }

    

    for(i=0;i<showCount;i++){

        var bookItem = $("<tr></tr>"),

            bookItem_title = $("<td class=\"book_title\">" + bookData[i].title + "</td>"),

            bookItem_time = $("<td class=\"book_time\">" + bookData[i].time + "</td>"),

            bookItem_author = $("<td class=\"book_author\">" + bookData[i].author + "</td>"),

            bookItem_prize = $("<td class=\"book_prize\">" + bookData[i].prize + "</td>");

        bookItem.append(bookItem_title)

            .append(bookItem_time)

            .append(bookItem_author)

            .append(bookItem_prize);

        bookMap[i] = bookItem;

        oFragment.appendChild(bookItem[0]);

    }

    bookContentNode[0].appendChild(oFragment);

    itemHeight = parseInt(bookMap[0].height());

    emptyContainerNode.css("height", bookCount * itemHeight);

  下一步就是给class为scroll-pane的节点应用jScrollPane插件添加滚动条,同是要添加滚动条滚动时的事件,代码如下:

$('.scroll-pane').bind('jsp-scroll-y',function(event, scrollPositionY, isAtTop, isAtBottom){

        bookListBodyNode.css("top",scrollPositionY);

        replaceBooklistData(scrollPositionY);

    }

).jScrollPane();



function replaceBooklistData(scrollPositionY){

    var beginIndex = Math.round(scrollPositionY / itemHeight);

    for(var i=0;i<showCount;i++){

        var bookItem = bookMap[i],

            bookItem_title = bookItem.find(".book_title"),

            bookItem_time = bookItem.find(".book_time"),

            bookItem_author = bookItem.find(".book_author"),

            bookItem_prize = bookItem.find(".book_prize");

        bookItem_title.html(bookData[i+beginIndex].title);

        bookItem_time.html(bookData[i+beginIndex].time);

        bookItem_author.html(bookData[i+beginIndex].author);

        bookItem_prize.html(bookData[i+beginIndex].prize);

    }

}

  最后还要引入一个鼠标滚动时的插件mousewheel,全部代码如下:

<!DOCTYPE html>

<html>

    <head>

        <meta charset="utf-8" />

        <title>Table Body Scroll Demo</title>

        <link type="text/css" href="style/jquery.jscrollpane.css" rel="stylesheet" media="all" />

        <link type="text/css" href="style/demo.css" rel="stylesheet" media="all" />

        <script type="text/javascript" src="script/jquery.js"></script>

        <script type="text/javascript" src="script/jquery.mousewheel.js"></script>

        <script type="text/javascript" src="script/jquery.jscrollpane.min.js"></script>

    </head>

    <body>

        <h3>DEMO</h3>

        <div class="bookList">

            <table class="bookList_head">

                <thead>

                    <tr>

                        <th class="book_title">Title</th>

                        <th class="book_time">Time</th>

                        <th class="book_author">Author</th>

                        <th class="book_prize">Prize</th>

                    </tr>

                </thead>

            </table>

            <div class="scroll-pane">

                <div id="emptyContainer" class="emptyContainer"></div>

                <table class="bookList_body">

                    <tbody id="bookContent">

                    </tbody>

                </table>

            </div>

        </div>

        <script type="text/javascript" id="sourcecode">

            var bookData = [],

                bookMap = [],

                bookCount = 1000,

                showCount = 10,

                bookListBodyNode = $(".bookList_body"),

                bookContentNode = $("#bookContent"),

                itemHeight = 0,

                oFragment = document.createDocumentFragment();

                

            $(function(){

                $('.scroll-pane').bind('jsp-scroll-y',

                    function(event, scrollPositionY, isAtTop, isAtBottom){

                        bookListBodyNode.css("top",scrollPositionY);

                        replaceBooklistData(scrollPositionY);

                    }

                ).jScrollPane();

            });



            loadData();



            function replaceBooklistData(scrollPositionY){

                var beginIndex = Math.round(scrollPositionY / itemHeight);

                for(var i=0;i<showCount;i++){

                    var bookItem = bookMap[i],

                        bookItem_title = bookItem.find(".book_title"),

                        bookItem_time = bookItem.find(".book_time"),

                        bookItem_author = bookItem.find(".book_author"),

                        bookItem_prize = bookItem.find(".book_prize");

                    bookItem_title.html(bookData[i+beginIndex].title);

                    bookItem_time.html(bookData[i+beginIndex].time);

                    bookItem_author.html(bookData[i+beginIndex].author);

                    bookItem_prize.html(bookData[i+beginIndex].prize);

                }

            }



            function loadData(){

                var    emptyContainerNode = $("#emptyContainer");

                for(var i=0;i<bookCount;i++){

                    bookData.push({

                        "title":"JavaScript高级程序设计第"+(i+1)+"",

                        "time":"2013-1-27",

                        "author":"佚名"+i,

                        "prize":(i%50+1)+".00"

                    });

                }

                

                for(i=0;i<showCount;i++){

                    var bookItem = $("<tr></tr>"),

                        bookItem_title = $("<td class=\"book_title\">" + bookData[i].title + "</td>"),

                        bookItem_time = $("<td class=\"book_time\">" + bookData[i].time + "</td>"),

                        bookItem_author = $("<td class=\"book_author\">" + bookData[i].author + "</td>"),

                        bookItem_prize = $("<td class=\"book_prize\">" + bookData[i].prize + "</td>");

                    bookItem.append(bookItem_title)

                        .append(bookItem_time)

                        .append(bookItem_author)

                        .append(bookItem_prize);

                    bookMap[i] = bookItem;

                    oFragment.appendChild(bookItem[0]);

                }

                bookContentNode[0].appendChild(oFragment);

                itemHeight = parseInt(bookMap[0].height()) || 34;//FOR IE7

                emptyContainerNode.css("height", bookCount * itemHeight);

            }

        </script>

    </body>

</html>

  代码中的CSS(除了demo.css)和JS都可以在这里找到:https://github.com/vitch/jScrollPane

   demo.css代码如下:

.bookList{

    width:520px;

    height:364px;

}

.scroll-pane

{

    height:330px;

    overflow: auto;

}

.bookList .bookList_head,.bookList .bookList_body{

    width:100%;

    border-collapse:collapse;

}

.bookList .bookList_body{

    z-index:999;

    position:absolute;

    top:0;

    left:0;

}

.bookList .bookList_head thead{

    background-color:#F2F4F6;

}

.bookList th,.bookList td{

    padding:8px 0px 8px 5px;

    text-align:left;

    border-bottom:1px solid #CCC;

    font-size:14px;

}

.bookList .bookList_body tr:nth-child(even){

    background-color:#F0F0F0;

}

.bookList .bookList_body tr:hover{

    background-color:#CCC;

}

.book_title{

    width:250px;

}

.book_time{

    width:100px;

}

.book_author{

    width:80px;

}

.book_prize{

} 

.emptyContainer{

    width:100%;

    z-index:-1;

}

  初步测试,在IE6/7/8/9、chrome、firefox下均正常显示,如果大家有更好方案,欢迎分享。

你可能感兴趣的:(优化)