Data binding UI5:格式化程序从XML视图多次调用或调用过快

Data binding UI5:格式化程序从XML视图多次调用或调用过快,data-binding,sapui5,formatter,Data Binding,Sapui5,Formatter,我正在使用OpenUI5。使用formatter.js,我在视图中格式化了一些文本 但我的格式化程序被调用了3次: 将模型绑定到面板控件时:oPanel.setModel(oModel,“data”) sBirthday和sFormat都是未定义的 完成onInit()并渲染视图后: sBirthday的值设置正确,而sFormat的值设置不正确 再次说明:sBirthday和sFormatara的估值正确 为什么会发生这种情况?是否正确? 应用程序收到错误,因为格式化程序中的ageDescri

我正在使用OpenUI5。使用
formatter.js
,我在视图中格式化了一些文本

但我的格式化程序被调用了3次:

  • 将模型绑定到面板控件时:
    oPanel.setModel(oModel,“data”)
    
    sBirthday
    sFormat
    都是
    未定义的

  • 完成
    onInit()
    并渲染视图后:
    sBirthday
    的值设置正确,而
    sFormat
    的值设置不正确

  • 再次说明:
    sBirthday
    sFormat
    ara的估值正确

  • 为什么会发生这种情况?是否正确?
    应用程序收到错误,因为格式化程序中的
    ageDescription()
    无法管理
    未定义的值

    formatter.js

    sap.ui.define([],function(){
    “严格使用”;
    返回{
    年龄描述:功能(sBirthday,sFormat){
    做某事;
    var sFromMyBd=时刻(sBirthday,sFormat).fromNow();
    做某事;
    还圣;
    }
    }
    });
    
    main.view.xml

    
    
    Main.controller.js

    sap.ui.define([
    “sap/ui/core/mvc/Controller”,
    “sap/ui/model/json/JSONModel”,
    “模型/格式化程序”
    ],函数(控制器、JSONModel、格式化程序){
    “严格使用”;
    返回Controller.extend(“Controller.main”{
    格式化程序:格式化程序,
    onInit:function(){
    var-oModel=new-JSONModel();
    var oView=this.getView();
    oModel.loadData(“model/data.json”);
    var oPanel=oView.byId(“用户面板id”);
    oPanel.setModel(oModel,“数据”);
    做某事;
    },
    });
    });
    
    data.json

    • 仅当数据请求完成时,才将模型设置为视图:

      onInit:function(){
      const dataUri=sap.ui.require.toUri(“/model/data.json”);
      const model=newjsonmodel(dataUri);
      model.attachEventance(“requestCompleted”,function()){
      this.getView().setModel(model);
      },这个);
      // ...
      },
      
      这确保了格式化程序只被调用一次(由绑定初始化时发生的
      checkUpdate(true
      调用;请参见下文),之后不会检测到进一步的更改

    • 另外(或者)使格式化程序更具防御性。比如:

      函数(值1、值2){
      让结果=”;
      如果(值1和值2){
      //相应的格式。。。
      }
      返回结果;
      }
      

    为什么会发生这种情况

  • 视图被实例化
  • 调用控制器的onInit
  • 。这里,请求文件
    model/data.json
    (model为空)
  • 将视图添加到UI时,UI5会传播现有父视图 将模型添加到视图中
  • 视图中的绑定被初始化,在每个绑定中触发
    checkUpdate(/*forceUpdate*/true
  • 由于激活了
    forceUpdate
    标志,将触发
    change
    事件,即使根本没有任何更改,也会强制触发格式化程序:
    [未定义,未定义]
    → <代码>[未定义,未定义]
    -第一次格式化程序调用
  • 获取
    model/data.json
    现在已经完成。现在,模型需要再次
    检查update
  • [未定义,未定义]
    → <代码>[值1,未定义]→ 检测到的更改→ 第二次格式化程序调用
  • [value1,未定义]
    → <代码>[value1,value2]→ 检测到的更改→ 第三次格式化程序调用

  • 现在,考虑到您正试图将静态JSON文件加载到项目中,最好最大限度地利用
    manifest.JSON

    这样,您就可以确保在进行任何绑定之前,数据已经加载并在模型中可用

    您可以通过在sap.app下添加JSON文件作为数据源来实现这一点

    manifest.json

    现在,只需将名为
    data
    dataSource
    添加为sap.ui5下的
    模型之一

    "sap.ui5": {
        "rootView": {
            "viewName": "com.sample.app.view.App",
            "type": "XML"
        },
        "models": {
            "i18n": {
                "type": "sap.ui.model.resource.ResourceModel",
                "settings": {
                    "bundleName": "com.app.sample.i18n.i18n"
                }
            },
            "data": {
                "type": "sap.ui.model.json.JSONModel",
                "dataSource": "data"
            }
        }
    }
    
    有了这个,你就不必再叫它了

    var oModel = new JSONModel();
    var oView = this.getView();
    oModel.loadData("model/data.json");
    var oPanel = oView.byId("user-panel-id");
    oPanel.setModel(oModel,"data"); 
    
    …作为我们在
    manifest.json
    中添加的
    数据模型
    ,从一开始就可以看到
    oView
    oPanel


    这样,格式化程序是否被多次调用并不重要,因为它从一开始就已经有了可用的数据。

    也在考虑提出同样的建议,但在测试它时,我意识到UI5实际上并不等待加载模型数据。因为数据负载通常很小,所以它会工作很多次,但是一旦数据负载变大或者出现延迟问题,格式化程序就会被再次调用多次。嗯,是的,我明白你的意思。我的工作假设他的数据负载确实很小,因为他的
    data.json
    似乎只加载一个“用户”。在任何情况下,对于更大的数据集,我可能也会选择类似于您的解决方案Boghyon的东西。谢谢你指出这一点。
    "sap.ui5": {
        "rootView": {
            "viewName": "com.sample.app.view.App",
            "type": "XML"
        },
        "models": {
            "i18n": {
                "type": "sap.ui.model.resource.ResourceModel",
                "settings": {
                    "bundleName": "com.app.sample.i18n.i18n"
                }
            },
            "data": {
                "type": "sap.ui.model.json.JSONModel",
                "dataSource": "data"
            }
        }
    }
    
    var oModel = new JSONModel();
    var oView = this.getView();
    oModel.loadData("model/data.json");
    var oPanel = oView.byId("user-panel-id");
    oPanel.setModel(oModel,"data");