[英]How can I render a static HTML file with Handlebars on a Nodejs server?
[英]How can I render a Handlebars file using two different routes?
我正在努力从新闻网站上抓文章。 我已经成功地删除了文章,数据已成功到达前端。 (它正确的console.log)。 我的问题是我无法使用按钮将数据呈现到页面上 - 数据仅在我刷新时填充页面。
我知道这个问题与Handlebars有关,因为如果我尝试使用jQuery渲染页面,它就可以了。
我相信这与我的路线有关。 我通过/ articles路由将数据发送到页面,但正如您所看到的,我并没有专门使用res.render或res.redirect。 我想这就是为什么它不起作用? 但是,我不知道如何解决它。 我对路线和回调有点不稳定。 我是编码的新手,但我向你保证,我已经研究并尝试了许多修复无济于事。 任何帮助或指导表示赞赏。 谢谢。
app.get("/", function(req, res) {
db.Article
.find({})
.then(function(dbArticle) {
// res.render("index");
res.render("index", { articles : dbArticle });
});
});
app.get("/scrape", function(req, res) {
axios.get("https://www.nytimes.com/section/technology?
action=click&pgtype=Homepage®ion=TopBar&module=HPMini
Nav&contentCollection=Tech&WT.nav=page")
.then(function(response) {
var $ = cheerio.load(response.data);
$("a.story-link").each(function(i, element) {
var results = {};
results.link = $(this).attr("href");
// console.log("This is my link " + results.link)
results.blurb = $(this).children().find(".summary").text();
// console.log("This is my blurb " + results.blurb)
results.headline = $(this).children().find(".headline").text();
// console.log("This is my headline " + results.headline)
db.Article
.create(results)
.then(function(dbArticle) {
res.json(dbArticle);
// res.end();
// console.log("YES", dbArticle);
})
.catch(function(err) {
res.json(err);
})
})
})
})
app.get("/articles", function(req, res) {
db.Article
.find({})
.then(function(dbArticle) {
res.json(dbArticle);
// console.log(dbArticle, "scraped")
})
.catch(function(err) {
res.json(err);
});
});`
在某个地方,你有一个概念上的脱节。 我不知道到底在哪里,我将试图涵盖一些基础知识,希望我可以填补相关的差距。
假设您的Express服务器运行在localhost:3000
。 它在localhost
上并不重要,如果代码在世界各地的计算机上运行,一切都会有相同的效果。 关键是浏览器无法看到您的代码,它具有HTML,CSS,JavaScript等的先天知识,但对您的应用程序一无所知。
当您在浏览器地址栏中键入URL http://localhost:3000/
,它会对运行在localhost:3000
上的服务器上的路径/
发出HTTP GET
请求。 请求只是通过网络发送的一系列字节(当我说'wire'认为网络电缆时,即使实际上没有涉及物理网络电缆)。 使用浏览器的开发工具查看“网络”部分,并跟踪此特定请求。 单击它并查看请求详细信息。
浏览器完全不知道服务器中发生了什么。 请记住,就浏览器而言,这台服务器“遍布全球”。
当这个请求到达你的服务器时,它会通过你在app.get('/', ...
注册的app.get('/', ...
。对res.render
的调用会运行Handlebars模板并生成一串HTML标记然后将该字符串转换为字节,并将这些字节作为响应体“通过线路”发送回来。响应还有一些标题来描述正文中的内容,但最终它只是序列中发送的大量字节。
这个响应是回到浏览器的。 它不知道它是如何生成的。 就浏览器而言,它可以很容易地从静态文件中提供。 它并不关心。 它需要这个HTML标记(即一大块文本)并解析它以创建一个DOM树。 这是一个正确的数据结构,重要的是要明白它与相应的标记是截然不同的(虽然密切相关)。 关于术语的简短说明,我们称之为tag
中的标记成为DOM中的element
节点。 然后,浏览器获取DOM节点树并使用它们生成页面图像,这是实际在浏览器视口中向用户显示的图像。
为什么我一直在谈论通过网络发送'字节'? 不是一切都只是字节? 嗯,是的,不。 如果你有一个像数组或对象这样的数据结构,你不能只是通过网络发送它。 它可能使用计算机内存中的字节来表示,但要将其作为HTTP请求/响应的一部分发送,需要将其转换为一种格式,将其表示为一个接一个的线性字节序列。 此过程通常称为序列化。 HTML标记字符串是HTML DOM节点的序列化表示,就像JSON通常用作序列化JavaScript数据结构(如对象和数组)的方式一样。
所以,回到我们/
请求,如果您查看浏览器开发工具的网络部分,您将能够看到请求和响应。 它以一种格式良好的方式呈现它,因此您不必尝试自己读取原始字节序列。 为了重申关键点,浏览器只知道HTTP响应告诉它的内容,它不知道您使用Handlebars来创建HTML标记。
当然,标记可以包含其他资源的URL,例如图像,CSS,JavaScript等。 当浏览器将标记解析为DOM节点时,它会遇到这些其他URL,并在需要时为每个URL发出单独的HTTP请求。 这些请求中的每一个都与原始/
请求的行为大致相同,并且浏览器再次不知道服务器如何生成响应:它可能返回静态文件的内容,或者它可能生成整个响应-the飞。
现在我们来讨论更新页面以响应用户交互的主题。
也许最容易理解的互动点击链接,即<a href="/other-url">click</a>
等锚标记。 这只会更新浏览器地址栏中的URL并丢弃上一页。
HTML表单类似,但它可以执行各种其他技巧,例如POST
请求。 表单是使用<form>
元素构建的(也许更准确地说我应该说form
元素,没有<
和>
,但我认为<form>
更容易理解,只要我们清楚标记和DOM中的标记之间的区别元件)。 出于本说明的目的,它们与锚链接非常相似。 浏览器URL会更新,并且会在其中加载新页面。 (我不打算在这里介绍它,但有办法提交表格,以便当前页面不会改变)。
这两种方法都会丢弃页面并从服务器上重新加载它。 多年来,这就是动态网站的构建方式。 然后AJAX出现了。
使用AJAX,您可以在JavaScript中执行HTTP请求,而无需更改当前页面位置。 浏览器并没有真正尝试理解从AJAX请求返回的响应,它只是进行了一些基本的解析,然后将其交给您注册的任何回调。
这让我们回到原来的例子。 您有一个AJAX请求呼叫服务器并撤回一些JSON数据。 然后使用jQuery使用该JSON相应地更新页面的DOM节点。 这是一个非常好的方法,但让我们谈谈一些替代方案。
目标是更新页面以反映新数据,就像我们完整刷新页面一样。 为此,我们需要使用由Handlebars生成的标记中的jQuery构建完全相同的DOM节点结构。 这显然违反了DRY原则,因为我们在两个地方重复了相同的结构。
删除此重复的一种方法是始终使用AJAX加载页面的该部分。 使用Handlebars(在服务器上)初始呈现页面将使页面的该部分留空,然后一旦页面加载,一些客户端JavaScript将用于启动AJAX请求。 这可能会略微延迟页面的初始加载时间,也可能导致SEO出现问题,但对于很多SPA而言,这些并不是很重要的问题,因此这就是使用的方法。
在光谱的另一端,我们可以重新加载页面。 我们可以通过执行AJAX请求来执行此操作,然后在请求成功后单独重新加载页面(例如,使用window.location.reload()
)。 我们也可以完全删除AJAX请求。 相反,我们可以将表单提交给相关的更新URL。 服务器将对数据执行相关更改,然后返回新呈现的页面,最有可能使用res.render
调用,就像它对/
route一样。
然后我们有两个解决方案,介于两者之间。
我们仍然可以使用AJAX请求并更改响应,这样它不会返回JSON,而是返回HTML标记以注入页面的相关部分。 我们需要使用合适的partial来分割服务器上的Handlebars模板,这样我们就可以生成我们需要的小部分HTML而不是整个页面的HTML。
另一个中间解决方案是在两端都有把手。 数据仍将使用JSON加载,但它将通过浏览器中的Handlebars模板运行。 要使其正常工作,您需要将相关的Handlebars JS文件加载到浏览器中。 您还需要找到一种方法将相关模板放入浏览器,或者使用AJAX请求加载它,或者更可能在服务器上初始呈现页面时注入它。
这是四种不同的方法,我们远远没有用尽可能性。 鉴于这是一个学习练习,而不是一个现实世界的问题,实际上不可能打电话给哪种方法是最好的,每种方法都有利有弊。 我认为最重要的是让你清楚服务器上运行什么代码以及客户端运行什么代码以及两者如何通过HTTP请求进行交互。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.