Как использовать тег cfwddx в ColdFusion
Я хотел бы отправить структуру ColdFusion в Javascript. Посмотрев, как я могу это сделать, я обнаружил тег cfwddx. Похоже, что я получил часть пути туда. Я создал тестовую программу
<head>
<script type = "text/javascript" src = "frag3.js"> </script>
</head>
<body>
<cfset str = StructNew()>
<cfset str['betty'] = 1>
<cfset str['nancy'] = 2>
<cfdump var = "#str#">
<cfwddx action="CFML2JS"
input="#str#"
toplevelvariable="xyz"
output = "genstr">
<cfoutput>
<script type = "text/Javascript">
test('betty')
function test (arg) {
alert("got to test");
#genstr#
alert ("xyz " + xyz[arg]);
}
nothing()
</script>
</cfoutput>
Cfdump дает правильный ответ
Когда я смотрю на вывод #genstr#, он содержит правильный код JavaScript:
xyz = new Object(); xyz["betty"] = "1"; xyz["nancy"] = "2";
Когда я запускаю код, как показано выше, предупреждение дает правильный ответ. И когда я вызываю функцию "nothing()", которая находится на frag3.js, предупреждение показывает, что она работает, поэтому оператор src работает.
Однако когда я перемещаю сам тест функции (arg) в frag3.js, он не запускается.
Может кто-нибудь сказать мне, как заставить "тестировать" работу как внешнюю функцию, а не просто встроенную в мой код ColdFusion? Кстати, я не изучил JQuery, поэтому ответы JQuery не очень поможет; Мне нужен базовый JavaScript.
3 ответа
Вместо того, чтобы записывать биты переменных (назовем их "инициализация" или "конфигурация") в исходный код вашего веб-сайта (или, что еще хуже, в исходный код ваших статических файлов JS), я рекомендую следующее.
Создайте компонент, имеющий метод удаленного вызова, который возвращает структуру со всей конфигурацией. Теперь вы можете вызвать этот метод из кода ColdFusion на сервере (где вы получите структуру) и через Ajax из кода JavaScript на клиенте (где вы получите JSON).
/** Config.cfc (or call it something similar)
*
*/
component {
remote struct function getConfig() returnformat="JSON" {
var str = StructNew();
str['betty'] = 1;
str['nancy'] = 2;
return str;
}
}
ваш main.cfm (для простоты примера я включаю jQuery для обработки запроса Ajax):
<html>
<head>
<script type="text/javascript" src="frag3.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>
<h1>Config, as seen by the server</h1>
<cfinvoke component="Config" method="getConfig" returnvariable="cfg">
<cfdump var="#cfg#">
<h1>Config, as seen by the client</h1>
<pre id="cfgDump"></pre>
<script type="text/javascript">
$(function () {
$.get("Config.cfc?method=getConfig").done(function (cfg) {
// cfg already is a regular JS object at this point
// convert to JSON again for display purposes
$("#cfgDump").text( JSON.serialize(cfg, null, 2) );
});
});
</script>
</body>
</html>
Чисто и просто.
Возможно, наиболее эффективным решением вашей проблемы будет включение встроенного динамического содержимого в сам документ.
Когда вы копируете функцию test(arg)
в файл Javascript, я полагаю, вы копируете #genstr#
также? Так выглядит в файле js именно так, как у вас есть выше?
Это работает как задумано. Файлы.js не обрабатывают Cold Fusion, и если вы посмотрите на консоль разработчика, вы, вероятно, получите синтаксическую ошибку.
Вы можете сохранить его в документе или изменить расширение файла js на.cfm.
На данный момент ваш js_main.cfm
(пример) файл будет обрабатываться так же, как и любой другой файл, запрашиваемый браузером, и он будет сбрасывать верхние и нижние колонтитулы, если ваша обработка запросов делает это, поэтому это вызовет больше ошибок. Вы должны защитить эти файлы от этого. Вы можете сделать это с помощью некоторых файлов cfif в вашем приложении, например:
<!--- This checks the path to make sure it doesn't contain livemedia. --->
<cfif not listfind(cgi.script_name,"livemedia","/")>
... do includes
</cfif>
Или вы можете сделать так, как я бы, вероятно, сделал, и заблокировать эти файлы в папке только для обслуживания JS, CSS-файлов с расширением cfm с их собственным application.cfc/cfm для переопределения глобального файла сайта, если я столкнулся с ситуацией, в которой я чувствовал что динамически генерируемый js/css был действительно лучшим вариантом.
Затем вы можете делать то, что показываете в своем OP, и передавать переменные на клиентскую сторону, если вам действительно это нужно. В качестве альтернативы, вы можете называть два "приложения" одинаковыми, и хотя это делает обмен данными действительно простым, я все же должен посоветовать вам быть осторожным с тем, что вы делитесь, и вы раскрываете и проверяете правильность защиты субприложения.
И да, как и предполагали другие, #SerializeJSON()#
Это современный подход к копированию серверной переменной / объекта на стороне клиента.
Например..
<cfset CFStruct = {big = "little", red = "blue", subArray = ["A","B","C","D"]} />
<script>
<cfoutput>JSObj = #SerializeJSON(CFStruct)#;</cfoutput>
</script>
<!--- While I use shorthand to form the struct and subArray, that's only for speed,
structs, arrays, queries, etc formed in any fashion work just fine. --->
Создает JSObj
с элементами big, red, subArray
(который имеет дочерние элементы A, B, C, D
).
Все равно, какой бы метод вы ни выбрали (wddx
или же SerializeJSON()
), они не будут работать в файле.js.
Я должен упомянуть, что есть другой вариант, позволяющий серверу анализировать файлы.js, но это будет намного более болезненным, чем оно того стоит. Во многих случаях, когда вы будете использовать простой js-файл, будут возникать помехи.
Обратите внимание, что ваши файлы вызываются через теги на стороне клиента <script>
а также <link>
полностью отдельные запросы. Они не будут делиться url, form, request, variables
прицелы. Однако они могут поделиться cookies
а также client
а также session
область действия, если два приложения имеют одинаковое имя.
Наконец, замечательная вещь о внешнем контенте, называемом через HTML-теги, независимо от расширения, заключается в том, что он обычно кэшируется по умолчанию. Это замечательно для пропускной способности и даже для быстрой загрузки страниц, пока у вас не будет сценария, когда вы хотите последовательно загружать не кэшированные копии.
По этой причине, когда вы чувствуете, что должны динамически генерировать что-то, что вы хотите вставить во внешний файл, у вас есть несколько методов.
- Вы можете установить no-cache в заголовке (CF или Htaccess могут сделать это).
- Вы можете указать случайное число в строке запроса вызова скрипта.
<script src="/livemedia/js_main.cfm?randomizer=#randrange(1,1000000)#"></script>
- Возможно, файл не нужно обновлять каждый раз для каждого пользователя, может быть, просто каждый пользователь должен видеть свою копию. Вы все равно прикрепите строку запроса, потому что несколько пользователей могут войти в систему с одного компьютера. Это, однако, будет зависеть от пользователя.
<script src="/livemedia/js_main.cfm?#session.username#"></script>
- Пересмотрите, как ваша страница компилирует и хранит данные, которые должны быть встроены в страницу.
Если вы присоединяете что-то к строке запроса файла javascript, вам следует переместить статическое содержимое файла в отдельный файл, который не нужно каждый раз восстанавливать. Нет необходимости перезагружать 15 функций JavaScript с каждым запросом страницы, потому что 1 содержит динамическое содержимое.
Я не большой разработчик CF, но самый простой способ, которым я знаю, для вывода структур и массивов для использования javascript - это использование JSON SerializeJson()
Например, как переменная JS на странице CF:
<script>
var myVar = <cfoutput>#SerializeJson(str)#</cfoutput>;
</script>
Хотя JSON является строкой... когда он печатается внутри тега script, javascript будет читать его как массив или объект без необходимости синтаксического анализа в клиенте.
Я использую точно такой же вывод для доставки AJAX также