表格資料變更,一般包含幾個內容:新增、修改、刪除、移動,開發中常會面臨的一個問題就是變更之後如何將資料同步到節點上,一直以來個人的建議還是利用表格重載,不管是url模式的還是data模式的實際都是需要重載,url重載自然會重新請求後台得到最新的數據,data模式一般就是對data的操作,之後重新以新的data去渲染出來。
同時會考慮的是如何盡量減少請求,可能感受最深的就是update操作,為了要更新這一記錄而重載整個表格,請求一遍數據感覺劃不來,那麼一般來說就可以利用表格的tool事件中的obj.update這個方法去更新。
不過具體使用中就會發現其諸多的不足的地方,本文就是主要針對這些不足進行一個處理給出一個tablePlug.update的方法,然後進而衍生出add和remove和move,同時新增了更新統計行資料的方法。
測試頁面: 綜合測試頁面 流載入表格測試頁面 定時重新整理表格測試頁面
##一、update 正如上面說的obj.update(data)有諸多限制,優點上來說就是用最小的修改代價,實現了資料的更新,他就更新參數中的data中的鍵的數據,不會整個行更不會整個table的節點更新;缺陷是底層的實現邏輯有點問題:
1、是透過遍歷data,更新快取cache中對應的記錄的key的value,然後根據cols的配置資訊更新td的內容,但是如果是想要更新toolbar列的話就沒戲,目前解析的只有templet的,所以如果想要更新toolbar的話基本上就只能設定成templet,而且要為這個列增加一個field,才有理論上的可能。
###2、toolbar欄位即使加了field改成templet也未必能更新過來,因為內部的實作邏輯是先判斷原始的data是否有這個key,所以如果field命名是原始的data裡面沒有的,後面用obj.update也更新不進去的,這個是比較大的限制。 ######因為拿我們專案來說,後台給我們的資料如果原始的記錄裡面沒有這個key的值他不會給一個key: ''的,那麼後面要想利用obj.update這個key就變得不可能,除非利用parseData在渲染之前對後台給的資料做一個人工的初始化把對應的key添加上,但是可想而知有多麻煩。 ######3、資料他是一個一個更新進去,然後更新一個值就更新對應的td,但是這個就存在另外一個風險了,就是遍歷物件他是無序的,例如update{a: 1 , b:2},如果a字段的cols中會用到b字段的值做一個處理再顯示出來。 ######那麼如果遍歷順序是先更新a的值,然後就開始更新a的td的內容,這時候cache中b的值還是舊的不是你要更新進去的2,等到更新了b字段了他又不能說偵測到其他欄位有使用了這個欄位會去再次更新對方的內容,這就導致了a出來的結果還是錯的。 ######4、更新了統計列的某一個值統計行的對應資料沒有重新計算。 ######總結的來說就是,obj.update實現的還是太過理想化太過簡單,一條記錄從數據上來說每個key是獨立的這個沒什麼問題,但是到頁面顯示就不然了,因為頁面的內容它不一直是單一欄位的簡單值顯示,也會進行一些特殊處理。 ######所以需要一個templet來轉化,來自定義,所以有可能一個td裡面會用到多個字段這個很正常,工具列的按鈕也會根據數據的狀態去決定部分按鈕是否顯示等等。 ######所以個人認為要更新這個資料不能是一個獨立的小單元的更新,而是先update這一行的資料然後在update這一行,而不是遍歷被update的key一個個更新,再往大了看,實際這個表的記錄也是一個整體。 ######也是不能說你改了這條記錄其他的記錄必定是不變的,不排除某個字段的td他會根據當前頁面的同一個field做了什麼處理現實,比如統計行,所以目前的想法就是直接將值先update到cache中,然後再呼叫table內部的渲染tr td的內容。 ######大致的程式碼:#########前面是針對參數做了一些處理讓參數更靈活,最關鍵的是後半部的更新cache的部分,還要一個最關鍵的renderData的方法:###他的作用就是將cache中的資料重新解析渲染一遍,同時針對是否是移動資料還有預設點擊那一筆記錄的處理,但是核心是渲染cache,呼叫table.js內部的renderData。
使用場景:
1、知道目前編輯修改的是那筆記錄,可以看看一個最常用的場景就是點擊編輯彈出一個form然後修改提交,完成之後希望盡量不要重新請求介面更新到data和頁面中去,
gif很不好錄,自己使用測試的例子裡面的編輯按鈕測試效果即可
#調用的更新資料的形式是:
tablePlug.update(表格实例的id, 当前tr的index, newData)
2、不知道當前的trIndex的情況下update某一筆記錄的話,必須有一個限制就是必須是有主鍵的表格,並且更新的資料中必須包含主鍵的字段,不然你也不知道更新的到底是哪一筆紀錄。
tablePlug.update('demo', {id: 10002, username: '贤心'});
3、一次更新多筆記錄,這個參數trIndex就沒有意義了,加了也沒用,因為是更新多筆記錄,所以可以這麼寫
tablePlug.update('demo', [{id: 10002, username: '贤心'}, {id: 10006, username: '小偷', age: 18, sign: '大叔'}]);
這個測試頁面可以看看頭部toolbar中的「積分清零」還有「女性積分加100」這兩個測試按鈕以及背後的事件執行的方法
4、更任性的,只要傳入一個tableId,update會將目前按照cache中的資料給渲染一次,這個是非常實用的,例如如果你覺得我update中的邏輯針參數對cache的修改的邏輯不滿意可以自己用自己覺得更好的方法去處理cache,最後執行一下tablePlug.update('demo')就好了,提供更高的自由度,和拓展的可能性。
二、addData
addData新增的記錄是已經要求介面完成回傳的資料記錄,本質上來說就是不一樣的,所以不要混淆。
具體addData的程式碼:
data模式的話,實際上也是在data裡面加入一些記錄,然後也是再reload一下。
// 添加单条记录: tablePlug.addData ('demo', {id: newId, username: '甲'}); // 添加多条记录 tablePlug.addData ('demo', [{id: newId1, username: '乙'},{id: newId2, username: '丙'}]);
關於addData的有一個比較綜合的例子可以看看利用table的data模式怎麼跟流加載配合使用,弄成一個流加載的表格
https:/ /sun_zoro.gitee.io/layuitableplug/testTableFlow
#三、del
##新增和刪除實際個人建議還是reload比較穩妥,不管是url還是data模式都是,所以刪除對應的處理方式也跟新增實際差不多,只不過刪除麻煩一點的就是data模式要在原始的記錄裡面去刪除指定的記錄。 而且有可能開啟了複選的狀態記憶刪除了就要將關於他的狀態給調整一下;還是為了使用更方便,參數同樣做了處理,1、刪除指定的下標的數據,可以查看表格行的toolbar中的刪除按鈕的監聽處理,但是注意,如果表格是url的模式,目前測試頁面寫的都是json文件,所以reload也不會有效果的。 所以要測試請在data模式的測試,不用糾結這個,url的如果是實際的服務接口的話是後台返回數據,一般刪除成功了後面查詢是不會再出來的,除非後台接口有問題。2,刪除指定的一些記錄,這個一般有兩種形式,但是要求一樣就是必須是有主鍵的表格
// id集合 tablePlug.del('demo', [1,2,3,4]); // 对象数组 tablePlug.del('demo', [{id: 1, name: 'name1'}, {id:2}, {id:4}]);
四、move
這個處理基本上跟update差不多,將資料在cache中調整位置,然後呼叫一下元件內部的renderData的方法讓他重新渲染出來就好然後為了使用方便衍生出來一個上移跟下移的方法
效果理论上利用一些拖拽事件或者其他的插件在事件中调用一下tablePlug.move('demo', form, to);就能够实现顺序的任意改变了
限制:注意!这个只是针对数据移动,不会有单条数据记录的变动,如果原始的数据里面有点击了排序,那么移动之后默认是会去掉这个排序的状态了的,因为移动之后很可能就不能满足当前的排序规则了,所以建议在使用移动的时候不要跟sort搭配,如果有sort而且所谓的移动是会发起请求改变数据的,那么这个建议还是使用请求接口得到两个新的数据然后用update去更新他们的位置。
五、renderTotal
在记录更新之后,如果存在统计行有需要统计的列,那么值一般也要跟着变,另外一个更加重要的作用就是可以自定义统计规则,而不是自带的求和,可以自定一定计算的函数,或者可以直接类似templet一样的去自定义返回的内容,包括异步的去读取想要显示的数据。
代码大概如下:
从实现代码可以看出就是给cols的字段配置新增一个totalFormat的设置,可以设置一个规则如果不设置的话就是sum(目前也只是添加了sum,其他的规则后面会加入或者自己加入,比如平均。
最大最小不过个人觉得主要意义是可以自定义方法,这个才是实用常用的),也可以设置一个方法,如果不是异步的可以直接把结果返回,如果是需要异步的那么也可以在得到最终想要的结果的时候执行:
tablePlug.renderTotal(tableId, field, res);
比如下面的:
平时实用的话不是都要自己去调用的,在插件内部已经在renderDone回调里面会去执行他了:
参数也是比较自由,不同的组合会有不同的效果,
// 触发更新某个表格的所有列的统计数据 renderTotal(tableId); // 触发更新某个表格的某个字段的数据 renderTotal(tableId, fieldName); // 更新某个表格的某个字段的统计数据为value renderTotal(tableId, fieldName, totalValue);
六、refresh
之前做过一个智能reload的修改,即在执行table.reload的时候会根据传过去的option来判断只是重新请求数据还是需要重载一下,个人觉得效果可以了。
不过对于有强迫症(有追求)的小伙伴来说,在一些场景下还是不够好,就是那些定时刷新的,表现就是一方面滚动条会回到top:0,left:0,还有其他的比如鼠标在操作分页组件的时候会觉得失去焦点,新增一个tablePlug.refresh来试一试能否满足要求。
先看效果:
事件背后做的事情:
表格config:
背后的实现思路
修改table的Class.prototype.pullData支持refresh模式
renderData的时候根据是否refresh去做一些细节的处理,还有一个限定就是返回的数据中关于总数应该是不变的,如果发生了改变,那么还是会renderData,会重新渲染page组件。
另外一个限制就是这种refresh的表格不建议再加什么按钮呀edit呀,因为它一直会在变,基本主要就是用来做一个单纯用来显示用的表格,比如一些经常变化的数据,访问人次,股票动态之类的。
使用:
// 启动表格demo的自动刷新功能,500毫秒一次 tablePlug.refresh('demo', 500); // 取消表格demo的自动刷新 tablePlug.refresh('demo', false); // 停止所有已开启自动刷新的表格的自动刷新 tablePlug.refresh(false);
更多layui框架知识请关注layui使用教程。
以上是layui表格資料變更的一種處理方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!