getOwnerComponent在按需嵌入哪个视图的控制器中返回未定义

问题描述

如果满足某些要求,我想将第二个视图嵌套到我的根视图中。通过创建XMLView对象并将其添加<page>元素的<App>聚合中,可以很好地工作。但是,当我尝试通过manifest.json访问认模型(由this.getownerComponent().getModel()文件创建)时,它会抛出:

未捕获的TypeError:无法读取未定义的属性'getModel'

它在根控制器中有效,但在嵌套控制器中,this.getownerComponent()再次返回了undefined

即使在根视图的开头添加视图,它也可以工作。也许我在控制器中添加错误的视图方式?


RootView.view.xml:

<mvc:View controllerName="test.demo.controller.RootView" xmlns:mvc="sap.ui.core.mvc">
    <App id="app" xmlns="sap.m">
        <Page id="page" title="{i18n>title}">
            <Button text="load nested view" press=".onLoadButtonPress"/>
        </Page>
    </App>
</mvc:View>

RootView.controller.js:

sap.ui.define([
    "sap/ui/core/mvc/Controller","sap/ui/core/mvc/XMLView"
],function (Controller,XMLView) {
    "use strict";

    return Controller.extend("test.demo.controller.RootView",{
        onLoadButtonPress: function () {
            this.mDefault = this.getownerComponent().getModel(); // works just fine
            alert(this.mDefault);
            XMLView.create({
                viewName: "test.demo.view.nestedView"
            }).then(function(oView) {
                this.byId("page").addContent(oView);
            }.bind(this));
        }
    });
});

nestedView.view.xml:

<mvc:View xmlns:mvc="sap.ui.core.mvc" controllerName="test.demo.controller.nestedView">
  <!-- ... -->
</mvc:View>

nestedView.controller.js:

sap.ui.define([
    "sap/ui/core/mvc/Controller"
],function (Controller) {
    "use strict";

    return Controller.extend("test.demo.controller.nestedView",{
        onInit: function () {
            this.mDefault = this.getownerComponent().getModel(); // throws Uncaught TypeError: this.getownerComponent() is undefined
            alert(this.mDefault);
        }
    });
});

manifest.json中,我添加GWSAMPLE_BASIC OData服务作为认模型。

解决方法

在JS上下文中创建视图(或任何其他元素)时,应在sap.ui.core.Component中的方法runAsOwner中进行。例如:

onLoadButtonPress: async function() {
  const fn = () => XMLView.create({ viewName: "test.demo.view.NestedView" });
  const oView = await this.getOwnerComponent().runAsOwner(fn);
  this.byId("page").addContent(oView);
},

发件人:https://embed.plnkr.co/29UrnDHpTHquNWuH?show=controller/Nested.controller.js,preview

根据API参考:

对象的所有权仅在创建对象时由框架检查。此后不进行检查或更新。并且只能在执行Component.runAsOwner函数的过程中检测到它。如果不采取进一步措施,则只有在构造UIComponent的内容或路由器创建新的View和它的内容。 (source)

然后在嵌套视图的控制器中,调用this.getOwnerComponent()应该返回组件而不是undefined,因此调用this.getOwnerComponent().getModel()也应该起作用。