如何使用 Grails 资产管道在要在页脚内呈现的视图中声明 javascript 资产
How to declare javascript asset in the view to be rendered within the footer using Grails Asset Pipeline
因为没有延迟选项:
<asset:javascript src="custom_view_script.js"/>
除了资源插件之外,还有什么可以用来将特定于视图的脚本放在结束正文标记之前,而无需在布局中全局声明它?
我确实知道:
<asset:deferredScripts/>
但这只处理页面脚本,不包括。
最简单的方法是使用站点网格。
在您的布局中,您需要放置
<g:pageProperty name="page.script"/>
正文末尾。
然后在页面中你会做这样的事情:
<content tag="script">
<script type="application/javascript">
... your code here ...
</script>
</content>
请注意,内容标签(脚本)是您指定的任何文本,但要从 sitemesh 引用该内容,您需要在其前面添加 "page."。
但是,请注意,因为 sitemesh 属性不是累积的,我的意思是,如果您将两个部分的内容标记为="script",则只会使用最后一个部分。
如果您需要,就像我通常做的那样,您可以通过使用稍微修改 SitemesTagLib 的自定义 TagLib 来完成它:
class MyContentTagLib implements RequestConstants {
static namespace = "mycontent"
Closure addContent = { Map attrs, body ->
if( body != null ) {
def htmlPage = getPage()
if( htmlPage instanceof GSPSitemeshPage && attrs.tag ) {
def name = attrs.tag
def sitemeshPage = (GSPSitemeshPage) htmlPage
StreamCharBuffer currentContent = sitemeshPage.getContentBuffer( "page.$name" ) as StreamCharBuffer
StreamCharBuffer newContent = wrapContentInBuffer( body )
if( currentContent ) {
newContent.writeTo( currentContent.writer )
newContent = currentContent
}
sitemeshPage.setContentBuffer( name, newContent )
}
}
}
private AbstractHTMLPage getPage() {
return (AbstractHTMLPage)getRequest().getAttribute(PAGE)
}
private StreamCharBuffer wrapContentInBuffer(Object content) {
if (content instanceof Closure) {
content = content()
}
if (!(content instanceof StreamCharBuffer)) {
// the body closure might be a string constant, so wrap it in a StreamCharBuffer in that case
FastStringWriter stringWriter=new FastStringWriter()
stringWriter.print((Object)content)
StreamCharBuffer newbuffer = stringWriter.buffer
newbuffer.setPreferSubChunkWhenWritingToOtherBuffer(true)
return newbuffer
} else {
return (StreamCharBuffer)content
}
}
}
现在您可以在您的布局中保留 g:pageProperty,但您会在您的页面中这样做:
<mycontent:addContent tag="script">
<script type="application/javascript">
... your code here ...
</script>
</mycontent:addContent>
这应该收集您放入不同视图和模板中的所有内容,然后将其显示在您的最终 html 中,您的 g:pageProperty 标签所在的位置。
因为没有延迟选项:
<asset:javascript src="custom_view_script.js"/>
除了资源插件之外,还有什么可以用来将特定于视图的脚本放在结束正文标记之前,而无需在布局中全局声明它?
我确实知道:
<asset:deferredScripts/>
但这只处理页面脚本,不包括。
最简单的方法是使用站点网格。
在您的布局中,您需要放置
<g:pageProperty name="page.script"/>
正文末尾。
然后在页面中你会做这样的事情:
<content tag="script">
<script type="application/javascript">
... your code here ...
</script>
</content>
请注意,内容标签(脚本)是您指定的任何文本,但要从 sitemesh 引用该内容,您需要在其前面添加 "page."。
但是,请注意,因为 sitemesh 属性不是累积的,我的意思是,如果您将两个部分的内容标记为="script",则只会使用最后一个部分。
如果您需要,就像我通常做的那样,您可以通过使用稍微修改 SitemesTagLib 的自定义 TagLib 来完成它:
class MyContentTagLib implements RequestConstants {
static namespace = "mycontent"
Closure addContent = { Map attrs, body ->
if( body != null ) {
def htmlPage = getPage()
if( htmlPage instanceof GSPSitemeshPage && attrs.tag ) {
def name = attrs.tag
def sitemeshPage = (GSPSitemeshPage) htmlPage
StreamCharBuffer currentContent = sitemeshPage.getContentBuffer( "page.$name" ) as StreamCharBuffer
StreamCharBuffer newContent = wrapContentInBuffer( body )
if( currentContent ) {
newContent.writeTo( currentContent.writer )
newContent = currentContent
}
sitemeshPage.setContentBuffer( name, newContent )
}
}
}
private AbstractHTMLPage getPage() {
return (AbstractHTMLPage)getRequest().getAttribute(PAGE)
}
private StreamCharBuffer wrapContentInBuffer(Object content) {
if (content instanceof Closure) {
content = content()
}
if (!(content instanceof StreamCharBuffer)) {
// the body closure might be a string constant, so wrap it in a StreamCharBuffer in that case
FastStringWriter stringWriter=new FastStringWriter()
stringWriter.print((Object)content)
StreamCharBuffer newbuffer = stringWriter.buffer
newbuffer.setPreferSubChunkWhenWritingToOtherBuffer(true)
return newbuffer
} else {
return (StreamCharBuffer)content
}
}
}
现在您可以在您的布局中保留 g:pageProperty,但您会在您的页面中这样做:
<mycontent:addContent tag="script">
<script type="application/javascript">
... your code here ...
</script>
</mycontent:addContent>
这应该收集您放入不同视图和模板中的所有内容,然后将其显示在您的最终 html 中,您的 g:pageProperty 标签所在的位置。