SpreadJS是葡萄城联合 40 余年业余控件技术和在电子表格应用领域的教训而推出的纯前端表格控件。作为一个类Excel控件,SpreadJS如何实现以后比拟风行的表格协同呢?本篇文章将简略介绍一下。
首先,从框架搭建上,本篇示例采纳当下风行的前后端拆散的开发方式,前端应用npm作为脚手架搭建Svelte框架。 后端应用Java的SpringBoot作为后端框架。前端应用SpreadJS V15.2.5以及SpreadJS在线表格编辑器Designer为前端操作的平台后端应用GCExcel作为文档的终端解决,随时提供备份与复原。
首先,介绍下在前端Svelte框架下搭建SpreadJS在线表格编辑器。
1、在pageage.json文件中引入相干SpreadJS资源

 "@grapecity/spread-excelio": "15.2.5",    "@grapecity/spread-sheets": "15.2.5",    "@grapecity/spread-sheets-barcode": "15.2.5",    "@grapecity/spread-sheets-charts": "15.2.5",    "@grapecity/spread-sheets-designer": "15.2.5",    "@grapecity/spread-sheets-designer-resources-cn": "15.2.5",    "@grapecity/spread-sheets-languagepackages": "15.2.5",    "@grapecity/spread-sheets-pdf": "15.2.5",    "@grapecity/spread-sheets-pivot-addon": "15.2.5",    "@grapecity/spread-sheets-pivots": "^14.0.0",    "@grapecity/spread-sheets-print": "15.2.5",    "@grapecity/spread-sheets-resources-zh": "15.2.5",    "@grapecity/spread-sheets-shapes": "15.2.5",    "@grapecity/spread-sheets-tablesheet": "15.2.5",

2、而后,集成在线表格编辑器Svelte组件版。在上一篇文章中,咱们介绍了如何在Svelte框架中实现在线表格编辑器。
咱们依照此思路新建一个SpreadSheet.svelte文件,写入根底在线表格编辑器。

<script>import {onMount} from 'svelte';import '@grapecity/spread-sheets-print';import "@grapecity/spread-sheets-charts";import '@grapecity/spread-sheets-shapes';import '@grapecity/spread-sheets-pivot-addon';import '@grapecity/spread-sheets-tablesheet';import '@grapecity/spread-sheets-designer-resources-cn';import '@grapecity/spread-sheets-designer';import * as GC from '@grapecity/spread-sheets';import * as GCDesigner from '@grapecity/spread-sheets-designer';let designer = null;onMount(async () => {designer = new GCDesigner.Spread.Sheets.Designer.Designer(document.getElementById("designerHost"));let spread = designer.getWorkbook();});</script><div id="designerHost" class="designer-host"></div><style scoped>@import "@grapecity/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css";@import '@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css';.designer-host {width: 100%;height: 100vh;}</style>

3、协同文档可能不止一个,咱们须要在页面上创立一个文档列表,来容许用户抉择编辑哪个文档,所以咱们须要创立一个文档列表页面OnlineSheets.svelte。在此页面中,咱们要实现路由跳转,和加载文档数据。
这里咱们用了svelte-spa-router进行路由跳转 与isomorphic-fetch进行前后端数据传输。

