Aurelia如何将所有属性转发到自定义组件中的子元素
我在不同的项目中使用React和Aurelia 我的Aurelia应用程序变得非常复杂,我非常想处理重复的逻辑。假设我想要一个节流按钮,它将等待异步请求再次被单击,使用React它非常简单: 我希望我的Aurelia如何将所有属性转发到自定义组件中的子元素,aurelia,Aurelia,我在不同的项目中使用React和Aurelia 我的Aurelia应用程序变得非常复杂,我非常想处理重复的逻辑。假设我想要一个节流按钮,它将等待异步请求再次被单击,使用React它非常简单: 我希望我的与本机具有完全相同的行为,除非它会自动阻止多个请求发生,直到前一个请求完成或失败: class MyComponent extends Component { handleClick = async e => { const response = await this.longR
与本机
具有完全相同的行为,除非它会自动阻止多个请求发生,直到前一个请求完成或失败:
class MyComponent extends Component {
handleClick = async e => {
const response = await this.longRequest(e)
console.log(`Received: `, response)
}
longRequest = async e => {
return new Promise((res, rej) => {
setTimeout(() => { res(e) }, 1000)
})
}
render() {
return <div>
<button className="btn" onClick={this.handleClick}>Click me</button>
<ThrottledButton className="btn" onClick={this.handleClick}>Click me</ThrottledButton>
</div>
}
}
类MyComponent扩展组件{
handleClick=async e=>{
const response=等待此.longRequest(e)
log(`Received:`,response)
}
longRequest=async e=>{
返回新承诺((res,rej)=>{
setTimeout(()=>{res(e)},1000)
})
}
render(){
返回
点击我
点击我
}
}
下面是
的一个实现:
class ThrottledButton扩展组件{
建造师(道具){
超级(道具)
this.state={operating:false}
}
render(){
const{onClick,…restProps}=this.props
const decoratedOnClick=async e=>{
如果(本状态操作)返回
this.setState({operating:true})
试一试{
等待承诺。解决(点击(e))
this.setState({operating:false})
}捕捉(错误){
this.setState({operating:false})
失误
}
}
返回{this.props.children}
}
}
现在我真的想在Aurelia中实现相同(或类似)的功能,下面是用例组件:
<template>
<require from="components/throttled-button"></require>
<button
class="btn"
click.delegate="handleClick($event)">
Click me
</button>
<throttled-button
class="btn"
on-click.bind="handleClick">
Click me
</throttled-button>
</template>
export class MyComponent {
handleClick = async e => {
const response = await this.longRequest(e)
console.log(`Received: `, response)
}
async longRequest(e) {
return new Promise((res, rej) => {
setTimeout(() => { res(e) }, 1000)
})
}
}
点击我
点击我
导出类MyComponent{
handleClick=async e=>{
const response=等待此.longRequest(e)
log(`Received:`,response)
}
异步长请求(e){
返回新承诺((res,rej)=>{
setTimeout(()=>{res(e)},1000)
})
}
}
这是我目前的节流按钮:
<template>
<button click.delegate="decoratedClick($event)" class.bind="class">
<slot></slot>
</button>
</template>
export class ThrottledButton {
@bindable onClick = () => {}
@bindable class
constructor() {
this.operating = false
}
decoratedClick = async e => {
console.log(this.operating)
if (this.operating) return
this.operating = true
try {
await Promise.resolve(this.onClick(e))
this.operating = false
} catch (err) {
this.operating = false
throw err
}
}
}
导出类节流按钮{
@可绑定onClick=()=>{}
@可绑定类
构造函数(){
这是错误的
}
装饰点击=异步e=>{
console.log(this.operating)
如果(本操作)返回
这是真的
试一试{
等待承诺。解决(这个。点击(e))
这是错误的
}捕捉(错误){
这是错误的
失误
}
}
}
如您所见,
与本机的
有很大不同,尤其是:
传播
运算符,我必须手动传递绑定的每个属性
至
至本机按钮。对于大多数组件,它是一个
巨大的努力可能会导致许多错误<template>
<button ref="btn">
<slot></slot>
</button>
</template>
@inject(Element)
export class ThrottledButton {
constructor(el) {
this.el = el
this.operating = false
}
attached = () => {
this.btn.addEventListener('click', this.forwardEvent)
}
detached = () => {
this.btn.removeEventListener('click', this.forwardEvent)
}
forwardEvent = e => {
this.operating = true
this.el.dispatchEvent(e) // no way to get the promise
}
}
@注入(元素)
导出类节流按钮{
建造师(el){
this.el=el
这是错误的
}
附件=()=>{
this.btn.addEventListener('click',this.forwardEvent)
}
分离=()=>{
this.btn.removeEventListener('单击',this.forwardEvent)
}
forwardEvent=e=>{
这是真的
this.el.dispatchEvent(e)//无法获得承诺
}
}
但是,无法获得对承诺的引用,这使得节流变得不可能
有没有希望在奥雷利亚解决这些问题?任何想法都将不胜感激。您可以使用自定义属性来解决此问题。这是typescript中的代码
import { autoinject, customAttribute } from 'aurelia-framework';
@customAttribute('single-click')
@autoinject()
export class SingleClickCustomAttribute {
clicked: (e: Event) => void;
private value: () => Promise<any>;
private executing: boolean = false;
constructor(
private element: Element
) {
this.clicked = e => {
if (this.executing) {
return;
}
this.executing = true;
setTimeout(async () => {
try {
await this.value();
}
catch (ex) {
}
this.executing = false;
}, 100);
};
}
attached() {
this.element.addEventListener('click', this.clicked);
}
detached() {
this.element.removeEventListener('click', this.clicked);
}
}
从'aurelia framework'导入{autoinject,customAttribute};
@customAttribute('单击')
@自动注入()
导出类SingleClickCustomAttribute{
点击:(e:事件)=>作废;
私人价值:()=>承诺;
私有执行:boolean=false;
建造师(
私有元素:元素
) {
this.clicked=e=>{
如果(这个正在执行){
返回;
}
this.executing=true;
setTimeout(异步()=>{
试一试{
等待这个值();
}
捕获(ex){
}
此参数=false;
}, 100);
};
}
附({
this.element.addEventListener('click',this.clicked');
}
分离的(){
this.element.removeEventListener('click',this.clicked');
}
}
像这样使用它
<button single-click.call="someAsyncMethod()" type="button">...</button>
。。。
要调用的异步方法应如下所示:
async someAsyncMethod(): Promise<void> {
await this.saveData();
}
async someAsyncMethod():承诺{
等待此消息。saveData();
}
诀窍是使用.call传递异步函数,并使用state属性。感谢您的回复。这些作品很棒,也很整洁。但我仍然想知道是否有任何方法可以将所有的道具传给某个孩子,这是一种非常有用的组合/继承模式。
async someAsyncMethod(): Promise<void> {
await this.saveData();
}