如何在 30 分钟完成表格增删改查的前后端框架搭建 - V2EX
如果想在 V2EX 获得更好的推广效果,欢迎了解 PRO 会员机制:
pro/about

如果你经常使用铜币置顶主题,持有 V2EX Solana Token 会在每日签到时获得额外铜币:
solana
GrapeCityChina

如何在 30 分钟完成表格增删改查的前后端框架搭建

  •  
  •   GrapeCityChina May 20, 2022 1032 views
    This topic created in 1453 days ago, the information mentioned may be changed or developed.

    30 分钟,你可以做什么? 可以风卷残云的饱餐一顿;可以简单地打扫一下房间;或者可以跳 10 十遍刘宏《本草纲目》毽子操。 而今天,本葡萄要带你在 30 分钟内完成一套拥有增删改查表格系统的前后端搭建!

    在日常的系统开发中,表格( Grid )是最常见的数据表达形式,而表格中“增删改查”又是最常见的功能之一。所以在日常开发过程中,快速构建表格增删改查的框架将会成为影响开发效率最重要的部分之一。 为了实现本次 30 分钟快速构建表格系统的目标,我们需要回顾年初的文章中,我们介绍的集算表的相关内容。

    什么是集算表?

    为了让前端的表格不但具备类 Excel 的公式计算能力,同时还拥有传统表格控件的高性能,我们希望将传统的高性能结构化表格 (Grid) 与公式计算引擎 (CalcEngine)结合在一起。为了实现这样的设计,我们首次提出了数据管理容器 (DataManager) 的概念,将原有在后端才具备的关系数据引擎,完全在前端实现,从而实现了在大量数据(百万行)的环境下,实现秒级的加载、排序、筛选,而这所有的操作,都能够完全在前端浏览器中,通过 Javascript 代码实现。 数据管理容器 (DataManager)不仅承担了数据存储与索引的功能,同时还实现了多数据表关系、视图、CRUD 等功能。 集算表( TableSheet )则负责将数据管理容器 (DataManager)中整理好的数据、视图、关系,通过 SpreadJS 本身的"Canvas 画布"呈现在网页中。

    在集算表的帮助下,电子表格中的数据管理器具备了直连数据源、数据关系(外键)管理和异步操作更新等功能,产品数据处理分析能力得到进一步提升。

    综合集算表的功能特性,以下问题使用集算表将会变得很容易:

    • 加载后端数据到表格中,并进行分析、处理
    • 需要整合来自多个数据表(源)的数据并进行分析
    • 对后端提供的原始数据进行再加工(修改、计算等)和回写

    实战开始

    了解了集算表,接下来我们就正式开始内容搭建。

    首先,我们对问题进行步骤拆解: 1 、后端使用 Spring Boot 做快速搭建,创建一个 spring boot web 工程,下面是大致用到的 dependencies

    基本除了 springboot 自带的之外,额外引用了 fastjson 用于对一些复杂 json 格式进行处理。

    2 、构建前后台,可以选择前后端分离,或者结合的方式(例子中选中了前后端结合的方式),大致工程结构如下:

    3 、构建前端页面,前端页面的可以选择适合的框架( VUE ,React ,Angular ,例子中使用源生 JS 进行构建),在页面中引入 SpreadJS TableSheet (集算表)中的相关依赖

    需在原本 SpreadJS 的依赖基础上引入 gc.spread.sheets.tablesheet 这个依赖。

    4 、构建前端集算表配置配置集算表的功能操作

    var myTable = dataManager.addTable("myTable", { remote: { read: { url: "initDataManager" }, batch: { url: "batchUpdateDataManager" } }, batch: true, autoSync: false }); 

    上述配置了读取和批量两个操作,读取设置是在指定地址下读取数据。而批量操作包含对数据的批量增删改。从而覆盖到整个增删改查逻辑。

    var rowActiOns= GC.Spread.Sheets.TableSheet.BuiltInRowActions; var optiOns= sheet.rowActionOptions(); options.push( rowActions.removeRow, rowActions.saveRow, rowActions.resetRow, ); sheet.rowActionOptions(options); 

    上述代码设置了页面上供用户进行操作的对应按钮(删除行,保存行,重置行)

    myTable.fetch().then(function() { var view = myTable.addView("myView", [ { value: "id", caption:"编号", width: 80 }, { value: "firstname", caption:"姓", width: 100 }, { value: "lastname", caption:"名", width: 100 }, { value: "homephone", caption:"电话", width: 100 } ]); sheet.setDataView(view); }); 

    上述代码设置了表格的结构,对每一列进行了设置

    var submitButton = document.getElementById('submit'); submitButton.addEventListener('click', function() { sheet.submitChanges(); }); 

    通过设置一个提交的按钮,用于将批量的修改进行一次性提交。 5 、后端构建对应的数据增删改查逻辑(实例中通过一个假数据构建一个 list 进行模拟,实际情况可以扩展持久层与真实的数据库进行交互)。

    private static List<Employee> list = new ArrayList<Employee>(); static { for(int i=0;i<10;i++) { Employee employee = new Employee(); employee.setId(i); employee.setFirstname("FirstName"+i); employee.setLastname("LastName"+i); employee.setHomephone("HomePhone"+i); list.add(employee); } } @RequestMapping(value = "/initDataManager", method = RequestMethod.GET) @ResponseBody public List<Employee> initWorkBook() { return list; } @RequestMapping(value = "/batchUpdateDataManager", method = RequestMethod.POST) @ResponseBody public List<Map<String,Object>> batchUpdateDataManager(@RequestBody List<BatchManager> batchManagerList) { List<Map<String,Object>> reutrnList = new ArrayList<Map<String,Object>>(); for (BatchManager batchManager : batchManagerList){ Map<String,Object> returnMap = new HashMap<String,Object>(); String type = batchManager.getType().toString(); try{ if (type.equals("update")) { Employee employee = batchManager.getDataItem(); int index = batchManager.getSourceIndex(); Employee employeeSource = list.get(index); employeeSource.setId(employee.getId()); employeeSource.setFirstname(employee.getFirstname()); employeeSource.setLastname(employee.getLastname()); employeeSource.setHomephone(employee.getHomephone()); list.remove(index); list.add(index, employeeSource); returnMap.put("succeed", true); }else if (type.equals("insert")) { Employee employee = batchManager.getDataItem(); list.add(employee); returnMap.put("succeed", true); employee.setId(employee.getId()+10000); returnMap.put("data", employee); }else if (type.equals("delete")) { int index = batchManager.getSourceIndex(); list.remove(index); returnMap.put("succeed", true); } }catch(Exception e) { returnMap.put("succeed", false); } reutrnList.add(returnMap); } return reutrnList; } 

    这样,我们的框架就算搭建完成了。后面可以根据情况再做细微的调整和优化。总共耗时 30 分钟左右。 实例的代码可以参考附件,有兴趣的朋友可以下载自行参考搭建

    关注葡萄城社区,回复“增删改查”,即可免费获取文内 demo 。

    更多纯前端表格 demo 在线体验: https://demo.grapecity.com.cn/spreadjs/gc-sjs-samples/index.html

    No Comments Yet
    About     Help     Advertise     Blog     API     FAQ     Solana     2899 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 36ms UTC 15:23 PVG 23:23 LAX 08:23 JFK 11:23
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86