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線上體驗:
https://demo.grapecity.com.cn/spreadjs/gc-sjs-samples/index.html