当自定义元素加载时,从 activate() 返回 Promise
Return Promise from activate() when customElements have loaded
我知道Aurelia允许我们从VM的activate()
方法返回Promise()
,如果是这样,它将等待承诺解析,然后再切换到新视图。
但是,假设我有一个由一个或多个子组件组成的视图,并且它们都发出 HTTP 请求,我怎么知道所有子组件何时从我的父组件中完成?
奖励问题:只有进入<router-outlet>
的 VM 使用 activate()
方法,而用作自定义元素的 VM 使用 attached()
方法是否正确?
编辑:为了详细说明,这是我的一个页面/路线/主视图可能的样子:
<template>
<main>
<section id="item">
<h1>${item.title}</h1>
<img src="${item.image}">
<p>${item.description}</p>
<ul>
<li repeat.for="si of item.subItems">
${si.subItem}
</li>
</ul>
</section>
<aside>
<author-info></author-info>
<recent-items limit="3"></recent-items>
<random-quote></random-quote>
</aside>
</main>
</template>
我可以轻松地等待${item}
加载,然后在主视图的 activate
方法中解析 promise,但这并不能保证aside
中的三个子元素已加载。这使得它们一个接一个地弹出,看起来不太好。
如果可能的话,我非常想使用 Aurelia的内置功能,但我想我可能不得不使用 EventAggregator 或 Ashley 建议的双向绑定来求助于我自己的加载器。
很想听听Aurelia团队中的某个人关于这是否可能?
加载路由activate()
回调中的所有数据
正如 Ashley 在上面的评论中指出的那样,最佳策略是加载父路由中的所有数据,并通过绑定将该数据推送到自定义元素中。您提到这会导致在包含该元素的每个路由中复制/粘贴代码,但我们可以通过将加载代码移动到服务类并将该类注入路由来解决此问题。这样,我们可以保持代码干燥,同时保持其简单易读。
我们将通过创建一个<random-quote>
自定义元素以及一个将为我们提供随机报价的服务来演示。
randomQuoteCustomElement.ts
export class RandomQuoteCustomElement {
@bindable quote: IQuote;
}
randomQuoteCustomElement.html
<template>
<i>${quote.text}</i>
<strong>${quote.author}</strong>
</template>
随机报价服务.ts
export class RandomQuoteService {
getRandomQuote: Promise<IQuote>() {
return this.http.fetch('api/quote/random')
.then((response) => response.json())
});
}
}
接下来,我们将在视图中包含自定义元素,将服务注入视图模型,通过服务获取数据,并使activate()
方法依赖于返回的承诺。
主目录
import { RandomQuoteService} from './randomQuoteService';
@inject(RandomQuoteService)
export class MainViewModel {
quote: IQuote;
constructor(quotes: RandomQuoteService) {
this.quotes = quotes;
}
activate() {
return Promise.all([
this.quotes.getRandomQuote()
.then((quote) => this.quote = quote)
]);
}
}
主.html
<template>
<require from="./randomQuoteCustomElement"></require>
<random-quote quote.bind="quote"></random-quote>
</template>
因为我们希望我们的activate()
函数强烈依赖于RandomQuoteService
的结果,所以我们需要直接在activate()
回调中包含此代码。我们还可以设计自定义元素以允许绑定数据,但回退到获取自己的数据,利用相同的服务。
randomQuoteCustomElement.ts
export class RandomQuoteCustomElement {
@bindable quote;
constructor(quotes) {
if (!this.quote) {
quotes.getRandomQuote()
.then((quote) => !this.quote && this.quote = quote);
}
}
}
下面是一个工作示例:https://gist.run/?id=c5570192afe5631355efe6b5da3e44b5
我不确定如此复杂的链具有activate
和attached
,但您可以随时使用自定义事件。
在父元素activate
:
return new Promise((resolve, reject) => {
var subscription = this.eventAggregator.subscribe('child-element-loaded', e => {
subscription.dispose();
resolve();
});
});
在自定义元素中,您需要在需要时触发此事件:
this.eventAggregator.publish('child-element-loaded');
当然,您需要导入事件聚合器
import {EventAggregator} from 'aurelia-event-aggregator';
并将其注入到子元素和父元素中。
如果在呈现视图之前必须返回多个 http 调用,则可以使用 Promise.all
,然后将结果绑定到子组件。例如:
activate () {
let promise1 = new Promise()...;
let promise2 = new Promise()...;
let promise3 = new Promise()...;
return Promise.all([promise1, promise2, promise3]);
//bind the results to children components
}
这样,activate()
将等待所有的承诺。但是,正如@AshleyGrant在他的评论中所说,您应该小心这一点。这可能会导致过程缓慢。
- 节点导出返回一个空对象
- ES6构造函数返回基类的实例
- 监视函数从服务返回不起作用,但作用域函数起作用
- 控制台返回var不是't定义,但它是
- 从函数返回角度承诺
- Javascript返回值只在循环中返回一次
- 从控制器返回后Ajax启动事件激发
- CKFinder 3为所选文件返回错误的URL
- 如何在d3.js中返回路径的y坐标
- 如何从jquery函数返回变量
- Angular js-返回一个包含类似
- JSONP请求返回结果,但也触发error_callback
- 如何使用Spring MVC将Facebook返回的响应数据保存在Java类中
- 从HTTPGET返回一个自定义对象列表,以便在Angular 2应用程序中使用
- JS验证ajax返回的html中的表单数据
- 使用谷歌应用程序脚本将服务器端数据表返回到客户端
- AJAX:$_GET不返回任何值
- 从Javascript方法返回全局变量
- Meteor方法在客户端返回null,在客户端运行的相同方法返回正确的值
- 当自定义元素加载时,从 activate() 返回 Promise