Как я могу сделать так, чтобы блок кода в пользовательском теге запускался только при первом вызове тега?
-
06-09-2019 - |
Вопрос
Я создаю набор пользовательских тегов ColdFusion, предназначенных для упрощения повторного использования определенных элементов макета.Я буду использовать их способом, аналогичным следующему:
<cfimport prefix="layout" taglib="commonfunctions/layouttags">
<layout:fadingbox>
This text will fade in and out
</layout:fadingbox>
<layout:stockticker>
This text will scroll across the screen
</layout>
Чтобы код, генерируемый этими пользовательскими тегами, работал, файл JavaScript должен быть связан со страницей следующим образом:
<script src="commonfunctions/layouttags/enablingscript.js" type="text/javascript"></script>
Я бы предпочел включить скрипт изнутри пользовательских тегов, вместо того чтобы заставлять пользователя включать его самого.Проблема в том, что файл JavaScript должен быть включен только однажды на страницу.После первого использования одного из этих пользовательских тегов я бы хотел, чтобы последующие вызовы одного и того же тега на той же странице, чтобы избежать повторения <script> tag.Мне пришло в голову, что я мог бы сделать что-то подобное:
<cfif NOT isDefined("Caller.LayoutTagInitialized")>
<script src="commonfunctions/layouttags/enablingscript.js" type="text/javascript"></script>
</cfif>
<cfset Caller.LayoutTagInitialized = 1>
...но это кажется неэлегантным.
Интересно, есть ли способ получше?
Как бы вы это реализовали?
Редактировать - Уточнение:
На случай, если то, что я написал выше, не имело смысла, вот более подробный пример:
Если у меня есть пользовательский тег, подобный этому:
<cfif ThisTag.ExecutionMode EQ "start">
<script src="commonfunctions/layouttags/enablingscript.js" type="text/javascript"></script>
<div class="mytag">
<cfelse>
</div>
</cfif>
... и у меня есть CFML - разметка , вызывающая тег следующим образом:
<layout:mytag>
One
</layout:mytag>
<layout:mytag>
Two
</layout:mytag>
<layout:mytag>
Three
</layout:mytag>
... Я хочу, чтобы был сгенерирован HTML, подобный следующему:
<!-- Script included only the first time the tag is called -->
<script src="commonfunctions/layouttags/enablingscript.js" type="text/javascript"></script>
<div class="mytag">
One
</div>
<!-- No <script> tag on the second call -->
<div class="mytag">
Two
</div>
<!-- No <script> tag on the third call -->
<div class="mytag">
Three
</div>
Решение
Ваше решение не за горами.
Сэм прав в том, что executionmode - это то, что вы хотите использовать, когда вы хотите, чтобы что-то появилось в начальном или конечном режиме тега, что является частью того, что вы хотите.
Но затем вы говорите, что хотите, чтобы этот тег скрипта выводился в начальном режиме только для первого тега, используемого на странице.
Вот где вы могли бы использовать предложение Питера о области действия запроса.В отличие от области по умолчанию (или "переменных"), область запроса является общей для всех пользовательских тегов в данном запросе.Вы предложили использовать область вызывающего объекта, и это тоже могло бы сработать, если бы вызывающий объект не был другим пользовательским тегом, и в этом случае область вызывающего объекта была бы только локальной областью в пользовательском теге.Область запроса (которая существует примерно с CF 4.01) - ваш лучший выбор.
В этом случае предложенное вами решение было близко:в пользовательском теге в стартовом режиме программно проверьте, не создали ли вы уже переменную отслеживания в области запроса при первом размещении тега script.Если нет, выведите тег script и создайте переменную отслеживания.
Помимо изменения вашего кода с использования caller на request , я бы также предположил, что вы захотите поместить CFSET внутрь IF .Нет необходимости выполнять его снова в случае сбоя теста IF.
Другие советы
Используйте область запроса.
Пользовательские теги имеют встроенную область видимости, называемую thistag.
Этот код будет работать:
<cfif thisTag.ExecutionMode eq "start">