Да и Да.
Пользовательские теги хороши для разделения многократно используемых элементов HTML. Преимущества в том, что они безопасны для контекста, и вы можете передавать в них аргументы, чтобы изменить их поведение, чего вы не можете сделать с cfinclude
. Вы даже можете создавать вложенные теги, которые меняют свое поведение в зависимости от своих родителей. Большинство моих HTML-макетов в ColdFusion выглядят примерно так:
<cf_layout>
<cf_head title="My Page>
<!--- Some local head stuff ---->
</cf_head>
<cf_content>
Lots of stuff goes here.
</cf_content>
</cf_layout>
Это, очевидно, значительно упрощается, но я могу изменить весь макет сайта, изменив пользовательский тег или даже изменив папку пользовательского тега (например, динамический this.customTagPaths
для замены макетов.
Пользовательские теги не получают достаточно любви. Обними их и наслаждайся:).
Вот еще один пример того, что я делаю:
<cfset arOrders = OrderService.getOrders() />
<table>
<cfloop array="#arOrders#" index="currentOrder">
<cf_orderrow order="#currentOrder#" />
</cfloop>
</table>
Мой OrderRow
пользовательский тег обрабатывает весь экран для отображения строки заказа в таблице. Это включает в себя кнопки добавления / редактирования / удаления, вычисления, которые должны произойти, условия, которые должны быть выполнены для изменения отображения. Я могу отобразить строку заказа в любом месте в области администратора. На странице сведений о клиенте, на странице, показывающей все заказы за определенный период времени. Это не имеет значения. Мои пользователи знают, что в любом месте, где они видят строку, описывающую заказ, это будет выглядеть так, как они ожидают.
Вот еще несколько конкретных примеров небольших пользовательских тегов, которые я использую в нескольких приложениях.
cf_jquery
Это включает в себя jQuery и jQueryUI на странице, но только если ни один другой шаблон в приложении уже не добавил jQuery по этому запросу. Это позволяет мне создавать несколько частей jQuery на странице, и независимо от того, в каком порядке я их называю, я всегда буду знать, что jQuery был добавлен в заголовок документа только один раз.
<cfif thisTag.ExecutionMode EQ "end" AND (NOT StructKeyExists(Request, "JQueryInited") OR Request.JQueryInited EQ False)>
<cfparam name="Attributes.IncludeUI" default="False" />
<cfparam name="Request.jQueryUIInited" default="False" />
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<cfif Attributes.IncludeUI AND Request.jQueryUIInited IS False>
<link href="/shared/css/smoothness/jquery-ui-1.8.11.custom.css" rel="stylesheet" />
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js"></script>
<cfset Request.jQueryUIInited = True />
</cfif>
<cfset Request.JQueryInited = True />
</cfif>
Я даже создаю теги для небольшой информации, которая, как я знаю, будет использоваться во всем приложении в нескольких местах, например, тег cf_contact
:
<cfif thisTag.ExecutionMode EQ "end">
<cfparam name="Attributes.Phone" default="xxx.xxx.xxxx" />
<cfparam name="Attributes.Email" default="me@you.com" />
<cfparam name="Attributes.EmailName" default="Email Support" />
<h2 style="font: bold 12px Verdana, Geneva, Arial, Helvetica, sans-serif; margin-bottom: 0;">Contact Us</h2>
<p style="text-align: left; margin-top: 0;"><cfoutput>#Attributes.Phone#</cfoutput><br />
<cfoutput><a href="mailto:#Attributes.Email#">#Attributes.EmailName#</a></cfoutput></p>
</cfif>
Зачем делать тег для чего-то такого маленького? Почему бы и нет? Если в приложении все мои контактные данные будут одинаковыми (и я должен, чтобы пользователи могли легко их идентифицировать), я могу сделать для них тег так же легко, как и включить. Если я решу, что я хочу, чтобы там происходило какое-то другое программное поведение, мое приложение уже настроено для его использования.
cf_timeblock
Этот пользовательский тег показывает набор списков выбора для выбора временного блока (чч: мм тт). Я использую это во всем приложении, занимающемся планированием, поэтому у меня есть тег, который позволит мне отображать блок на какое-то время, и я могу отправить, какие значения должны быть предварительно выбраны (мне не хватает проверки для атрибутов, но только притворись, что он там сейчас):
<cfif thisTag.ExecutionMode EQ "end">
<cfsilent>
<!--- Get Time Blocks --->
<cfset TimeBlocks = Application.DAO.getTimeQueries() />
</cfsilent>
<select name="hour" style="width: auto; float: none;">
<cfoutput query="TimeBlocks.Hours">
<option value="#TimeBlocks.Hours.Value#"<cfif TimeBlocks.Hours.Value EQ Attributes.Hour> selected="selected"</cfif>>
#TimeBlocks.Hours.Value#
</option>
</cfoutput>
</select>:<select name="min" style="width: auto; float: none;">
<cfoutput query="TimeBlocks.Mins">
<option value="#TimeBlocks.Mins.Value#"<cfif TimeBlocks.Mins.Value EQ Attributes.Min> selected="selected"</cfif>>
#TimeBlocks.Mins.Value#
</option>
</cfoutput>
</select>
<select name="mer" style="width: auto; float: none;">
<cfoutput query="TimeBlocks.Mer">
<option value="#TimeBlocks.Mer.Value#"<cfif TimeBlocks.Mer.Value EQ FORM.mer> selected="selected"</cfif>>
#TimeBlocks.Mer.Value#
</option>
</cfoutput>
</select>
</cfif>
Я использую тонны больше этого, но все они очень специфичны для приложения / объекта. Примерно в любое время, когда я начинаю извлекать что-то из включения, или, если я обнаруживаю, что копирую фрагмент логики отображения с одной страницы на другую, я начинаю думать о том, как вставить этот код в собственный тег.
Вот еще несколько примеров пользовательских библиотек тегов, которые я считаю полезными.