函数中的 Aurelia 自定义元素 bubbling/delegating?

Aurelia custom element bubbling/delegating from within a function?

我有一个自定义元素,它在跨度中显示一些文本,如果用户决定编辑文本,我会隐藏跨度并显示文本输入。 当用户将注意力从文本输入上移开时,我会隐藏输入并使用更新后的文本再次显示范围。 这一切都很好。

当我在页面上使用自定义元素时,我需要能够在页面上触发一个函数以从自定义元素中获取更新的文本以更新数据库中的文本。

当用户完成编辑文本并且我重新显示跨度时,我不知道如何冒出该事件以便调用页面上的函数来保存更改。 如果我使用的是按钮或其他东西,我可以为按钮点击设置委托,但不知道如何实现,因为我没有使用按钮。

希望这是有道理的!提前致谢!

这是一些精简代码。

自定义-element.html:

<i if.bind="icon" class="${icon}"></i><span if.bind="!(allowEditTitle && isEditingTitle)" maxlength>${title}</span>
<input ref="titleInputEditor" type="text" value.bind="title" if.bind="allowEditTitle && isEditingTitle" maxlength="100" />

自定义-element.ts

@bindable title: string;
@bindable allowEditTitle: boolean = false;
isEditingTitle: boolean = false;

toggleEditTitle() {
    let me = this;
    if (this.allowEditTitle === true) {
        this.isEditingTitle = !this.isEditingTitle;
    }
    if (this.isEditingTitle == true) {
        window.setTimeout(function () {
            $(me.titleInputEditor).focus();
            $(me.titleInputEditor).select();
            $(window).one('click', function () {
                if (me.isEditingTitle == true) {
                    me.toggleEditTitle();
                } 
            });
            $(me.titleInputEditor).one('click', function (e) {
                e.stopPropagation();
            });
            $(me.titleInputEditor).one('focusout', function () {
                me.toggleEditTitle();
            });
        });
    }
}

app.html

<custom-element title="Default Text" 
        allow-edit-title.bind="true" 
        on-???????.call="saveTextFunction">
</custom-element>

您可以使用 aurelia-event-aggregator 来完成此操作。您可以在 focusout 上发布一个事件,然后在代码中的其他地方订阅该事件(很可能是某个地方的服务),这将更新您的数据库。


自定义-element.ts

import { autoinject, EventAggregator } from "aurelia-framework";

@autoinject
export class CustomElement {
  constructor(private ea: EventAggregator)


...

        $(me.titleInputEditor).one('focusout', function () {
            me.ea.publish('input-changed', me.title);
            me.toggleEditTitle();
        });
...
}

service.ts

import { autoinject, EventAggregator } from "aurelia-framework";

@autoinject
export class Service {
  constructor(private ea: EventAggregator)

  public attached() {
    this.ea.subscribe('input-changed', (value) => {
       // update database using value
    });
  }
}

有关事件聚合器的更多文档,请参阅 here

据我所知,您尝试绑定一个函数。这是通过 .call 绑定完成的,没错。

将@bindable 属性添加到您的自定义元素并从适当的地方调用它

@binable onUpdateChanges: Function;
updateText(){
   if(this.onUpdateChanges)
      this.onUpdateChanges();
}

在app.html中这样绑定:

<custom-element title="Default Text" 
    allow-edit-title.bind="true" 
    on-update-changes.call="saveTextFunction()">
</custom-element>

在 app.ts 中添加 saveTextFunction

saveTextFunction(){
      //Do stuff to update/save/persist something
}

如果你想传递参数,你需要在你的自定义元素中注册 onUpdateChanges 略有不同

自定义-element.ts

updateText(){
   if(this.onUpdateChanges)
      this.onUpdateChanges({text: what_ever_value_you_want_to_pass});
}

app.html

<custom-element title="Default Text" 
    allow-edit-title.bind="true" 
    on-update-changes.call="saveTextFunction(text)">
</custom-element>

app.ts

 saveTextFunction(text:string){
      //Do stuff to update/save/persist something
}

Jesse 的答案 (EventAggregator) 如果您需要在位于应用中任意位置的两个元素之间传递信息(例如,“冒泡”并不总是有效),那么您可以采用这种方法

Schadensbegrenzer 的回答也适用于您的特定情况,但我个人认为通过可绑定对象传递函数更意味着将行为动态传递给自定义元素,而不是跨元素通信。

在你的情况下我会做的实际上是让事件冒泡。您可以像这样使用 CustomEvent 来完成此操作:

自定义-element.ts

$(me.titleInputEditor).one('focusout', function () {
    // it'd be slightly cleaner to inject `Element` in your CustomElement
    // and dispatch this event on that element instead
    me.titleInputEditor.dispatchEvent(new CustomEvent('input-changed', {
        detail: me, // if you want to pass this CustomElement instance up to the listener
        bubbles: true
    }));
    me.toggleEditTitle();
});

app.html

<custom-element title="Default Text" 
        allow-edit-title.bind="true" 
        input-changed.delegate="saveTextFunction">
</custom-element>