编辑
2023-08-17
我当开发
00

目录

1. 代码概览
2. 问题
3. 优化

昨天使用FineUIGrid写了一个购物车,主要是改变数量和单价计算总价的功能,纯前端。在实现时遇到了坑,解决后使用了闭包的结构优化,这里推演下应用的过程

1. 代码概览

首先购物车需要两个列,数量和单价,可以编辑,这里使用了 RendererFunction 进行绘制,绘制函数就是返回个 input 标签 购物车的项需要新增和删除,这里对应两个方法 adddataremovedata,在修改数据后需要计算合计价格:updateTotal ,所以有代码如下,这里抽象一下,细节不重要

/**绘制输入数量*/ const renderNumber = function(v, { rowId, rowValue }, m, g){ return `<input id="Number_${rowId}" value="${v}" class="number" style="width:98%;" type="text">`; }
/** * 新增方法 * @param {[MsINVMB]} values 新增的数据数组 */ function adddata(values){ F.ui.Grid1.addNewRecords(data, true); //更新总价 updateTotal(); }
/** * 删除方法 * @param {ID} rowId 删除的ID */ function removedata(rowId){ F.ui.Grid1.deleteRow(rowId, true); //更新总价 updateTotal(); }
/** * 更新总价 */ function updateTotal(){ //计算总价 let res = GetSummary(); //更新总价 F.ui.Grid1.setSummaryData(res); }

2. 问题

熟悉FineUI前端的能感觉到坑来了,调用过 addNewRecordsdeleteRow 的同学都知道,这两个方法会重绘Grid,即触发 renderNumber 函数,造成输入的值会被重置,比如我在某行的数量输入了2,然后新增了一行,执行 addNewRecords ,然后输入的2没了,成默认项了,这时总价也不对了;这里不讨论为什么会触发绘制,对外可能是逆天的,但是对内是自洽的; 最直接的解决方法就是在 新增 或 删除 行之前先得到录入的值,执行新增后再给赋上,然后计算总价;所以多了两个方法 GetInputValSetInputVal ,改造如下;

/** * 新增方法 * @param {[MsINVMB]} values 新增的数据数组 */ function adddata(values){ let rawvalue = GetInputVal(); F.ui.Grid1.addNewRecords(data, true); SetInputVal(rawvalue); //更新总价 updateTotal(); } /** * 删除方法 * @param {ID} rowId 删除的ID */ function removedata(rowId){ let rawvalue = GetInputVal(); F.ui.Grid1.deleteRow(rowId, true); SetInputVal(rawvalue); //更新总价 updateTotal(); }

3. 优化

这时让我别扭的地方来了,我最讨厌割裂,明显 GetInputValSetInputVal 是一对,在调用时中间间隔其他的逻辑,而且他俩本身不参与其他逻辑,SetInputVal 只接收 GetInputVal 返回的值,rawvalue 外露没有意义还有可能被篡改,所以我感觉他俩应该是一个函数,为什么方法我还要写两个,我能不能塞到一个函数里,并且中间还可以跨其他的逻辑;

/**得到值*/ function GetInputVal(){} /**设置值*/ function SetInputVal(values){}

这个场景下,我想到了使用闭包的方式,有一个函数 RestoreInputVal ,如果要跨过其他逻辑,这个函数返回的应该是 SetInputVal 的实现而不是调用,它应该这么写

/**还原值*/ function RestoreInputVal(){ const GetInputVal = ()=>...; const SetInputVal = (values)=>...; let rawvalue = GetInputVal(); return ()=>{ SetInputVal(rawvalue); }; }

用的时候像这样

/** * 新增方法 * @param {[MsINVMB]} values 新增的数据数组 */ function adddata(values){ let restorval = RestoreInputVal(); F.ui.Grid1.addNewRecords(data, true); restorval(); //更新总价 updateTotal(); } /** * 删除方法 * @param {ID} rowId 删除的ID */ function removedata(rowId){ let restorval = RestoreInputVal(); F.ui.Grid1.deleteRow(rowId, true); restorval(); //更新总价 updateTotal(); }

这样就实现了 rawvalue 的闭包,以此作为一个典型的应用案例

其实要按照面向对象的思路应该是一个 class ,这里也不考虑继承扩展,所以就不深入了

class InputRestore { #rawValue; constructor() { this.#rawValue = this.#getInputValue(); } #getInputValue() { // 原逻辑 } #setInputValue(value) { // 原逻辑 } restore() { this.#setInputValue(this.#rawValue); } }
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:没想好

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!