2017-03-02 143 views
3

是否可以在運行時動態定義自定義組件模板內的元素類型?在運行時更改元素類型

我想,以避免在下面的示例中的buttona元件的內部重複內容:

<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元素,但只有自定義組件,是否正確?

我問過的奧裏利亞本的Gitter問題,其中埃裏克Lieben建議使用@processContent(function)裝飾,取代指定function內的內容,並返回true讓Aurelia路上對其進行處理。

不幸的是,我不知道如何實際應用這些說明,並希望在這裏找到一些替代方法或有關如何實際完成此操作的一些細節。


編輯

我創建了一個相應的feature request。儘管已經提供了可能的解決方案,但是我希望看到一些更簡單的方法來解決這個問題;)

+0

'processContent'不會在這種情況下幫助,因爲它不會有訪問視圖模型的屬性(如'isLinkBtn') 。 –

回答

3

當您要重用HTML片段時,請使用撰寫。這樣做不是創建一個新的自定義元素。它只是在每個撰寫元素的位置包含HTML。因此,包含的HTML的視圖模型與構成它的元素的視圖模型相同。

看看這個GistRun:https://gist.run/?id=36cf2435d39910ff709de05e5e1bedaf

定製link.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> 

定製link.js

import {bindable} from 'aurelia-framework'; 

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

定製鏈接圖標-and-text.html

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

consumer.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

迴應你的「不那麼冗長」評論

你可以把它降低到一個文件,並使用上述GistRun技術和inlineView裝飾避免compose

看到這個GistRun:https://gist.run/?id=4e325771c63d752ef1712c6d949313ce

所有您東東d是這樣的一個文件:

定製links.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; 
} 
+1

有一點需要記住的是,使用'compose'來引入小塊HTML會比僅僅不進行DRY和內聯代碼的性能低得多。在這個問題的具體例子中,我可能傾向於重複HTML而不是使用'compose'。如果我們引入更大的HTML組合,那麼這就更有意義了。你剛剛提到的答案是正確的。 –

+1

同意阿什利。如果不知道代碼將運行的上下文,就不可能知道性能是否會成爲問題。除非我知道運行時環境需要最高效率,否則我總是先開始使用DRY。然後,如果測試顯示不可接受的性能,我會故意違反DRY以提高速度。 –

+0

我希望以一種不太「冗長」的方式來實現這一點,它不需要拆分元素shell('button'或'a')&內容,因爲內容僅包含2個元素,它們「無法生存「獨立,因此並不需要成爲一個獨立的組件。 – suamikim

1

對不起,我同時做兩件事情,而看小膠質,對此我並不擅長顯然:-)

對於你想最終完成的事情,這也可以嗎?

我不是一個專家,或者在這個領域有很多知識,但從我的理解,這將完成你想要的。瀏覽器將查看角色屬性並將其作爲鏈接或按鈕進行處理,並忽略實際的元素類型本身/不會在乎它是按鈕還是錨點,它會像在角色中定義的類型那樣操作。

然後,你可以像使用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

+0

我想這會工作,即使我不能爭辯爲什麼,我仍然希望儘可能明確地使用語義正確的標記。在技​​術上不可能使用正確標記的情況下(例如,由'divs'組成的自定義'comboboxes'等等),我會使用'role'。感謝任何方式的建議! – suamikim