前文中咱们具体介绍过稠密数组的那些事儿,以及在理论我的项目中,稠密数组如何在前端电子表格中施展出它最大的成果。而这次,咱们将从实战利用登程,为大家介绍稠密数组在前端中的具体利用。
咱们都晓得在 Javascript 中是通过 Array() 构造函数构件稠密矩阵,或者通过数组,设定数组的索引长度大于以后数组长度的形式来创立稠密矩阵。
var arr = new Array(100) //arr 没有元素,但 arr.length 是 100
var a = []; // 创立一个空数组,length 为 0
a[50] = 50; // 赋值增加一个元素,length 为 51
稠密数组中,没有元素的结点为 empty,获取这些结点将返回后果 undefined。通过应用 index in array 能够判断一个结点是否有元素。例如上面代码中,a[0] 和 a[1] 的返回都为 undefined,然而 a[1] 其实为空。
JS 中曾经反对稠密数组的存储,但在理论状况中,咱们保留稠密数组的保留并不是间接进行,而是会依据理论状况构建其余存储形式保留稠密数组。想理解为什么要多此一举,这里就须要大家理解一个概念——数据长久化。
咱们在前端进行许多操作时,会产生许多数据,例如在前端表格进行多人填报、协同的时候,会呈现很多须要长期保留的数据,有些数据还要转移到其它地位中便于人们存储、治理、操作等。而实现这一指标的关键点就是数据的长久化,咱们须要将内存中数据序列化为 json 等存储格局保留到数据库并还能反序列化到内存。在之前的文章详解电子表格中的 json 数据:序列化与反序列化曾经具体介绍了,大家有趣味能够查看。
看到这里,你认为问题彻底解决了吗,图样图森破。
为了解决数据长久化,咱们应用了 JSON,但这时新的问题也随之呈现,JSON 存储中没有 undefined。咱们对数组进行操作的时候,数组中 empty 字段都会序列化为 null,如下图所示。
JSON.stringify(a)
'[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,50]'
再次 parse 后,数组便不再是稠密数组了。
JSON.parse(JSON.stringify(a))
(51) [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 50]
这种状况下,为了解决 JSON 数据在转化过程中上述呈现的状况,咱们就须要构建一些其余存储形式,来更好的地解决这个问题~ 而这些存储形式又有哪些特点,让咱们一起看看。
1、对象存储
在前端利用 JS 的语言特点,咱们能够通过 Object 能够轻松实现 Sparse Array。例如在 Spread JS 中,对象属性名称对应所在单元格的行列,value 属性保留单元格的值,同样能够拓展出 formula 和 style 等属性保留单元格公式和款式。应用 Sparse Array 不必初始化大小也不必关怀数据的扩容,须要做行列操作时也只须要扭转行列属性的援用即可。
上图中的数据存储后果如下
{
"0": {
"0": {"value": 0}
},
"2": {
"1": {"value": 2},
"3": {"value": "S"}
},
"4": {
"3": {"value": 3}
}
}
须要存取数据时候间接通过对象属性拜访。上面是 JS Sparse Array 的一个简略对象实现。
function SparseArray(){this._array = {}
}
SparseArray.prototype.setValue = function(row, col, data){if(!this._array[row]){this._array[row] = {}}
this._array[row][col] = data
}
SparseArray.prototype.getValue = function(row, col){if(this._array[row]){return this._array[row][col]
}
return undefined;
}
let arr = new SparseArray();
arr.setValue(3, 3, 5);
console.log(arr.getValue(3, 3)) // 5
2、三元组
在矩阵中每一个元素有行标,列标,元素值三个信息,将元素按需放入数组中便是三元组存储。存储构造能够是一个蕴含元素信息对象,也能够间接简化为一个长度为 3 的数组。三元组的存储形式能够不便记录相似下图的轨迹信息或者自在曲线信息,通过对数组进行 push 和 pop,能够不便进行回退和后退。
上图中的轨迹信息,以数组三元组存储后如下,元素 value 代表以后已元素数量,也能够应用对象记录时间等更多信息。
[[1,1,1],
[5,8,2],
[4,3,3],
[1,5,4]
]
上面,咱们就用这种形式建设一个 undoStack 记录回退。
function TSMatrix(){this._array = [];
this.undoStack = []}
TSMatrix.prototype.addNode = function(row, col, value){this._array.push([row, col, value])
}
TSMatrix.prototype.canUndo = function(){return this._array.length > 0;}
TSMatrix.prototype.undo = function(){if(this._array.length > 0){this.undoStack.push(this._array.pop())
}
}
TSMatrix.prototype.canRedo = function(){return this.undoStack.length > 0;}
TSMatrix.prototype.redo = function(){if(this._array.length > 0){this._array.push(this.undoStack.pop())
}
}
TSMatrix.prototype.print = function(){console.log(JSON.stringify(this._array))
}
let mat = new TSMatrix();
mat.addNode(1, 1, 1)
mat.addNode(5, 8, 2)
mat.addNode(4, 3, 3)
mat.addNode(1, 5, 4)
mat.print() //[[1,1,1],[5,8,2],[4,3,3],[1,5,4]]
mat.undo()
mat.print() //[[1,1,1],[5,8,2],[4,3,3]]
mat.redo()
mat.print() //[[1,1,1],[5,8,2],[4,3,3],[1,5,4]]
除了以上两种形式,还能够将上述形式联合,建设十字链表以应答更简单的场景。大家如果感兴趣点个赞咱们下次持续说。
在后续的内容中,咱们还会持续为大家带来其余前端电子表格技术中的深度解密,走过路过不要错过。