Javascript 支持ajax和直接调用的视图引擎

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的选择是任意的,它可以是任何

我正在寻找一种方法来为Node.js(Express)中的模板提供服务,该模板“通常”呈现为HTML,如果是ajax请求的,则呈现为JSON

假设我在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 %}