我会改变方法。
Thymeleaf可以轻松地让您在模板中添加模型变量以供JavaScript使用。在我的实现中,我通常将这些变量放在关闭页头标签之前的某个位置,以确保它们在JS加载后出现在页面上。
当然,我会让模板决定要加载的内容。如果您要显示画廊,则按照您的方式呈现它,并使用数据属性来定义与一些JS代码相关联的画廊。然后编写一个不错的jQuery插件来处理您的画廊。
以下是一个相对基本的示例:
默认布局修饰器: layout/default.html
<!doctype html>
<html xmlns:layout="http://www.thymeleaf.org" xmlns:th="http://www.thymeleaf.org">
<head>
<title>My Example App</title>
<object th:remove="tag" th:include="fragments/scripts :: header" />
</head>
<body>
<div layout:fragment="content"></div>
<div th:remove="tag" th:replace="fragments/scripts :: footer"></div>
<div th:remove="tag" layout:fragment="footer-scripts"></div>
</body>
</html>
需要注意的是,这里包括了通用页脚脚本以及定义了 layout:fragment
的 div。我们将使用此布局 div 来包含所需的 jQuery 插件以用于相册。
带有常规脚本的文件:fragments/scripts.html
<div th:fragment="header" xmlns:th="http://www.thymeleaf.org">
<script type="text/javascript" th:inline="javascript">
/*<![CDATA[*/
var MY_APP = {
contextPath: /*[[@{/}]]*/,
defaultTheme: /*[[${theme == null} ? null : ${theme}]]*/,
gallery: {
theme: /*[[${gallery == null} ? null : ${gallery.theme}]]*/,
images: /*[[${gallery == null} ? null : ${gallery.images}]]*/,
names: /*[[${gallery == null} ? null : ${gallery.names}]]*/
}
};
/*]]>*/
</script>
</div>
<div th:fragment="footer" xmlns:th="http://www.thymeleaf.org">
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/my_app.js"></script>
</div>
在脚本文件中,有两个片段是从装饰器中包含的。页头片段包括JS层的有用上下文路径以及一个
defaultTheme
。然后定义并从我们的模型分配了一个画廊对象。页脚片段加载jQuery库和一个主站点JS文件,为了这个示例而再次使用。
带有惰性加载画廊的页面:products.html
<html layout:decorator="layout/default" xmlns:layout="http://www.thymeleaf.org/" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Products Landing Page</title>
</head>
<body>
<div layout:fragment="content">
<h1>Products</h1>
<div data-gallery="lazyload"></div>
</div>
<div th:remove="tag" layout:fragment="footer-scripts">
<script type="text/javascript" src="/js/my_gallery.js"></script>
</div>
</body>
</html>
我们的产品页面信息比较少。使用默认的装饰器,该页面会覆盖头部中的页面标题。我们的内容片段包括在一个h1标签中的标题和一个带有data-gallery属性的空的div。这个属性是我们将在jQuery插件中使用来初始化图库的属性。
该值设置为lazyload,因此我们的插件知道需要在某个地方设置的变量中查找图像ID。如果我们的插件只支持懒加载图库,则此值可以很容易地为空。
因此,布局加载一些默认脚本,并通过巧妙放置layout:fragments
,允许网站的某些部分独立于其他部分加载库。
下面是一个与我们的应用程序一起使用的基本Spring控制器示例:MyController.java
@Controller
public class MyController {
@RequestMapping("/products")
public String products(Model model) {
class Gallery {
public String theme;
public int[] images;
public String[] names;
public Gallery() {
this.theme = "basic";
this.images = new int[] {8,5,3,2};
this.names = new String[] {"Hey", "\"there's\"", "foo", "bar"};
}
}
model.addAttribute("gallery", new Gallery());
return "products";
}
}
为了简化我们的示例,Gallery类被内联到products方法中。这可以很容易地成为返回标识符数组或任何所需内容的服务或存储库。
我们创建的jQuery插件可能如下所示:my_gallery.js
(function($) {
var MyGallery = function(element) {
this.$el = $(element);
this.type = this.$el.data('gallery');
if (this.type == 'lazyload') {
this.initLazyLoadedGallery();
}
};
MyGallery.prototype.initLazyLoadedGallery = function() {
if (MY_APP.gallery.images.length) {
PhotoGallery.load(MY_APP.gallery.images).loadTheme({
name: MY_APP.gallery.theme
});
var imgs = MY_APP.gallery.images;
PhotoGallery.load(imgs[0],imgs[1],imgs[2],imgs[3]).loadTheme({
name: MY_APP.gallery.theme
});
}
};
$.fn.myGallery = function() {
return this.each(function() {
if (!$.data(this, 'myGallery')) {
$.data(this, 'myGallery', new MyGallery(this));
}
});
};
$('[data-gallery]').myGallery();
}(jQuery));
产品页面的最终呈现将如下所示:
<!doctype html>
<html>
<head>
<title>Products Landing Page</title>
<script type="text/javascript">
var MY_APP = {
contextPath: '/',
defaultTheme: null,
gallery: {
theme: 'basic',
images: [8,5,3,2],
names: ['Hey','\"there\'s\"','foo','bar']
}
};
</script>
</head>
<body>
<div>
<h1>Products</h1>
<div data-gallery="lazyload"></div>
</div>
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/my_app.js"></script>
<script type="text/javascript" src="/js/my_gallery.js"></script>
</body>
</html>
正如您所看到的,Thymeleaf 在将您的模型转换为有效的 JS 方面做得非常出色,并在需要时添加引号并进行转义。一旦页面完成渲染,并在文件末尾使用 jQuery 插件后,初始化工作就应该加载和准备就绪了。
这不是一个完美的例子,但我认为这是一个相当直观的 Web 应用程序设计模式。
eval()
,虽然这绝对不是最好的解决方案。 - Kejmlinline="javascript"
与eval([[${pageHelper.documentReady}]])
结合使用真的很好用。虽然我想暂时保留这个问题未回答,看看是否有"官方"的Thymeleaf方法来解决这个问题。无论如何,再次感谢你。干杯。John。 - John B.