Javascript 支持ajax和直接调用的视图引擎
我正在寻找一种方法来为Node.js(Express)中的模板提供服务,该模板“通常”呈现为HTML,如果是ajax请求的,则呈现为JSON 假设我在swig中有这样一个模板:Javascript 支持ajax和直接调用的视图引擎,javascript,json,node.js,express,viewengine,Javascript,Json,Node.js,Express,Viewengine,我正在寻找一种方法来为Node.js(Express)中的模板提供服务,该模板“通常”呈现为HTML,如果是ajax请求的,则呈现为JSON 假设我在swig中有这样一个模板: {% extends 'layout.html' %} {% block title %}Default Page{% endblock %} {% block body %} <p>Hi, {{ name }}.</p> {% endblock %} swig的选择是任意的,它可以是任何
{% extends 'layout.html' %}
{% block title %}Default Page{% endblock %}
{% block body %}
<p>Hi, {{ name }}.</p>
{% endblock %}
swig的选择是任意的,它可以是任何支持块布局继承的视图引擎
我在swig和Nunjucks的文档中搜索了一种简单的方法,以根据请求影响模板呈现,但我没有想到一个主意(这不是一个彻底的过度操作)。将我的答案简化为更适合您的特定用例:
您可以通过使用“中间件覆盖”轻松实现这一点
理想情况下,视图引擎应该能够执行以下操作:
{% if !xhr %}
{% extends 'layout.html' %}
{% endif %}
现在,当您调用res.render('someView',{title:'sometitle'})时代码>它将编译一个完整视图并向下发送,或者如果它是一个XHR请求,那么它将向下发送一个JSON blob,其中包含请求URL、页面标题和作为字符串呈现的视图。然后可以在客户端上动态更新页面
如果您的模板引擎不支持有条件的扩展
,那么您可以使用一些“hack”来解决这个问题。您将需要两个视图(伪代码):
编辑:还有另一种方法可以避免创建第二个小桥视图,甚至不必在每个视图的条件下包装每个extends
。我找到了这个方法。事实证明,您可以在布局文件中有条件地创建内容块,从而可以:
// layout
{% if !xhr %}
<html>
<head>
<title>My Awesome Page</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
{% else %}
{% block body %}{% endblock %}
{% endif %}
//布局
{%if!xhr%}
我的精彩页面
{%block body%}{%endblock%}
{%else%}
{%block body%}{%endblock%}
{%endif%}
这样,布局文件将决定是否包含周围的标记
PS-req.xhr
仅当发出AJAX请求的客户机框架包括(提示:大多数都是这样)时才起作用。如果您的框架不包含该标题,那么可能有一个选项可以切换,或者至少您应该能够设置自定义标题并自己包含它
您可以像在问题中建议的那样使用查询字符串变量,但使用此请求头是与服务器通信的标准约定,即请求是AJAX,并且通常在客户端框架中默认打开。这就是为什么Express有req.xhr
内置:)所以你要加载一个不同的视图,好吗!这可能是有用的。但这导致了大量的冗余。我不太确定是否要复制我的内容:/这不是复制品。这就是重点。这是一个额外的小文件,扩展了布局文件,包含了内容文件。视图的内容存在于部分视图文件中,并且只有在呈现someView\u full
文件时才会加载到完整文档中,然后该文件会吸入部分视图someView
。中间件助手的。当我调用res.renderView
时,该函数运行。您可以看到布局文件有一个内容块。可以看到连接布局文件和局部视图的文件。请注意,它是一个简单的包含视图,而不是重复视图。最后,是部分观点。没有重复的内容。只是局部和布局之间的一个额外的“桥梁”视图。我刚刚发现。你可能会觉得这个想法很有趣。解决了桥文件的需要。把你的布局分成两个逻辑路径,我想我会用这个。与我最初的想法相比,它还有一些好处,“blockstojson”部分应该自动工作。非常感谢。
// someView
<p>Hi, {{ name }}</p>
// someView_full
{% extends 'layout.html' %}
{% block title %}Default Page{% endblock %}
{% block body %}
{% include 'someView' %}
{% endblock %}
if (!req.xhr) {
res.render(viewName + "_full", viewData);
} else { ... }
// layout
{% if !xhr %}
<html>
<head>
<title>My Awesome Page</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
{% else %}
{% block body %}{% endblock %}
{% endif %}