有没有一种更干净的方法来处理 AJAX 帖子与 HTML 表单帖子的快速呈现

Is there a cleaner way to handle Express rendering differently for AJAX posts vs HTML form posts?

本文关键字:AJAX HTML 表单 处理 一种 方法 有没有      更新时间:2023-09-26

我有一个非常基本的HTML表单,我正在使用jQuery的AJAX发布功能来获取一些信息,具体取决于数据库插入是成功还是失败。

我的代码目前正在执行如下所示的操作,我仅在通过 AJAX 进行发布以区分来源时将 ajax post 变量设置为 true

app.post("/mypath", function (req, res) {
    var post = req.body;
    if (post.ajax) {
        console.log(post.ajax, "posting as ajax");
    }
    if (post.ajax) {
        res.json({data: "Woah! You posted as ajax."});
    }
    else {
        // If posting via HTML form, send the user where they need to go
        res.redirect("someview");
    }
});

真正担心的是,我不希望最终用户看到带有纯文本 JSON 的页面,但是当我支持 JavaScript 时,我希望其中一些 JSON 数据能够通知用户成功/失败。

有什么方法可以让它更干净吗?我有 3 个地方必须在该应用程序路由中进行条件渲染。

我正在使用快递 3.x

当然。只要客户端代码正确设置了Accept标头,就可以使用 res.format ,例如:

res.format({
    html: function() {
        res.redirect('someview');
    },
    json: function() {
        res.json({data: "You expected JSON? You got JSON!"});
    }
});

看看我不久前写的这篇文章。我编写了一个帮助程序,它将自动以 express 格式呈现完整或部分视图。

关键是要创建这样的 ja 视图:(可惜 Jade 视图是预编译的,你不能把变量传递给include,也不能有条件地调用extends,所以我们需要这个"胶水"文件。你会明白为什么。

// home_full.jade
extends layout  
block content  
    include home

它扩展了布局文件并包括部分视图。此视图充当实际视图和布局文件之间的粘合。这些中间观点总是以"_full.jade"结尾。

接下来,我创建了自己的小中间件函数,将助手添加到req

app.use(function (req, res, next) {  
    res.renderView = function (viewName, viewModel) {
        res.render(viewName + req.xhr ? null : '_full', viewModel);
        next();
    };
});

它被称为renderView,它为我们执行 xhr 逻辑。而不是使用req.render渲染视图...

res.render('home' + req.xhr ? null : '_full', viewModel);

。您只需调用req.renderView并传入视图名称:

res.renderView('home');

现在,如果请求是整页请求,那么我们将发回完全编译的视图、布局和所有内容。如果设置了 ajax 请求标头(大多数客户端库(如 JQuery 和其他库(都为您做了(,那么我们将只发回部分视图,并让客户端填充页面上的相应区域:)

PS - 如果您需要将视图与其他 JSON 数据一起发送回,您可以使用我的扩展版本的帮助程序函数。例:

res.renderView = function (viewName, viewModel) {
    if (!req.xhr) {
        res.render(viewName + '_full', viewModel);
    } else {
        res.render(viewName, viewModel, function (err, view) {
            if (err) return next(err);
            res.json({
                title: viewModel.title || "Untitled | CodeTunnel.com",
                bannerText: viewModel.bannerText || "CodeTunnel.com",
                view: view,
                url: req.url
            });
        });
    }
};

显然,您会调整res.json呼叫以满足自己的需求。在上面的实现中,我需要一个 JSON 对象,其中包含页面标题、要在页面横幅中显示的文本、作为对象上的字符串属性的视图标记以及请求 URL。然后,我将在客户端上使用这些数据来呈现部分视图,以及更新客户端上的页面标题和其他内容。