3

我想向 Javascript 发送一个 ColdFusion 结构。在查看如何执行此操作时,我发现了 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 给出了正确答案

cfdump 的输出

当我查看#genstr# 的输出时,它包含正确的 javascript 代码:

xyz = new Object(); xyz["betty"] = "1"; xyz["nancy"] = "2"; 

当我如上所示运行内联代码时,警报给出了正确的答案。当我调用驻留在 frag3.js 上的“nothing()”函数时,警报显示它已运行,因此 src 语句正在运行。

但是,当我将函数 test(arg) 本身移动到 frag3.js 时,它不会运行。

谁能告诉我如何让“测试”作为外部函数工作,而不仅仅是在我的 ColdFusion 代码中内联?顺便说一句,我没有学过 jquery,所以 jquery 的答案不会有多大帮助;我需要基本的 JavaScript。

4

3 回答 3

1

我建议不要将变量位(我们称它们为“初始化”“配置”)写入您网站的源代码(或者更糟的是,写入您原本静态的 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>

干净简单。

于 2015-01-04T08:29:14.593 回答
0

对您的问题最有效的解决方案可能是将动态内容内联包含在文档本身中。

当您将函数复制test(arg)到 Javascript 文件时,我想您也在复制#genstr#?所以它看起来,在 js 文件中,和你上面的完全一样?

这是按预期工作的。.js 文件不处理冷融合,如果您查看开发人员控制台,您可能会遇到语法错误。

您可以将其保持在文档中,或者将 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、具有 cfm 扩展名的 CSS 文件以及它们自己的 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

尽管如此,无论您选择哪种方法(wddxSerializeJSON()),这些都无法在 .js 文件中使用。

我必须提到允许服务器解析 .js 文件的另一个选项,但这会比它的价值更痛苦。许多使用纯 js 文件的场合都会受到干扰。

请注意,您通过客户端标签调用的文件就像<script>并且<link>完全是单独的 requests。他们不会共享url, form, request, variables范围。但是,如果两个应用程序具有相同的名称,它们可以共享和cookies作用域。clientsession

最后,无论扩展名如何,通过 html 标签调用的外部内容的美妙之处在于它通常默认缓存。这对于带宽甚至对于加载页面的速度都非常有用,直到您遇到想要一致地加载非缓存副本的场景。

出于这个原因,当您觉得必须动态生成要粘贴到外部文件中的内容时,您有一些方法。

  1. 您可以在标头中设置 no-cache(CF 或 Htaccess 可以这样做)。
  2. 您可以在脚本调用的查询字符串中提供一个随机数。<script src="/livemedia/js_main.cfm?randomizer=#randrange(1,1000000)#"></script>
  3. 也许不需要为每个用户每次都刷新文件,也许只是每个用户需要看到不同的副本。您仍然需要附加查询字符串,因为多个用户可能从同一台计算机登录。但是,它将是用户特定的。<script src="/livemedia/js_main.cfm?#session.username#"></script>
  4. 重新考虑您的页面如何编译和存储需要在页面中实时内联的数据。

如果要将某些内容附加到 javascript 文件的查询字符串,则应将文件的静态内容移动到不需要每次都重新生成的单独文件中。无需为每个页面请求重新加载 15 个 javascript 函数,因为 1 个包含动态内容。

于 2015-01-04T02:25:51.343 回答
-1

我不是一个大型 CF 开发人员,但我知道输出结构和数组以供 javascript 使用的最简单方法是使用 JSONSerializeJson()

例如作为 CF 页面中的 JS 变量:

<script>
    var myVar = <cfoutput>#SerializeJson(str)#</cfoutput>;
</script>

虽然 JSON 是一个字符串......当它在脚本标签中打印时,javascript 会将其读取为数组或对象,而无需在客户端解析它。

我也使用完全相同的输出进行 ajax 交付

于 2015-01-04T02:23:00.870 回答