【问题标题】:Does ColdFusion have an answer to ASP.NET's Master Pages?ColdFusion 对 ASP.NET 的母版页有答案吗?
【发布时间】:2010-10-17 05:05:26
【问题描述】:

我正在开发一个用 ColdFusion 编码的网站。我有一个 CSS/HTML 模板,我想将其应用于每个页面的内容,而无需复制任何不必要的代码。我已经被 ASP.NET 的母版页宠坏了,这将是我实现该站点的首选方式。不幸的是,我无法使用该选项。该站点必须在 Coldfusion MX 7 上运行。此外,领导该项目的开发人员不喜欢 Fusebox,因此该选项已失效。

每个页面的主导航、图形页眉和页脚都相同。标题标签、元标签和二级导航可能会因页面而异。除此之外,只有页面的“主要内容区域”会有所不同。

鉴于这些参数,我如何对网站进行编码以实现最大的可维护性?

【问题讨论】:

  • 哈,在我意识到是谁发帖之前就阅读了这个问题。缺少 .Net 嗯?

标签: design-patterns coldfusion master-pages code-reuse


【解决方案1】:

ColdFusion 开发人员在 90 年代后期开始使用名为 cf_bodycontent 的自定义标签,以避免包含单独的页眉和页脚文件。那是在 ASP.NET 的母版页出现之前的六七年。 ;-)

现在有一个本地标签可以做同样的事情:cfsavecontent。以下是人们如何在模板中使用 cfsavecontent 的精髓。

   <!--- index.cfm --->
   <cfsavecontent variable="content">
      <cfinclude template="#url.action#.cfm">
   </cfsavecontent> 

   <cfinclude template="template.cfm">

   <!--- template.cfm --->
   <cfparam name="title" default="Welcome">
   <html>
      <head><cfoutput>#title#</cfoutput></head>
      <body>
         ... header, menu, sidebar, whatever ...
         <cfoutput>#content#</cfoutput>
         ... right column, footer ...
      </body>
   </html>

   <!--- foo.cfm --->
   <cfset title="Welcome to Foo">
   Hello World! I'm the page at index.cfm?action=foo

   <!--- bar.cfm --->
   <cfset title="Welcome to Bar">
   Hello World! I'm the page at index.cfm?action=bar

如果您想在模板中放置一个模板,只需添加另一个 cfsavecontent。

   <!--- index.cfm --->
   <cfsavecontent variable="content">
      <cfinclude template="#url.action#.cfm">
   </cfsavecontent> 

   <cfsavecontent variable="content">
      <cfinclude template="internal_template.cfm">
   </cfsavecontent>

   <cfsavecontent variable="content">
      <cfinclude template="master_template.cfm">
   </cfsavecontent>         

   <cfoutput>#content#</cfoutput>         

您可以进行重构以消除冗余。

   <!--- index.cfm --->
   <cfsavecontent variable="content">
       <cfinclude template="#url.action#.cfm">
   </cfsavecontent> 

   <cfparam name="templates" default="internal,master">

   <cfloop list="#templates#" index="t">
       <cfsavecontent variable="content">
           <cfinclude template="#t#_template.cfm">
       </cfsavecontent>
   </cfloop> 

   <cfoutput>#content#</cfoutput>  

如果您想让一个模板“扩展”另一个模板,您可以通过将列表转换为堆栈并让每个模板将其父模板推入堆栈来实现。

  <!--- internal_template.cfm --->
  <cfset templates = listAppend("master", templates)>  

  ...
  <cfoutput>#content#</cfoutput>
  ...


  <!--- index.cfm --->
  <cfsavecontent variable="content">
      <cfinclude template="#url.action#.cfm">
  </cfsavecontent> 

  <cfparam name="templates" default="internal">

  <cfloop condition="listlen(templates) gt 0">
      <cfset t = listFirst(templates)>
      <cfset templates = listRest(templates)>
      <cfsavecontent variable="content">
          <cfinclude template="#t#_template.cfm">
      </cfsavecontent>
  </cfloop> 

  <cfoutput>#content#</cfoutput> 

