代码之家  ›  专栏  ›  技术社区  ›  Lars MH

Aurelia:在顶层声明自定义元素并跨应用程序访问

  •  0
  • Lars MH  · 技术社区  · 6 年前

    我有一个名为loading bar的自定义元素,它在我的应用程序的许多页面中使用。它的目的是在加载、下载内容时显示状态消息,并为后端操作提供响应消息。

    加载杆。html:

    <template show.bind="visible">
        <i class="fa fa-circle-o-notch fa-spin fa-fw" if.bind="type==1"></i>
        <i class="fa fa-check fa-fw" if.bind="type==2"></i>
        <span id="loading-text">${message}</span>
    </template>
    

    加载杆。ts:

    import { customElement, bindable, bindingMode, inject } from 'aurelia-framework';
    
    @customElement('loading-bar')
    export class LoadingBarCustomElement {
        private visible = false;
        @bindable({ defaultBindingMode: bindingMode.twoWay }) message;
        @bindable({ defaultBindingMode: bindingMode.twoWay }) type = 1;
    
    
        constructor() {
            this.visible = false;
        }
    
        messageChanged(newValue, oldValue) {
            if (newValue && newValue !== '')
                this.visible = true;
            else
                this.visible = false;
        }
    }
    

    目前,所有使用加载栏的页面都在其html中声明了此元素:

    <loading-bar message.bind="loadMsg" type.bind="loadType"></loading-bar>
    

    加载栏通过更改每个页面中的loadMsg和loadType局部变量来控制。

    我想做的是在just-on-place声明加载栏html,并且能够(从任何页面)调用像“showBar(msg,type)”这样的方法,这将影响全局声明的加载栏。

    我的第一个想法是在应用程序中声明加载栏。html(就像这里声明的导航栏一样)并注入一个类(在所有页面的ViewModel中),该类包含控制加载栏的showBar(msg,type)方法。

    我不确定这是否是正确的前进方向,也不确定它是如何最好地实现的,我希望能得到一些帮助。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Ashley Grant    6 年前

    您可以使用 EventAggregator 启用您要执行的操作。

    加载杆。ts

    import { customElement, bindable, bindingMode, autoinject } from 'aurelia-framework';
    import { EventAggregator, Subscription } from 'aurelia-event-aggregator';
    
    @customElement('loading-bar')
    @autoinject()
    export class LoadingBarCustomElement {
        private visible = false;
        private sub1: Subscription;
        private sub2: Subscription;
        @bindable({ defaultBindingMode: bindingMode.twoWay }) message;
        @bindable({ defaultBindingMode: bindingMode.twoWay }) type = 1;
    
    
        constructor(private ea : EventAggregator ) {
            this.ea = ea;
            this.visible = false;
        }
    
        attached() {
          this.sub1 = this.ea.subscribe('show-loading', ({ message, type }) => {
            this.type = type;
            this.message = message;
          });
    
          this.sub2 = this.ea.subscribe('hide-loading', () => {
            this.message = '';
          });
        }
    
        detached() {
          this.sub1.dispose();
          this.sub2.dispose();
        }           
    
        messageChanged(newValue, oldValue) {
            if (newValue && newValue !== '')
                this.visible = true;
            else
                this.visible = false;
        }
    }
    

    然后在应用程序的其他位置发布事件,如下所示:

    import {autoinject} from 'aurelia-framework';
    import {EventAggregator} from 'aurelia-event-aggregator';
    
    @autoinject()
    export class ExamplePage {
        constructor(private ea: EventAggregator){
        ...
        }
    
        async methodUsingTheLoadingBar(){
            ...
            this.ea.publish( 'show-loading, { message: 'Loading...', type: 1 });
            const foo = await getData();
            ...
            ...
            this.ea.publish('hide-loading');
        }
    }
    
        2
  •  -1
  •   Lars MH    6 年前

    决定这样解决:

    <loading-bar message.bind="lbc.loadMsg" type.bind="lbc.loadType"></loading-bar>
    

    已添加到应用。html

    创建了将用作单例的控制器类:

    export class LoadingBarController {
        private loadMsg = '';
        private loadType = 1;
    
        public showBar(message, type) {
            this.loadType = type;
            this.loadMsg = message;
        }
        public hideBar() {
            this.loadMsg = '';
        }
    }
    

    这是在应用程序中注入的。ts(别名为“lbc”),它实际上连接到加载栏元素,并注入到想要使用加载栏的页面的每个viewModel中。 然后通过注入控制器控制加载杆,如下所示:

    @inject(LoadingBarController)
    export class ExamplePage {
        constructor(private lbc: LoadingBarController){
        ...
        }
    
        methodUsingTheLoadingBar(){
            ...
            this.lbc.ShowBar('Loading...', 1);
            ...
            ...
            this.lbc.HideBar();
        }
    }