水平数据更新不适用于滚动 [英] Horizontal data update is not working on scroll

查看:68
本文介绍了水平数据更新不适用于滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个大数组,我需要将它渲染到一个表中。而不是渲染所有项目,我只是水平和垂直渲染几个项目。然后在基于鼠标滚动的滚动上是否发生垂直/水平更新表值。但我有两个问题

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 scroll whether happened vertical / horizontal updating table values. But I have two problems in this

以下是我的代码问题


  1. 横向滚动数据时不会更新。

  2. 水平滚动也会使屏幕闪烁。

  3. 水平元素未对齐正确。

这是jsbin链接 http://jsbin.com/oSOsIQe/2/edit

这是JS代码,我知道代码不干净但我稍后会清理它。

Here is the JS code, I know code is not clean but I will clean it later.

var $matrix = (function () {
function $matrix(data, holder, hidescrollbar, config) {
    var header_h = config.header || "150px";
    var data_h = config.header || "90px";
    !data && (function () {
        // Fake Data, will be removed later
        data = new Array(50000);
        for (var i = 0, l = data.length; i < l; i++) {
            var dummy = Math.random().toString(36).substring(5);
            var dum = [];
            for (var j = 0; j < 26; j++) {
                dum.push(dummy + i);
            }
            data[i] = dum;
        }
    }());
    hidescrollbar = hidescrollbar || false;
    var heightForcer = holder.appendChild(document.createElement('div'));
    heightForcer.id = "heightForcer";
    var view = null;
    //get the height of a single item
    var dimensions = (function () {
        //generate a fake item and calculate dimensions of our targets
        var div = document.createElement('div');
        div.style.height = "auto";
        div.innerHTML = "<div class='rowHeader'>fake</div><div class='rowData'>fake</div>";
        holder.appendChild(div);
        var output = {
            row: div.firstChild.offsetHeight,
            header: div.firstChild.offsetWidth,
            data: div.lastChild.offsetWidth
        }
        holder.removeChild(div);
        return output;
    })();

    function refreshWindow() {
        //remove old view
        if (view != null) {
            view.innerHTML = "";
        } else {
            //create new view
            view = holder.appendChild(document.createElement('div'));
        }
        var firstItem = Math.floor(holder.scrollTop / dimensions.row);
        var lastItem = firstItem + Math.ceil(holder.offsetHeight / dimensions.row) + 1;
        if (lastItem + 1 >= data.length) lastItem = data.length - 1;

        var hfirstItem = Math.floor(holder.scrollLeft / dimensions.data);
        var hlastItem = hfirstItem + Math.ceil(holder.offsetWidth / dimensions.data) + 1;
        if (hlastItem + 1 >= data[firstItem].length) hlastItem = data[firstItem].length - 1;

        //position view in users face
        view.id = 'view';
        view.style.top = (firstItem * dimensions.row) + 'px';
        view.style.left = (hfirstItem * dimensions.data) + 'px';
        var div;
        //add the items
        for (var index = firstItem; index <= lastItem; ++index) {
            div = document.createElement('div');
            var curData = data[index].slice(hfirstItem, hlastItem);
            div.innerHTML = '<div class="rowHeader">' + 
              curData.join('</div><div class="rowData">') +
            "</div>";
            div.className = "listItem";
            div.style.height = dimensions.row + "px";
            view.appendChild(div);
        }
        console.log('viewing items ' + firstItem + ' to ' + lastItem);
    }
    heightForcer.style.height = (data.length * dimensions.row) + 'px';
    heightForcer.style.width = (data[0].length * dimensions.data) + 'px';
    if (hidescrollbar) {
        //work around for non-chrome browsers, hides the scrollbar
        holder.style.width = (holder.offsetWidth * 2 - view.offsetWidth) + 'px';
    }
    refreshWindow();

    function delayingHandler() {
        //wait for the scroll to finish
        //setTimeout(refreshWindow, 10);
        refreshWindow();
    }
    if (holder.addEventListener) holder.addEventListener("scroll", delayingHandler, false);
    else holder.attachEvent("onscroll", delayingHandler);
}
return $matrix;
 }());

new $matrix(undefined, document.getElementById('listHolder'), false, {
  header: "150px",
  data: "90px",
  headerColumns: 2
});

请帮助我。

推荐答案

解决方案 ,概念我的回答对类似问题的扩展

代码

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%;
}



<div id="listHolder"></div>

只需清理一些代码:


  • 你没有以OO方式使用该对象,不需要新的/使用该函数作为构造函数(如果你打算,用一个大写启动它)

  • 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)

在这个时代,编译器可以为我们做很多事情,没有理由使用像'i'或'j'这样的名字' index'更加自我解释,if语句是针对你使用的运算符而设的(!data&& / * set data * / ,使用 if(!data)/ * set data * /

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*/)

不要使用匿名电话-once函数不需要它们,每次运行父函数时都需要重新编译它们

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

在循环之外声明变量

不要使用random()(在这种情况下)除非代码正常工作,否则很难看到最新情况

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

个人偏好发送null到函数而不是未定义,并且当矩阵与apt
一样使用注释时不要命名函数$ matrix!

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!

个人偏好除非你知道自己在做什么,否则++ x正是你所需要的,x ++是资源的轻微浪费

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

总是使用适当的缩进,即使if语句可以写在一行上。与 个人偏好无关,因为您在线发布代码,希望其他人帮助您

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

代码确保您更新语义。例如。名为'heightForcer'的元素现在也操纵宽度,通过调用'areaForcer'来消除它

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'

这篇关于水平数据更新不适用于滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