<script>    import {onMount} from 'svelte';    import { link } from "svelte-spa-router";    import {Utility} from "../utility.js";    let docList = [];    onMount(async () => {        Utility.getDocList().then(result => {            docList  = result.map((item,index)=>{                return {                    path:'/Spreadsheet/' + item.substring(0, item.lastIndexOf('.')),                    index,                    fileName:item                }            })        });    });</script><main class="main">    <table className='table' aria-labelledby="tabelLabel">        <thead>        <tr>            <th>Document</th>            <th></th>        </tr>        </thead>        <tbody>        {#each docList as docItem}            <tr>                <td>{docItem.index}</td>                <td>{docItem.fileName}</td>                <td className='row'>                    <a use:link={docItem.path}> Open</a>                </td>            </tr>        {/each}        </tbody>    </table></main>

以上代码实现了文档列表查看与文档跳转,应用 Open将跳转至后面设计好的在线表格编辑器中。
至此,前端的相干内容就筹备好了,接下来搭建下后端工作。
后端的筹备工作,首先装置gradle作为包管理器。当然,这里也能够用其余工具来代替,例如maven,或者源生引入jar包的形式将须要用到的jar包引入进来。之后创立springboot工程配合搭建gradle援用GCExcel以及前面协同须要用到的websocket。

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><version>2.4.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.4.3</version></dependency><dependency><groupId>com.grapecity.documents</groupId><artifactId>gcexcel</artifactId><version>4.0.3</version></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.6</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId><version>10.0.2</version></dependency><dependency><groupId>com.jayway.jsonpath</groupId><artifactId>json-path</artifactId><version>2.5.0</version></dependency></dependencies>

这样子,咱们做了框架的根本环境搭建,接下来咱们介绍下如何搭建webSocket。
在SpreadSheet.svelte文件中写入如下代码建设webSocket链接:

   function connectDocument(docName) {        if (webSocket != null) {            return;        }        var ws = new WebSocket(Utility.webSocketUrl);  //'ws://localhost:8090/spreadjs'        ws.onopen = function () {            var data = {                cmd: "connect",                docID: docName            }            ws.send(JSON.stringify(data));        }        ws.onmessage = onmessage;        webSocket = ws;    }

接下来咱们拜访下文档列表页,从文档列表页跳转进入文档,进行编辑。

接下来咱们须要监听前端收回的操作。这里因为在线表格编辑器自身将所有用户可能做的操作全副做了封装,所以省下了很多的功夫。

 onMount(async () => {        //初始化Designer        designer = new GCDesigner.Spread.Sheets.Designer.Designer(document.getElementById("designerHost"));        let spread = designer.getWorkbook();        //fromJSON        openDocument(docName);        //建设webSocket        connectDocument(docName);        var cm = spread.commandManager();        cm.addListener('myListener', onCommandExecute)    });

依据cmd去判断并且对命令再做一些简略封装,之后将封装过的命令发到服务端,之后通过websocket发同步指令:

function onCommandExecute(args) {        console.log(args.command);        var command = args.command;        var ServerCommand = null;        switch (command.cmd) {            case Utility.ServerCommands.EditCell:                ServerCommand = {                    sheetName: command.sheetName,                    row: command.row,                    column: command.col,                    newValue: command.newValue                }                break;            case Utility.ServerCommands.ResizeRow:                ServerCommand = {                    sheetName: command.sheetName,                    rows: command.rows,                    size: command.size                };                break;            case Utility.ServerCommands.ResizeColumn:                ServerCommand = {                    sheetName: command.sheetName,                    columns: command.columns,                    size: command.size                };                break;            case 'Designer.' + Utility.ServerCommands.SetFontFamily:            case 'Designer.' + Utility.ServerCommands.SetFontSize:            case 'Designer.' + Utility.ServerCommands.SetBackColor:            case 'Designer.' + Utility.ServerCommands.SetForeColor:            case 'Designer.' + Utility.ServerCommands.SetFontWeight:            case 'Designer.' + Utility.ServerCommands.SetFontStyle:            case 'Designer.' + Utility.ServerCommands.SetUnderline:            case 'Designer.' + Utility.ServerCommands.SetDoubleUnderline:                if (command.value && command.value.indexOf('undefined') === -1) {                    ServerCommand = {                        sheetName: command.sheetName,                        selections: command.selections,                        value: command.value                    }                }                break;            case Utility.ServerCommands.MoveFloatingObjects:                ServerCommand = {                    sheetName: command.sheetName,                    floatingObjects: command.floatingObjects,                    offsetX: command.offsetX,                    offsetY: command.offsetY                };                break;            case Utility.ServerCommands.ResizeFloatingObjects:                ServerCommand = {                    sheetName: command.sheetName,                    floatingObjects: command.floatingObjects,                    offsetX: command.offsetX,                    offsetY: command.offsetY,                    offsetWidth: command.offsetWidth,                    offsetHeight: command.offsetHeight                };                break;            case Utility.ServerCommands.InsertColumns:            case Utility.ServerCommands.InsertRows:                ServerCommand = {                    sheetName: command.sheetName,                    selections: command.selections                };                break;            default:        }        if (ServerCommand != null) {            var cmd = command.cmd;            var dotIndex = cmd.lastIndexOf('.');            if (dotIndex !== -1) {                cmd = cmd.substring(dotIndex + 1);            }            ServerCommand.cmd = cmd;            ServerCommand.docID = params.fileName;            Utility.ExecuteCommandAtServer(ServerCommand);            command.docID = ServerCommand.docID;            webSocket.send(JSON.stringify(command))        }    }

当协同端通过websocket接管到申请的时候,应用onmessage办法做同步命令。这里在协同端执行command之前须要先撤销之前的监听,防止再发送websocket导致死循环。在执行之后,再次增加监听。

 function onmessage(message) {        var command = JSON.parse(message.data);        command._styles = null;        let spread = designer.getWorkbook()        var cm = spread.commandManager();        cm.removeListener('myListener');        spread.commandManager().execute(command);        cm.addListener('myListener', onCommandExecute);    }

至此,协同根底内容搭建完结,咱们来看看编辑单元格内容后,产生了什么吧。
如下图所示,批改E4单元格内容,同时关上控制台网络tab。
将E4单元格数值2500改为2000,此时触发了EditCell事件,同时收回了交互指令:

![](https://img2023.cnblogs.com/blog/139239/202302/139239-20230214171707564-1725613752.png)此时新建一个窗口,复制链接,查看文档内容曾经变为了2000。如下动图所示:![](https://img2023.cnblogs.com/blog/139239/202302/139239-20230214171722569-698427034.gif)以上就是Svelte框架联合SpreadJS实现表格协同文档的办法,如果您想体验更多功能或收费下载试用SpreadJS,欢送拜访葡萄城官网。