苍穹监听动态表单,字段变化时,会触发propertyChanged事件
有时候我们有一个简单的业务需求:如果输入的值不是数字,则清空该字段为空,此时就会在代码设置字段值为null
如该方法:
引发的现象是,界面输入一次值时,触发一次propertyChanged,做了相关是否是数字判断,不符合着设置为null,这时候又触发了一次propertyChanged,虽然不会影响最终结果,但是连续触发两次,感觉很变扭,也很影响性能
产生疑问:是否可以设置参数,特殊情况下不触发propertyChanged
跟了一遍propertyChanged的值变化触发源码:
可以看出,只要有值变化,就会触发值更新,然后一定会调用propertyChanged方法,没有if else 或者 参数控制否是调用propertyChanged,是一定会调用。。。。
所以结论是,只要是值更新,一定会调用propertyChanged方法,没办法控制
最终翻阅了社区,找到一种方法可以避免二次调用propertyChanged的解决方案:
1、设置一个全局的变量,放到苍穹的pageCache中
2、每次要用代码调用值变更方法时,判断该值,从而避免二次调用
如图:
此方案实际上代码还是会走两遍,只不过不会再走第二次业务代码,从业务方面避免二次触发propertyChanged,也可以达到预期
疑问1:共享标识是否会引发线程安全问题?
经测试,苍穹插件,每次调用都是一个新的对象,所以PageCache对象也是一个新的,只有当前线程持有,是线程安全的
如图:
第一次调用的PageCache和第二次调用的PageCache是两个不一样的对象,线程安全!
疑问2:有评论说下面代码可以实现避免二次调用?
this.getModel().beginInit();
this.getModel().setValue();
this.getModel().endInit();
结论:经测试,没有用,还是会调用两次,如图:
1、界面原本是null,输入"f",第一次进入propertyChanged
2、然后执行业务代码,判断输入的"f"不是数字,设置null进入,此时第二次进入propertyChanged
3、第二次进入propertyChanged,可看到旧的值是"f",新的值是null
-- 2023/12/18 评论区@Reality 大佬的方法测试
DynamicObject data = this.getModel().getDataEntity(true);
DynamicObjectCollection entry = data.getDynamicObjectCollection("entryentity");
DynamicObject row = entry.get(rowIndex);
row.set("field",null);
this.getView().updateView("field",rowIndex);
结论:经测试,有用,不会触发二次propertyChanged
如图:
1、界面原本是null,输入"f",第一次进入propertyChanged
2、然后执行业务代码,判断输入的"f"不是数字,设置null,运行到set 和 updateView都没有再次进入propertyChanged
跟了下源码
方法一:this.getModel().setValue(fieldKey, null, rowIndex);
方法二:DynamicObject row = entry.get(rowIndex); row.set(fieldKey,null);
这两种方式走的代码都一样,都会执行到kd.bos.dataentity.metadata.dynamicobject.DynamicProperty#setValuePrivate
但是第一种会在执行setValuePrivate方法前,注册监听,并执行监听
PropertyChangeListener listener = this.registerPropChangeListener(currentRowObj, rowIndex, prop);
propertyChanged也是这个监听数组里面的一个元素
第二种就不会注册监听,所以每次在firePropertyChange时,获取不到监听数组,所以不会二次调用propertyChanged
第一种注册监听会获取到监听数组 named是有值的,会二次触发propertyChanged
第二种方式没有监听,named数组无值,不会二次触发propertyChanged
-- 2023/12/18 评论区@风 大佬的方法测试
this.getModel().initValue("field",null,rowIndex);
this.getView().updateView("field", rowIndex);
结论:经测试,也可以有用,不会触发二次propertyChanged,该方法也是目前来说最简便的,可首选
跟了源码,流程如下:
1、执行initValue方法
2、跟this.getModel().setValue(fieldKey, null, rowIndex);方式执行方式是一样的,也会注册监听,也会走监听
3、但是走到onPropertyChanged方法时,因为时init时刻设置值,所以isChange标识为false,所以不会执行OnPropertyChanged方法,所以避免了二次触发
如果谁还有更简便的方案,可以大家一起讨论~~~
本文转载自:金蝶云社区
作者:蒋经东
原文链接:https://vip.kingdee.com/article/522835450398934784?channel_level=金蝶云社区|搜索|综合&productLineId=29&lang=zh-CN
推荐阅读