Ellia.Duan 发表于 2024-9-13 14:48:32

SpreadJS 在 Vue 中问题汇总

本帖最后由 AlexZ 于 2024-10-9 14:19 编辑

在两年前,我写过一篇文章,叫做在Vue3中使用SpreadJS常见问题总结。这里面提到了分别使用SpreadJS,或者Designer的一些问题。但是这两年期间内,越来越多的客户遇到了Vue框架问题,我决定再重新整理一下。

主要问题有:性能慢、白屏、最大堆栈问题、输入内容丢失需要双击显示等。

1、性能慢
同样的代码div id的designer设计器比gc-spread-sheets加载数据慢,是为什么?
【15】项目使用vue3,响应慢的问题

2、白屏
【15.0.5】vue3项目中,addSheet创建的表格,切换后会白屏
【v17】当使用open方法打开sjs文件后,进行预览白屏,切换回编辑模版页面也白屏

3、最大堆栈问题(maximum call stack size exceeded)
【resumeCalcService&calculate 函数vue中执行报错堆栈溢出】
【V17.1.1】 json渲染,显示内存溢出循环引用

4、输入内容丢失
如下动图所示:


5、其他
SpreadJS右键手动删除行后,页面未实时更新
SpreadJS refresh方法延迟
SpreadJS V15 在移动端不能滚动
下拉框内容,选中后不更新


最大的原因是使用了this.designer 或者this.spread 。在一些客户的代码中,频繁调用this.designer 或者this.spread。而SpreadJS组件是一个很复杂的控件,spread实例如果挂载当前的this上,导致spread实例被自动代理,所以,并不建议使用this.designer 或者this.spread。
但是,如果不使用this.designer 或者this.spread,要进行频繁传参,也是不合适的。

那么。怎么办呢?
在SpreadJS中,有一个API叫做findControl。

一、findControl
1、Designer(在线表格编辑器)
如下代码:

<div id="gc-designer-container" style="width:100%;height:100vh;border:1px solid darkgray">
var designer = new GC.Spread.Sheets.Designer.Designer(document.getElementById("gc-designer-container"));
var designer = GC.Spread.Sheets.Designer.findControl(document.getElementById("gc-designer-container"));上述代码中,第一行是定义了一个id为“gc-designer-container”的dom元素。第二行代码,对Designer进行了实例化。第三行代码,我们发现可以通过findControl,传参dom元素来找到designer 对象。
也就是说,我们只需要全局保存dom元素,在其他方法中,如果要使用designer 对象 ,调用GC.Spread.Sheets.Designer.findControl(document.getElementById("gc-designer-container"))即可。

而在第三方框架中,大家也许没有使用上述的dom方式,而是用了这个gc-spread-sheets-designer组件。那么,又该如何处理呢?
    <gc-spread-sheets-designer :styleInfo='styleInfo' @designerInitialized='designerInitialized' id="gc-designer-container">
    </gc-spread-sheets-designer>接下来,在designerInitialized 初始化方法中,我们可以获取designer对象。然后通过getHost()保存其dom元素,将dom元素挂载在this上即可。
参考下面的代码:

    designerInitialized(designer){
      this.designer = designer.getHost()
      this.init()
    },

    init(){
      let designer = GC.Spread.Sheets.Designer.findControl(this.designer)
      let spread = designer.getWorkbook()
      
    },接下来 ,我们看一下,如果不用designer,光用spread的设置方式。
2、SpreadJS

<gc-spread-sheets @workbookInitialized="initWorkbook"
                        styleInfo='styleInfo' >
      </gc-spread-sheets>
initWorkbook: function (spread) {
      this.spread = spread.getHost();
      this.initData();
    },

initData: function () {
      let spread = GC.Spread.Sheets.findControl(this.spread)
    },
二、markRaw
如果项目已经开发很久了,上述改造工作量太大了,怎么办呢?
在vue3中,推出了一个markRaw的用法。具体参考这里:https://cn.vuejs.org/api/reactivity-advanced


因为作为vue的component, 只要往component上方一个property,vue就会用proxy把对象包了。这个封装是为了拿到变更后的对象来更新view。
当使用this.spread时,整个spread实例都被包了。不仅干扰到spread自己内部的数据访问。而且会引起一些问题。用markRaw,就是让vue不要包这个对象了,不进行代理。
【注】:此方法仅适用于Vue3。










页: [1]
查看完整版本: SpreadJS 在 Vue 中问题汇总