可组合的 Ractive js 组件
Composable Ractive js component
我正在开发代表 table 的 Ractive js 组件。它工作正常,但最近我添加了一些功能:过滤器、状态栏、左列复选框、table header。这个 table 组件在整个应用程序中无处不在。
问题是在不同的地方我只需要这些功能的一些组合。在当前的实现中,我在模板中有很多 if,我想去掉它们。
目前我想使用 decorator pattern 但不知道如何实现它,尤其是我需要弄乱核心 table 模板。
Table 模板:
{{#if status_bar}}
<table class="list-status">
<tbody>
<tr>
<td><input type="checkbox" checked="{{.select_all}}"></td>
<td>
{{#if has_filters}}
<span>Показать:</span>
{{#each filters:i}}
<button on-tap="@this.fire('activateFilter', event, i)" {{#if active}}class="active"{{/if}}>{{title}}</button>
{{/each}}
{{/if}}
{{#if ready}}
<span class="badge lists-badge">{{ collection.total_count }}</span>
{{#if selected.length > 0}}
<span class="badge lists-badge" style="background-color: red;">{{ selected.length }}</span>
{{/if}}
{{/if}}
</td>
</tr>
</tbody>
</table>
{{/if}}
<table class="{{class}}">
{{#if header}}
<thead>
<tr>
{{^hideSelectColumn}}
<th></th>
{{/hideSelectColumn}}
{{#each titles}}
<th class={{class}}>{{title}}</th>
{{/each}}
</tr>
</thead>
{{/if}}
<tbody>
{{#if ready}}
{{#each diff_create:i}}
<tr class="just-created">
{{^hideSelectColumn}}
<td class="{{firstColumnClass}}">
<div style="position: relative;"></div>
</td>
{{/hideSelectColumn}}
{{>pending}}
</tr>
{{/each}}
{{#if diff_create.length > 0}}
<tr>
<td colspan={{column_count}}></td>
</tr>
{{/if}}
{{#each page_models}}
<tr {{#if mfd}} class='mfd' {{/if}}>
{{^hideSelectColumn}}
<td class="{{firstColumnClass}}">
<input type="checkbox" class="list-checkbox" name='{{selected}}' value='{{@index}}'/>
<div style="position: relative;"></div>
</td>
{{/hideSelectColumn}}
{{>content}}
</tr>
{{/each}}
{{^page_models}}
<tr>
<td style='text-align:center; font-weight: bold; font-size: 15px' colspan={{column_count}}>Пусто!</td>
</tr>
{{/}}
{{/if}}
{{^ready}}
<tr>
<td style='text-align:center; font-weight: bold; font-size: 15px' colspan={{column_count}}>Загрузка...</td>
</tr>
{{/ready}}
</tbody>
</table>
<div class="pages">
{{#if pages_more_than_one}}
<ul class="pagination">
{{#if has_prev_page}}
<li class="arrow-left"><a on-tap='prevPage'><span class="icon-arrow-left4"></span></a></li>
{{/if}}
{{#each pages}}
<li class='{{@index+1==current_page ? "active": ""}}'><a on-tap='@this.fire("goToPage", @index+1)'>{{@index+1}}</a></li>
{{/each}}
{{#if has_next_page}}
<li class="arrow-right"><a on-tap='nextPage'><span class="icon-arrow-right8"></span></a></li>
{{/if}}
</ul>
{{/if}}
<div class="pages-count">
<select class="form-control" value="{{collection.perpage}}">
<option value='2'>2</option>
<option value='5'>5</option>
<option value='10'>10</option>
<option value='15'>15</option>
<option value='20'>20</option>
<option value='25'>25</option>
</select>
</div>
</div>
提前致谢。
Ractive 有 named yields,您可以在其中定义布局中的占位符,并让消费组件定义其中的内容。把它想象成一种布局机制。
一个简单的示例是模式,其中您有 header、body 和页脚,每个实例可能不同。模态组件只能定义为模态的布局(想想空的 bootstrap 模态)和一堆类似于插入 table 位置的收益率。
const Modal = Ractive.extend({
template: `
<div class="modal">
<div class="modal__header">{{yield header }}</div>
<div class="modal__body">{{yield body }}</div>
<div class="modal__footer">{{yield footer }}</div>
</div>
`
})
在消费组件上,您使用布局组件并定义这些位置的内容。请注意,yield 内容可以是 anything,甚至是其他组件。
const Page = Ractive.extend({
components: { Modal },
template: `
<div class="page">
<div class="page__stuff">
...
</div>
<Modal>
{{#partial header }}
This is the header
{{/partial}}
{{#partial body }}
This is the body
{{/partial}}
{{#partial footer }}
This is the footer
{{/partial}}
</Modal>
</div>
`
});
在您的情况下,您可以将 table 分解为组件(即过滤器、状态栏、左列复选框、table header)并定义布局组件。然后,你什么时候需要,你就用布局组件,随便塞进去什么地方。
一个更高级的功能是 Anchors. Together with ractive.attachChild()
and ractive.link()
,您可以手动将组件附加到锚点,on-the-fly。这本质上是 Ractive 在看到模板上的组件时如何挂载组件和绑定数据的方式。除了这一次,该功能在 API.
上公开
我正在开发代表 table 的 Ractive js 组件。它工作正常,但最近我添加了一些功能:过滤器、状态栏、左列复选框、table header。这个 table 组件在整个应用程序中无处不在。
问题是在不同的地方我只需要这些功能的一些组合。在当前的实现中,我在模板中有很多 if,我想去掉它们。
目前我想使用 decorator pattern 但不知道如何实现它,尤其是我需要弄乱核心 table 模板。
Table 模板:
{{#if status_bar}}
<table class="list-status">
<tbody>
<tr>
<td><input type="checkbox" checked="{{.select_all}}"></td>
<td>
{{#if has_filters}}
<span>Показать:</span>
{{#each filters:i}}
<button on-tap="@this.fire('activateFilter', event, i)" {{#if active}}class="active"{{/if}}>{{title}}</button>
{{/each}}
{{/if}}
{{#if ready}}
<span class="badge lists-badge">{{ collection.total_count }}</span>
{{#if selected.length > 0}}
<span class="badge lists-badge" style="background-color: red;">{{ selected.length }}</span>
{{/if}}
{{/if}}
</td>
</tr>
</tbody>
</table>
{{/if}}
<table class="{{class}}">
{{#if header}}
<thead>
<tr>
{{^hideSelectColumn}}
<th></th>
{{/hideSelectColumn}}
{{#each titles}}
<th class={{class}}>{{title}}</th>
{{/each}}
</tr>
</thead>
{{/if}}
<tbody>
{{#if ready}}
{{#each diff_create:i}}
<tr class="just-created">
{{^hideSelectColumn}}
<td class="{{firstColumnClass}}">
<div style="position: relative;"></div>
</td>
{{/hideSelectColumn}}
{{>pending}}
</tr>
{{/each}}
{{#if diff_create.length > 0}}
<tr>
<td colspan={{column_count}}></td>
</tr>
{{/if}}
{{#each page_models}}
<tr {{#if mfd}} class='mfd' {{/if}}>
{{^hideSelectColumn}}
<td class="{{firstColumnClass}}">
<input type="checkbox" class="list-checkbox" name='{{selected}}' value='{{@index}}'/>
<div style="position: relative;"></div>
</td>
{{/hideSelectColumn}}
{{>content}}
</tr>
{{/each}}
{{^page_models}}
<tr>
<td style='text-align:center; font-weight: bold; font-size: 15px' colspan={{column_count}}>Пусто!</td>
</tr>
{{/}}
{{/if}}
{{^ready}}
<tr>
<td style='text-align:center; font-weight: bold; font-size: 15px' colspan={{column_count}}>Загрузка...</td>
</tr>
{{/ready}}
</tbody>
</table>
<div class="pages">
{{#if pages_more_than_one}}
<ul class="pagination">
{{#if has_prev_page}}
<li class="arrow-left"><a on-tap='prevPage'><span class="icon-arrow-left4"></span></a></li>
{{/if}}
{{#each pages}}
<li class='{{@index+1==current_page ? "active": ""}}'><a on-tap='@this.fire("goToPage", @index+1)'>{{@index+1}}</a></li>
{{/each}}
{{#if has_next_page}}
<li class="arrow-right"><a on-tap='nextPage'><span class="icon-arrow-right8"></span></a></li>
{{/if}}
</ul>
{{/if}}
<div class="pages-count">
<select class="form-control" value="{{collection.perpage}}">
<option value='2'>2</option>
<option value='5'>5</option>
<option value='10'>10</option>
<option value='15'>15</option>
<option value='20'>20</option>
<option value='25'>25</option>
</select>
</div>
</div>
提前致谢。
Ractive 有 named yields,您可以在其中定义布局中的占位符,并让消费组件定义其中的内容。把它想象成一种布局机制。
一个简单的示例是模式,其中您有 header、body 和页脚,每个实例可能不同。模态组件只能定义为模态的布局(想想空的 bootstrap 模态)和一堆类似于插入 table 位置的收益率。
const Modal = Ractive.extend({
template: `
<div class="modal">
<div class="modal__header">{{yield header }}</div>
<div class="modal__body">{{yield body }}</div>
<div class="modal__footer">{{yield footer }}</div>
</div>
`
})
在消费组件上,您使用布局组件并定义这些位置的内容。请注意,yield 内容可以是 anything,甚至是其他组件。
const Page = Ractive.extend({
components: { Modal },
template: `
<div class="page">
<div class="page__stuff">
...
</div>
<Modal>
{{#partial header }}
This is the header
{{/partial}}
{{#partial body }}
This is the body
{{/partial}}
{{#partial footer }}
This is the footer
{{/partial}}
</Modal>
</div>
`
});
在您的情况下,您可以将 table 分解为组件(即过滤器、状态栏、左列复选框、table header)并定义布局组件。然后,你什么时候需要,你就用布局组件,随便塞进去什么地方。
一个更高级的功能是 Anchors. Together with ractive.attachChild()
and ractive.link()
,您可以手动将组件附加到锚点,on-the-fly。这本质上是 Ractive 在看到模板上的组件时如何挂载组件和绑定数据的方式。除了这一次,该功能在 API.