3

是否可以在运行时动态定义自定义组件模板中的元素类型?

我想避免在以下示例中重复buttonand元素的内部内容:a

<template>
    <button if.bind="!isLinkBtn">
        <span class="btn-icon">${icon}</span>
        <span class="btn-text">${contentText}</span>
    </button>

    <a if.bind="isLinkBtn">
        <!--
        The content is a 1:1 duplicate of the button above which should be prevented
        somehow in order to keep the view DRY
        -->
        <span class="btn-icon">${icon}</span>
        <span class="btn-text">${contentText}</span>
    </a>
</template>

是否可以写这样的东西:

<template>
    <!--
    The type of element should be defined at runtime and can be a standard HTML "button"
    or an anchor "a"
    -->
    <element type.bind="${isLinkBtn ? 'a' : 'button'}">
        <span class="btn-icon">${icon}</span>
        <span class="btn-text">${contentText}</span>
    </element>
</template>

我知道动态组合,<compose view="${widget.type}-view.html"></compose>但据我所知,这不允许我创建默认 HTML 元素,而只能创建自定义组件,对吗?

我在 Aurelia Gitter 上问过这个问题,Erik Lieben 建议使用@processContent(function)装饰器,替换给定内容中的内容function并返回true让 Aurelia 处理它。

不幸的是,我不知道如何实际应用这些说明,并希望在这里提供一些替代方法或有关如何实际完成此操作的一些细节。


编辑

我已经创建了相应的功能请求。即使已经提供了可能的解决方案,我也希望看到一些更简单的方法来解决这个问题;)

4

2 回答 2

3

如果您想重用 HTML 片段,请使用 compose。这样做不会创建新的自定义元素。它只是在每个 compose 元素的位置包含 HTML。因此,包含的 HTML 的视图模型与组成它的元素相同。

看看这个 GistRun:https ://gist.run/?id=36cf2435d39910ff709de05e5e1bedaf

自定义链接.html

<template>
    <button if.bind="!isLinkBtn">
      <compose view="./custom-link-icon-and-text.html"></compose>
    </button>

    <a if.bind="isLinkBtn" href="#">
      <compose view="./custom-link-icon-and-text.html"></compose>
    </a>
</template>

自定义链接.js

import {bindable} from 'aurelia-framework';

export class CustomLink {
    @bindable() contentText;
    @bindable() icon;
    @bindable() isLinkBtn;
}

自定义链接图标和文本.html

<template>
    <span class="btn-icon">${icon}</span>
    <span class="btn-text">${contentText}</span>
</template>

消费者.html

<template>
  <require from="./custom-link"></require>
  <custom-link content-text="Here is a button"></custom-link>
  <custom-link is-link-btn.bind="true" content-text="Here is a link"></custom-link>
</template>

您可能希望将它们拆分为单独的元素,<custom-button><custom-link>不是使用is-link-btn属性来控制它们的呈现。您可以使用相同的技术来重用常见的 HTML 部分,并使用装饰器组合来重用公共代码。

请参阅此 GistRun:https ://gist.run/?id=e9572ad27cb61f16c529fb9425107a10

回复您的“不那么冗长”的评论

您可以将其归为一个文件,并避免compose使用上述GistRuninlineView装饰器中的技术:

请参阅此 GistRun:https ://gist.run/?id=4e325771c63d752ef1712c6d949313ce

您只需要一个文件:

自定义链接.js

import {bindable, inlineView} from 'aurelia-framework';

function customLinkElement() {
    return function(target) {
        bindable('contentText')(target);
        bindable('icon')(target);
  }
}


const tagTypes = {button: 'button', link: 'a'};


@inlineView(viewHtml(tagTypes.button))
@customLinkElement()
export class CustomButton {

}


@inlineView(viewHtml(tagTypes.link))
@customLinkElement()
export class CustomLink {

}


function viewHtml(tagType) {
  let result = `
    <template>
        <${tagType}${tagType === tagTypes.link ? ' href="#"' : ''}>
            <span class="btn-icon">\${icon}</span>
            <span class="btn-text">\${contentText}</span>
        </${tagType}>
    </template>
    `;

  return result;
}
于 2017-03-02T16:34:03.463 回答
1

抱歉,我一边看 gitter,一边同时做两件事,我显然不擅长 :-)

对于你最终想要完成的事情,这也可以吗?

我不是a11y专家,也不是该领域的很多知识,但据我了解,这将实现您想要的。浏览器将查看角色属性并将其作为链接或按钮处理,并忽略实际的元素类型本身/不关心它是按钮还是锚点,它的行为就像它是角色中定义的类型一样。

然后,您可以将其设置为带有 css 的按钮或链接标签。

<a role.bind="type"><span>x</span><span>y</span></a>

其中类型是链接或按钮,请参见:https ://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_link_role

于 2017-03-03T08:08:22.817 回答