我有一个大数组,我需要将它渲染到一个表中。而不是渲染所有项目,我只是水平和垂直渲染几个项目。然后在基于鼠标滚动的滚动上是否发生垂直/水平更新表值。但是我有两个问题
以下是我的代码问题
这是jsbin链接http://jsbin.com/oSOsIQe/2/edit
这是JS代码,我知道代码不干净但我稍后会清理它。
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
});
请帮我解决这个问题。
答案 0 :(得分:2)
我注意到你的jsbin示例已被略微修改并使用了wheelDelta属性。这就是您无法区分水平和垂直更新的原因。您需要使用wheelDeltaX
和wheelDeltaY
,它们将是一个值或零,具体取决于用户是垂直滚动还是水平滚动。
另外,小心使用鼠标滚轮事件,它不符合标准,所以可能会回来困扰你。可能值得看一下JQuery源代码,看看scroll()
方法如何实现这些处理程序。我想象有一个计时器监视元素的滚动偏移,当对象滚动时触发合成事件。但这是一个完全疯狂的猜测。就像我说的那样,你最好还是看看它。
答案 1 :(得分:1)
问题是您在onmousewheel
上挂钩#foo
事件,但没有意识到#foo
只与其中包含的数据一样大。如果您进行了以下更改(即采用#wrapper
而不是#foo
)
var listHold = document.getElementById('wrapper');
您会注意到值已更新。
答案 2 :(得分:1)
<强> 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%;
}
<div id="listHolder"></div>
清理代码只是一些事情:
你没有以OO的方式使用该对象,不需要新的/使用该函数作为构造函数(如果你打算,以一个大写的方式启动它)
在这个时代,编译器可以为我们做很多事情,没有理由使用像'i'或'j'这样的名字,其中'index'更加自我解释,而if语句是为了你使用的运算符(!data && /*set data*/
,使用if (!data) /*set data*/
)
不要在不需要的情况下使用匿名的一次调用函数,每次父函数运行时都需要重新编译它们
在循环之外声明变量
不要使用random()(在这种情况下),除非代码有效,否则很难看到最新情况
个人偏好向函数发送null而不是undefined,并且当矩阵与apt一样时,不要将函数命名为$ matrix 使用评论!
个人偏好除非你知道自己在做什么,否则++ x正是你所需要的,x ++是对资源的轻微浪费
因为你正在使用水平滚动,忘记隐藏滚动条
从简单开始,不要试图获得高度,只需强制一个。检测高度等问题是为工作解决方案保留的细节
总是使用正确的缩进,即使if语句可以写在一行上。关于您的个人偏好并不重要,因为您在线发布代码希望其他人帮助您
编辑代码时请确保更新语义。例如。名为'heightForcer'的元素现在也操纵宽度,通过调用'areaForcer'来消除它