【问题标题】:Loading static resources from a Grails custom tag, with disposition: 'head'从 Grails 自定义标签加载静态资源,配置:'head'
【发布时间】:2012-12-31 07:15:02
【问题描述】:

我正在尝试编写一个 Grails 自定义标签,它(除其他外)会触发资源的包含,所以像 <myTags:view name="foo"/> 这样的东西会加载,比如 js/views/foo.js。我希望它加载disposition: 'head'

我可以使用<r:external/>,但这不会把它放在<head> 中,它只会产生一个内联的<script/> 标签。我可以使用<r.script/>,但这并不能让我引用路径;我必须让我的自定义标签读取文件并将其转储到out

现在,如果 foo.js 是它自己的模块,我可以这样做:r.require([module: 'foo']),但它不是;部分原因是我不想在ApplicationResources.groovy 中声明所有这些文件。但也许我可以让ApplicationResources.groovy 通过读取可用文件以编程方式创建模块——这可能吗?还是有更好的办法?

【问题讨论】:

  • 真正的重点是创建模块并将它们包含在需要它们的页面中。我知道您要做什么,但是我认为它不会在实践中起作用。如果您多次使用该标签,您可能会多次加载该文件。如果你遵循 Grails 约定,你会过得更好。
  • 我从经验中知道,如果我要求开发人员记住每次创建视图以在 ApplicationResources.groovy 中创建模块条目,以及每次使用视图时确保有一个 标签,他们会忘记,我们会一遍又一遍地遇到同样的问题。我宁愿不违反 DRY。
  • 嗯,看起来实际上 is 应该把它放在头上,但据我所知,它什么也没做.

标签: grails grails-2.0 custom-tags


【解决方案1】:

我最终决定让ApplicationResources.groovy 以编程方式创建模块,因此自定义标签可以使用<r:require/>

这个想法是,对于每个 Backbone 视图,在 web-app/myApp/views 下,.js 文件中有一个 Backbone 视图,.handlebars 文件中有一个 Handlebars 模板(按照惯例,名称相同)。 .handlebars 文件被声明为普通模块,但被 Handlebars-Resources 插件预编译。

ApplicationResources.groovy中的一些代码查找所有视图并创建相应的资源模块:

GrailsApplication grailsApplication = Holders.getGrailsApplication()
File viewsDir = grailsApplication.parentContext.getResource("myApp/views").file;
if (viewsDir.exists() && viewsDir.isDirectory() && viewsDir.canRead()) {
    String[] viewsJS = viewsDir.list().findAll { name -> 
        name.endsWith("View.js") 
    }
    String[] views = viewsJS.collect { name ->
        name.substring(0, name.length() - ".js".length())
    }

    for (view in views) {
        "${view}" {
            dependsOn 'backbone', 'backbone_relational', 'handlebars'
            resource url: "dpg/views/${view}.handlebars", 
                     attrs: [type: 'js'], 
                     disposition: 'head'
            resource url: "dpg/views/${view}.js", 
                     disposition: 'head'

        }
    }
}

然后是标签库:

class ViewsTagLib {
    static namespace = "myApp"

    def view = { attrs ->
        r.require(module: "${attrs.name}View")
        out << "<${attrs.tagName} id='${attrs.id}'></${attrs.tagName}>"
    }
}

在 GSP 中调用它:

<myApp:view tagName="div" name="foo" id="foo1"/>
<myApp:view tagName="div" name="foo" id="foo2"/>

生产:

<html>
    <head>
        ...
        <!--
            Automagically generated modules (included only once).
            Should put these in the same bundle, but handlebars-resources
            gets confused.
        -->
        <script src="/myApp/static/bundle-bundle_fooView_handlebars.js" 
                type="text/javascript" ></script>
        <script src="/myApp/static/bundle-bundle_fooView_head.js" 
                type="text/javascript" ></script>
    </head>
    <body>
        ...
        <div id="foo1"></div> <!-- backbone placeholder for 1st view instance-->
        <div id="foo2"></div> <!-- backbone placeholder for 2nd view instance-->
    </body>
</html>

这不是很漂亮,但混乱大多是隐藏的,它应该大大减少样板文件和忘记向多个文件添加魔术字符串的机会。

【讨论】:

    猜你喜欢
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    • 2021-09-09
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 2020-01-18
    • 1970-01-01
    相关资源
    最近更新 更多