从后端获取数据传输到前端进行显示(cpp-httplib+Vditor+Handlebars)

1. 引言

在之前的文章中,笔者实现了一个渲染 Markdown 格式文章的网页前端 Vite 项目(参看《给 Markdown 渲染网页增加一个目录组件(Vite+Vditor+Handlebars)》),以及一个支持 Markdown格式数据的静态文件服务的后端项目(参看《使用cpp-httplib发布静态文件服务》)。在这里,就将前端与后端打通,通过 cpp-httplib 提供的 API 接口动态返回 Markdown 文章数据,由前端 Vite 项目利用 Handlebars 模板与 Vditor 渲染引擎完成展示与交互。

2. 实现

2.1 后端

JSON 是 HTTP 传输中事实上的标准数据格式,尤其是在现代 Web API(特别是 RESTful API)中,因此我们将后端的接口改成返回 JSON 格式数据的接口。按照 RESTful API 风格,命名为 /api/v1/post,使用 HTTP 的 Get 方法。具体代码如下:

cpp 复制代码
#include <httplib.h>

#include <filesystem>
#include <fstream>
#include <iostream>
#include <nlohmann/json.hpp>
#include <string>

#include "BlogData.h"

using namespace std;
using namespace nlohmann;
namespace fs = std::filesystem;

int main() {
  httplib::Server svr;

  std::u8string docRoot =
      u8"D:/Work/HttpServer/public/最小二乘问题详解1:线性最小二乘";

  svr.Get("/api/v1/post",
          [&](const httplib::Request& req, httplib::Response& res) {
            DataTransfer::BlogData blogData;

            {
              fs::path blogMetaJsonPath = fs::path(docRoot) / "meta.json";
              nlohmann::json blogMetaJson;
              ifstream infile(blogMetaJsonPath);
              infile >> blogMetaJson;
              blogData.blogMeta = blogMetaJson;
            }

            {
              fs::path blogContentPath =
                  fs::path(docRoot) / u8"最小二乘问题详解1:线性最小二乘.md";
              std::ifstream file(blogContentPath, std::ios::binary);

              std::string content((std::istreambuf_iterator<char>(file)),
                                  std::istreambuf_iterator<char>());
              blogData.content = std::move(content);
            }

            // 构造响应 JSON
            json response_data = blogData;

            // 设置响应
            res.set_header("Access-Control-Allow-Origin",
                           "http://127.0.0.1:8000");  // 允许跨域
            res.set_content(response_data.dump(), "application/json");
          });

  std::cout << "Server listening on http://127.0.0.1:8080\n";
  svr.listen("0.0.0.0", 8080);

  return 0;
}

这段代码的实现非常简单,分别读取元数据 meta.json 和 文章内容 最小二乘问题详解1:线性最小二乘.md 文件,组织成 JSON 格式,设置到 HTTP 响应的内容中并且返回。其中,用到 nlohmann/json 对 结构体对象序列化和反序列化(参考《C++中JSON序列化和反序列化的实现》)。

另外需要注意的就是跨域问题。由于前端项目与后端项目是分离的,因此它们处在不同的域中,前端要请求后端的资源,就会发生跨域问题。解决办法就是在 HTTP 的响应头中设置允许跨域的键和值:

cpp 复制代码
res.set_header("Access-Control-Allow-Origin", "http://127.0.0.1:8000");  // 允许跨域

2.2 前端

前端的修改就简单多了,只需要修改获取远端数据的接口就可以了:

cpp 复制代码
const response = await fetch("http://127.0.0.1:8080/api/v1/post");
if (!response.ok) {
    throw new Error("网络无响应");
}
const blogData = await response.json();
//...

其实这也是前后端分离的优势,后端提供数据资源的获取,前端则负责数据的可视化。最终的效果如下所示:

3. 其他

以上就是一个最简单的前后端分离 Web 项目。任何复杂功能都可以在此基础上进行扩展,只需搭配相应的架构设计,以更好地支持具体业务需求。

实现代码

相关推荐
To_OC6 小时前
通义千问多模态生图踩坑记:我是如何把两个报错逐个干翻的
前端·aigc·vite
梵得儿SHI1 天前
Vue 项目实战与性能优化全攻略:从代码、渲染到首屏,一站式解决卡顿慢加载
前端·vue.js·性能优化·vite·前端面试·前端优化·首屏优化
天蓝色的鱼鱼3 天前
Vite 8 换上 Rolldown 后,前端构建真的会快很多吗?
前端·vite
裕波4 天前
Vue&ViteConf 2026 将于 7 月 18 日在上海举办,尤雨溪将现场发表主题演讲
vue.js·vite
鲁班小子5 天前
Vite resolve.dedupe 使用教程
vue.js·vite
kyriewen9 天前
从Webpack到Vite:我们迁移了一个10万行代码的项目,总结了这7个坑
前端·webpack·vite
大家的林语冰9 天前
尤雨溪官宣:Vite+ 全员加盟 Cloudflare,正式进军全栈开发和 AI 部署云平台!
前端·javascript·vite
明月_清风10 天前
爆破前端生态!Cloudflare 收购 Vite 背后,前端开发者会迎来什么变化?
前端·vite
Anesthesia丶13 天前
Vite + Svelte + shadcn-svelte 最小化 Demo+Vue3语法对比总结
vue·vite·svelte·shadcn-svelte
曲幽18 天前
写页面时别再把 Element Plus 整个搬进来啦!Vue3按需加载的坑我帮你踩平了
vue3·web·vite·icon·element plus·vs code·import·unplugin