Horizontal data update is not working on scroll

前端 未结 3 2233
被撕碎了的回忆
被撕碎了的回忆 2021-02-20 03:19

I have a big array and I need to render it into a table. Instead of rendering all items I am rendering only few items horizontally and vertically. Then on scroll based on mouse

3条回答
  •  广开言路
    2021-02-20 04:09

    SOLUTION, an conceptual extension to my answer to a similar question

    CODE

    function matrix(data, holder, config) {
        'use strict';
    
        //copy the config, substituting defaults
        config = {
            cellWidth : (config && config.cellWidth) || 150,
            rowHeight : (config && config.rowHeight) || 22,
        };
    
        if (!data) {
            //create 50000x26 array for data
            data = (function (length, depth) {
                var output = new Array(length);
                var startAt;
    
                for (var index = 0; index < length; ++index) {
                    //var startAt = Math.random().toString(36).substring(5);
                    var startAt = index + ':';
                    output[index] = new Array(depth);
    
                    for (var index2 = 0; index2 < depth; ++index2)
                        output[index][index2] = startAt + index2;
                }
    
                return output;
            })(50000, 26);
        }
    
        //guard against 0 length arrays
        if (data.length < 1 || data[0].length < 1)
            return;
    
        var areaForcer = holder.appendChild(holder.ownerDocument.createElement('div'));
    
        var view = null;
        function refreshWindow() {
            //remove old view
            if (view != null)
                view.innerHTML = "";
            //create new view
            else
                view = holder.appendChild(holder.ownerDocument.createElement('div'));
    
            var firstRow = Math.floor(holder.scrollTop / config.rowHeight);
            var lastRow = firstRow + Math.ceil(holder.offsetHeight / config.rowHeight) + 1;
            if (lastRow + 2 > data.length)
                lastRow = data.length - 1;
    
            var firstColumn = Math.floor(holder.scrollLeft / config.cellWidth);
            var lastColumn = firstColumn + Math.ceil(holder.offsetWidth / config.cellWidth) + 1;
            if (lastColumn + 2 > data[0].length)
                lastColumn = data[0].length - 1;
    
            //position view in users face
            view.id = 'view';
            view.style.top = (firstRow * config.rowHeight) + 'px';
            view.style.left = (firstColumn * config.cellWidth) + 'px';
    
            var row;
            var cell;
            //add the rows
            for (var index = firstRow; index <= lastRow; ++index) {
                row = view.ownerDocument.createElement('div');
                row.style.height = config.rowHeight - 2 + 'px';
                view.appendChild(row);
    
                //add the cells
                for (var index2 = firstColumn; index2 <= lastColumn; ++index2) {
                    cell = row.ownerDocument.createElement('div');
                    cell.className = 'listItem';
                    cell.innerHTML = data[index][index2];
                    cell.style.width = config.cellWidth - 2 + 'px';
                    row.appendChild(cell);
                }
            }
    
            console.log('viewing items [' + firstRow + ':' + lastRow + '][' + firstColumn + ':' + lastColumn + ']');
        }
    
        areaForcer.style.height = (data.length * config.rowHeight) + 'px';
        areaForcer.style.width = (data[0].length * config.cellWidth) + 'px';
    
        refreshWindow();
    
        function delayingHandler() {
            //wait for the scroll to finish
            setTimeout(refreshWindow, 10);
        }
    
        if (holder.addEventListener)
            holder.addEventListener('scroll', delayingHandler, false);
        else
            holder.attachEvent('onscroll', delayingHandler);
    }
    
    matrix(null, document.getElementById('listHolder'), false);
    
    html, body {
        width:100%;
        height:100%;
        padding:0;
        margin:0
    }
    
    body{
        overflow:hidden; 
    }
    
    .listItem {
        border : 1px solid gray;
        margin : 1px 0px;
        display : inline-block;
    }
    
    #listHolder {
        position:relative;
        height:100%;
        width:100%;
        background-color:#CCC;
        box-sizing:border-box;
        overflow:auto;
    }
    
    #view {
        position:absolute;
    }
    
    #view, #view * {
        overflow : hidden;
        white-space : nowrap;
    }
    
    #view > div {
        width : 100%;
    }
    

    Just some things to clean up your code:

    • you're not using the object in an OO fashion, no need for new/use the function as a constructor (and if you are going to, start it with a capital)

    • in this day and age the compiler can do a lot of things for us, there's no reason to use names like 'i' or 'j' where 'index' is much more self explanatory, and the if statement was made for what you used the and operator for (!data && /*set data*/, use if (!data) /*set data*/)

    • don't employ anonymous, call-once functions where they're not required, they need to be recompiled each time the parent function runs

    • declare variables outside of loops

    • don't use random() (in this case) unless the code is working, makes it harder to see whats going on

    • personal preference send null to a function instead of undefined and don't name a function $matrix when matrix is just as apt use comments!

    • personal preference unless you know what you're doing, ++x is exactly what you need and x++ is a minor waste of resources

    • because you're using horizontal scroll, forget about hiding the scrollbar

    • start out simple and don't attempt to get the height, just force one. things like detecting height are niceties reserved for working solutions

    • always use proper indentation, even if the if statement can be written on one line. Doesn't matter about your personal preference because you're posting the code online expecting other people to help you

    • when you edit code make sure you update the semantics. E.g. the element called 'heightForcer' now manipulates the width aswell, obviate that by calling it 'areaForcer'

提交回复
热议问题