【问题标题】:Aurelia view inheritance gives odd behavior (typescript skeleton)Aurelia 视图继承给出了奇怪的行为(打字稿骨架)
【发布时间】:2020-05-13 03:10:16
【问题描述】:

我最近开始尝试 Aurelia(我是 Javascript 的新手,并且习惯于类型化语言,所以我正在使用 typescript 框架),我遇到了一些我不理解的视图继承的奇怪问题。

我想创建两个具有通用功能的视图,这就是为什么我想创建一个两个视图都可以扩展的通用超类。然而,这导致了意外行为:当在 app.html 中包含两个视图时,仅显示两个视图之一,具体取决于 require 语句的顺序。

我在下面包含了一个小的最小示例:

父视图.ts

import {bindable} from 'aurelia-framework';   

export abstract class ParentView {
    @bindable title: string;
}

child-a-view.html

<template><div>${title} A</div></template>

child-a-view.ts

import {ParentView} from './parent-view'

export class ChildAView extends ParentView {
    constructor() {
        super()
    }
}

child-b-view.html

<template><div>${title} B</div></template>

child-b-view.ts

import {ParentView} from './parent-view'

export class ChildBView extends ParentView {
    constructor() {
        super()
    }
}

app.ts

export class App {}

app.html

<template>
    <require from="./child-a-view"></require>
    <child-a-view title="TitleA"></child-a-view>

    <require from="./child-b-view"></require>
    <child-b-view title="TitleB"></child-b-view>
</template>

这会给出一个包含文本“TitleA B”的页面作为输出,而我希望有两行“TitleA A”和“TitleB B”。

app.html 中 require 语句的另一种顺序

<template>
    <require from="./child-b-view"></require>
    <require from="./child-a-view"></require>
    <child-a-view title="TitleA"></child-a-view>
    <child-b-view title="TitleB"></child-b-view>
</template>

给出一个包含文本“TitleB A”的页面作为输出,而我再次希望有两行“TitleA A”和“TitleB B”。

这是 Aurelia 中的一个错误,是否不允许继承视图类,还是我在这里做错了什么导致了这个?

【问题讨论】:

    标签: typescript aurelia


    【解决方案1】:

    这不一定是 Aurelia 中的错误,更多的是 JavaScript 的一般问题。但是,是的,众所周知,自定义元素的继承存在问题,因此不建议这样做。

    Aurelia 强烈支持组合而不是继承。

    如果您需要在两个或多个 ViewModel 之间共享公共代码,请尝试以另一种方式处理它:使用“公共”代码创建一个 ViewModel,然后将您本来会放入子项的 stuff 变量视图模型。

    另见this similar question

    正如@Alec Buchanan 已经指出的那样,您可以使用compose 轻松地将两个视图组合成一个自定义元素(从而实现与继承 ViewModel 相同的效果)。

    例如:

    child-a-view.html

    <template><div>${title} A</div></template>
    

    child-b-view.html

    <template><div>${title} B</div></template>
    

    parent-view.ts

    import {bindable} from 'aurelia-framework';   
    
    export class ParentView {
        @bindable title: string;
    }
    

    parent-view.html

    <template>
        <compose view="./child-a-view.html"></compose>
        <compose view="./child-b-view.html"></compose>
    </template>
    

    这将自动将子视图的绑定上下文设置为父视图的绑定上下文,这意味着您可以将子视图的 html 文件当作 parent-view.ts 是它们的 ViewModel。

    【讨论】:

    • 感谢您的建议。就我而言,这确实是一种很好的方法,因为几乎所有功能对于两种视图都是通用的。它还有助于后续步骤之一(我想要一个“元”组件,它可以根据上下文在 child-a 视图和 child-b 视图之间切换)。我确实注意到,对于一个特定的视图,我目前不得不在视图中塞入太多的逻辑,因为它不适合通用模型。有没有办法例如向视图添加第二个模型来解决这种情况?
    • 有几种方法可以解决这个问题,但最好的方法在很大程度上取决于您所指的逻辑。如果您可以将有问题的模型/视图放在一个要点中,我可以看看它。 gist.run/?id=883568d7c8e2add9ed393150100f4744
    【解决方案2】:

    是否有必要尝试将这些模块用作自定义元素?你能不使用 compose 元素来包含每个元素吗?

    例如

    <template>
        <compose view-model="childAView" view="./child-a-view"></compose>
        <compose view-model="childBView" view="./child-b-view"></compose>
    <template>
    

    【讨论】:

      【解决方案3】:

      派生类需要自己的行为。在您的情况下,您需要在子类上至少有一个装饰器来告诉 Aurelia 正确继承它。

      【讨论】:

        猜你喜欢
        • 2017-07-18
        • 1970-01-01
        • 2021-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-04
        • 2018-02-23
        相关资源
        最近更新 更多