在上一篇文章中,我们已经详细介绍了稀疏数组的那些事,以及稀疏数组在实际项目中如何在前端电子表格中发挥最大的作用。而这次,我们将从实际应用出发,介绍一下稀疏数组在前端的具体应用。我们都知道在Javascript中,通过Array()构造函数构造稀疏矩阵,或者通过数组,将数组的索引长度设置为大于当前数组长度来创建稀疏矩阵。vararr=newArray(100)//arr没有元素,但是arr.length是100vara=[];//创建一个空数组,长度为0a[50]=50;//赋值添加一个元素,长度为51在稀疏数组中,没有元素的节点为空,获取这些节点将返回结果undefined。通过在数组中使用索引,您可以确定节点是否具有元素。例如,在下面的代码中,a[0]和a[1]的返回都是未定义的,但a[1]实际上是空的。JS已经支持稀疏数组的存储,但是在实际情况下,我们并不是直接保存稀疏数组,而是根据实际情况构造其他存储方式来保存稀疏数组。要想理解为什么必须这样做,就需要理解一个概念——数据持久化。当我们在前端进行很多操作的时候,会产生大量的数据。比如多人填写前端表单,协作时,会有大量的数据需要长期保存。一些数据也会转移到其他地方供人们存储、管理、操作等,实现这个目标的关键是数据持久化。我们需要将内存中的数据序列化成json等存储格式保存到数据库中,反序列化到内存中。上一篇文章对电子表格中的json数据进行了详细的讲解:序列化和反序列化已经详细介绍过了,有兴趣的可以去看看。看到这里,是不是觉得问题已经彻底解决了,图森的格局被打破了。为了解决数据持久化,我们使用了JSON,但是这时候新的问题也出现了,JSON存储中没有undefined。当我们对数组进行操作时,数组中的空字段会被序列化为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,null,50]'再次解析后,数组不再是稀疏数组。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,50]在这种情况下,为了解决JSON数据转换过程中的上述情况,我们需要构建一些其他的存储方式来更好的解决这个问题问题~还有这几种存储方式有什么特点,让我们一起来看看吧。1.对象存储在前端。利用JS的语言特性,我们可以很方便的通过Object来实现SparseArray。比如在SpreadJS中,对象属性名对应单元格的行列,value属性保存单元格的值。也可以扩展公式和样式等属性来保存单元格公式和样式。使用SparseArray不需要初始化大小,也不需要关心数据扩展。当需要进行行和列操作时,只需要改变行和列属性的引用即可。上图中的数据存储结果如下{"0":{"0":{"value":0}},"2":{"1":{"value":2},"3":{"value":"S"}},"4":{"3":{"value":3}}}当需要访问数据时,可以直接通过对象属性访问。下面是一个简单的JS稀疏数组对象实现。functionSparseArray(){this._array={}}SparseArray.prototype.setValue=function(row,col,data){if(!this._array[row]){this._array[row]={}}这个。_array[row][col]=data}SparseArray.prototype.getValue=function(row,col){if(this._array[row]){returnthis._array[row][col]}returnundefined;}让arr=newSparseArray();arr.setValue(3,3,5);console.log(arr.getValue(3,3))//52.矩阵中三元组的每个元素都有行和列标签,该元素value有三条信息,按需将元素放入数组就是三元组存储。存储结构可以是包含元素信息的对象,也可以直接简化为长度为3的数组。三元组的存储方式可以方便的记录轨迹信息或者自由曲线信息,类似下图。通过push和pop数组,方便前后进退。上图中的轨迹信息存储为数组三元组如下。元素值表示当前元素的数量。您还可以使用该对象来记录时间和其他更多信息。[[1,1,1],[5,8,2],[4,3,3],[1,5,4]]下面,我们将以这种方式创建一个undoStack记录回退。函数TSMatrix(){this._array=[];this.undoStack=[]}TSMatrix.prototype.addNode=function(row,col,value){this._array.push([row,col,value])}TSMatrix.prototype.canUndo=function(){returnthis._array.length>0;}TSMatrix.prototype.undo=function(){if(this._array.length>0){this.undoStack.push(this._array.pop())}}TSMatrix.prototype.canRedo=function(){returnthis.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))}letmat=newTSMatrix();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]]除了上述两种方法外,还可以结合上述方法创建交叉链表,以应对更复杂的场景。有兴趣的请点个赞,我们下期继续聊。在后续的内容中,我们会继续为大家带来其他前端电子表格技术的深度解密,路过不要错过。
