我怎样才能使用两个不同的路线呈现一个Handlebars文件?

我正在从新闻网站上刮取文章。 我已经成功地刮掉了文章,数据成功地到达了前端。 (它console.log正确)。 我的问题是,我无法使用button将数据呈现到页面上 – 数据只在刷新时填充页面。

我知道这个问题与Handlebars有关,因为如果我尝试使用jQuery呈现页面,它就可以工作。

我相信这与我的路线有关。 我通过/ articles路由将数据发送到页面,但正如您所看到的,我没有具体使用res.render或res.redirect。 我想这就是为什么它不起作用? 但是,我不知道如何解决这个问题。 我在路由和callback方面有点不稳定。 我是新来的编码,但我向你保证,我已经研究和尝试了无数的修复无济于事。 任何帮助或指导表示赞赏。 谢谢。

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&region=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的服务器上为path发出HTTP GET请求。 请求只是一个字节序列(当我说“有线”认为networking电缆,即使实际上并没有涉及物理networking电缆)。 使用浏览器的开发工具在networking部分查看并追踪这个特定的请求。 点击它,看看请求的细节。

浏览器完全不知道服务器上发生了什么。 记住,就浏览器而言,这个服务器是“世界的一半”。

当这个请求到达你的服务器时,它会find你在app.get('/', ...注册的路由app.get('/', ...的调用将运行Handlebars模板并生成一个HTML标记。这个string然后被转换成字节,这些字节作为响应主体被“回线”发送回来。响应也有一些标题来描述正文中的内容,但是最终它只是一个序列中发送的很多字节。

这个回应是什么回到浏览器。 它不知道它是如何产生的。 就浏览器而言,它可以很容易地从静态文件提供。 它不关心。 它需要这个HTML标记(即一大块文本)并parsing它来创build一个DOM树。 这是一个合适的数据结构,重要的是要明白它与相应的标记是截然不同的(尽pipe密切相关)。 关于术语的简要说明,我们在标记中称之为tag ,成为DOM中的一个element节点。 然后浏览器使用这个DOM节点树并使用它们生成页面的图像,这是在浏览器视口中实际显示给用户的内容。

为什么我一直在谈论发送'通过电线的字节'? 不是一切都只是字节? 那么,是的,不。 如果你有一个像数组或数据结构的数据结构,你不能只是发送'通过电线'。 它可以用计算机内存中的字节来表示,但是可以将它作为HTTP请求/响应的一部分来发送,它需要被转换成一种格式,将其表示为一个字节的线性序列。 这个过程通常被称为序列化。 HTML标记的string是HTML DOM节点的序列化表示,就像JSON经常被用作序列化JavaScript数据结构(如对象和数组)的方式一样。

所以,回到我们的请求,如果你看看浏览器的开发工具的networking部分,你将能够看到请求和响应。 它以很好的格式显示,所以你不必尝试自己读取原始的字节序列。 为了重申关键点,浏览器只知道HTTP响应告诉它什么,它不知道你使用Handlebars来创buildHTML标记。

当然,标记可能包含其他资源(如图像,CSS,JavaScript等)的URL。 当浏览器将标记parsing到DOM节点时,它会遇到这些其他的URL,并在需要时为每个请求分别发出HTTP请求。 每个请求的行为与原始/请求的行为大致相同,并且浏览器再次不知道服务器如何生成响应:它可以返回静态文件的内容,也可以生成整个响应-the飞。

所以现在我们来回应用户交互更新页面的话题。

也许要理解的最简单的互动是点击一个链接,即像<a href="/other-url">click</a>这样的定位标记。 这只是更新浏览器地址栏中的url,并丢弃上一页。

一个HTML表单是相似的,但它可以执行各种其他技巧,如POST请求。 表单是使用<form>元素构build的(可能更准确地说,我应该说form元素,没有<> ,但是我认为<form>更容易理解,只要我们清楚标记和DOM中标记之间的区别元件)。 为了描述的目的,它们与锚链接非常相​​似。 浏览器的URL得到更新,新的页面被载入。 (我不打算在这里覆盖它,但有一些方法可以提交表单,以便当前页面不会改变)。

这两种方法都会丢弃页面,并从服务器上重新加载它。 多年来,这是如何build立dynamic网站。 然后AJAX来了。

使用AJAX,您可以在JavaScript内执行HTTP请求,而无需更改当前的页面位置。 浏览器并没有试图理解AJAX请求返回的响应,只是做了一些基本的parsing,然后把它交给你注册的callback函数。

这使我们回到你原来的例子。 你有一个AJAX请求调用服务器,并拉回一些JSON数据。 然后使用jQuery来使用该JSON来相应地更新页面的DOM节点。 这是一个非常好的方法,但让我们谈谈一些替代scheme。

目标是更新页面以反映新的数据,就像我们刷新整个页面一样。 要做到这一点,我们需要使用jQuery来build立完全相同的DOM节点结构,这些jQuery将在Handlebars生成的标记中。 这显然违反了DRY原则,因为我们已经在两个地方重复了同样的结构。

消除这种重复的一种方法是始终使用AJAX加载页面的该部分。 使用Handlebars(在服务器上)初始渲染页面会使页面的这一部分保持空白,然后一旦客户端页面加载,一些客户端JavaScript将用于启动AJAX请求。 这可以稍微延迟页面的初始加载时间,也可能会导致search引擎优化的问题,但对于很多的SPA,这些都不是重大的关注,所以这是使用的方法。

在频谱的另一端,我们可以重新加载页面。 我们可以通过执行AJAX请求来完成此操作,然后在请求成功后(例如,使用window.location.reload() )单独重新加载页面。 我们也可以完全删除AJAX请求。 相反,我们可以将表单提交到相关的更新URL。 服务器将对数据执行相关更改,然后返回新呈现的页面,很可能使用res.render调用,就像为/ route一样。

然后我们有两个解决scheme,坐在两者之间。

我们仍然可以使用AJAX请求并更改响应,以便不返回JSON而是返回HTML标记以注入页面的相关部分。 我们需要在服务器上使用合适的partial来分割Handlebars模板,这样我们才能生成我们需要的HTML的一小部分,而不是整个页面的HTML。

另一个中间解决scheme是两端都有把手。 数据仍将使用JSON加载,但会通过浏览器中的Handlebars模板运行。 为了得到这个工作,你需要把相关的Handlebars JS文件加载到浏览器中。 您还需要find一种方法将相关模板join到浏览器中,或者使用AJAX请求加载它,或者更有可能在服务器上初始渲染页面的过程中注入它。

所以这是四种不同的方法,我们并没有耗尽可能性。 鉴于这是一个学习练习,而不是一个现实世界的问题,不可能就哪种方法是最好的进行调用,每个方法都有优点和缺点。 我认为最重要的是要清楚在服务器上运行哪些代码以及在客户端运行哪些代码,以及两者如何通过HTTP请求进行交互。