这样您就有了 StackBox,它是在 StackOverflow 上发明的 ColdFusion 框架。 :-)

【讨论】:

  • 噢噢噢,我也喜欢这个!也许我会这样做。 +1
【解决方案2】:

ColdFusion 有很多方法可以做到这一点。


Application.cfc 在每个请求上执行,并且有两种方法(onRequestStartonRequestEnd)可用于在页面的主脚本中添加/追加内容.

另外值得注意的是,可以扩展/继承您的 Application.cfc,从而允许更复杂的 RequestStart/End 事件集。 More details herehere


Custom Tags 允许您创建一个标签,您可以将其包裹在每个模板周围以应用布局/等。它还允许属性/等定义常见但不断变化的文本。

例如:

<cf_page PageTitle="My Page">
    [main page content]
</cf_page>

在自定义标签 (page.cfm) 中,您拥有:

<cfif ThisTag.ExecutionMode EQ 'start'>
    <cfparam name="Attributes.PageTitle" default=""/>
    <cfcontent reset/><cfoutput><!DOCTYPE html>
    <html>
    <head>
        <title>My Website - #Attributes.PageTitle</title>
        [styles and scripts and stuff]
    </head>
    <body>
        <div id="heading">
            <img src="my_website_logo.png" alt="My Website"/>
        </div>
        <ul id="mainmenu" class="nav">
            [menu]
        </ul>
        <h1>#Attribute.PageTitle#</h1>
    </cfoutput>
<cfelse>
    <cfoutput>
        <div id="footer">
            [footer]
        </div>
    </body></html></cfoutput>
</cfif>

当然,您可以创建多个自定义标签,或者根据指定的属性创建一个以多种方式工作的标签。


Henry 已经提到了 MVC Frameworks,但是您不需要做 MVC 来使用模板/布局功能。

Fusebox 可以做 MVC,但它并不要求你这样做,不管怎样,FB 的 ContentVariables 都是实现模块化内容的好工具 - 除非您的首席开发人员可以证明他不喜欢 Fusebox(并提出更适合您的项目的替代方案!)然后绝对没有理由不选择它 - 它是一个成熟且众所周知的框架,易于使用、大量的开发人员等等。

但是,如果 Fusebox 真的不是一个选项,请查看 Charlie Arehart's list of frameworks - 该页面通常是一个巨大的工具列表,值得一看。


无论如何,这应该给你足够的东西来考虑现在......

【讨论】:

  • 自定义标签是个好主意。谢谢。
  • 彼得,很棒的帖子。您可以添加的一件事是使用 Application.cfc,您可以继承父 onRequestStart/End 以获得漂亮的主/子/孙页面效果,调用超级方法。哦,还有 Application.cfm/OnRequestEnd.cfm 和 cfinclude 父文件来代替它。
  • 从来没有想过使用自定义标签来做这个...... :) 很酷,有利于让它快速工作。
  • Nathan:是的,Application.cfc 继承有点繁琐?不过,为了完整起见,我会添加注释和链接。
  • Henry:很多人忘记了自定义标签,但它们非常方便!在 Railo 3.1 中,可以使用组件编写自定义标签 - 我还没有机会研究它是如何工作的,但它可能会让它们更加灵活......
【解决方案3】:

您可以尝试其中一种支持模板的 MVC 框架(几乎每个人都有)。

ColdBoxModel-GlueMach-IIFusebox...

这个Galleon Forum Ports Comparisons 页面重点介绍了每个框架如何处理模板...

【讨论】:

    【解决方案4】:

    查看 CFINCLUDE

    【讨论】:

    • 我使用 cfinclude 包含在页眉、页脚、其他元素等中,但我希望功能更强大。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多