javascript node.js 和单页 Web 应用程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19040148/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 14:09:02  来源:igfitidea点击:

node.js and single page web application

javascriptajaxjsonnode.jsexpress

提问by reza

I am looking at express.js for the back end and JS on the client side. My app is a single page Web App.

我正在查看后端的 express.js 和客户端的 JS。我的应用程序是单页 Web 应用程序。

The server will only serve JSON messages and my question is about "routing" for express. Is one supposed to use routing to connect the UI and the server side business logic? How will that work with my single page app?

服务器将只提供 JSON 消息,我的问题是关于 express 的“路由”。是否应该使用路由来连接 UI 和服务器端业务逻辑?这将如何与我的单页应用程序一起使用?

so lets say, the client makes an Ajax call to the server looking for a value in the database and there is server side script that provides the JSON back to the UI. How is this UI and node script relationship setup?

因此,可以说,客户端向服务器发出 Ajax 调用以查找数据库中的值,并且有服务器端脚本将 JSON 提供回 UI。这个 UI 和节点脚本关系是如何设置的?

Can someone shed some light on this?

有人可以对此有所了解吗?

回答by ryan.l

Single page apps are those that live on a single HTML document. This means that if you want to display some different content to the user, depending on the state of the application, you will need to do some DOM manipulation (cutting out and replacing certain elements of the current document with different HTML) in order to update the 'view' that the user sees. Excuse me if this is obvious to you, please don't take offense. I figured I'd start from here. Hang with me and I'll explain how your routing situation is going to play out (more or less).

单页应用程序是那些存在于单个 HTML 文档中的应用程序。这意味着如果你想向用户显示一些不同的内容,根据应用程序的状态,你需要做一些 DOM 操作(用不同的 HTML 剪切和替换当前文档的某些元素)才能更新用户看到的“视图”。对不起,如果这对你来说很明显,请不要冒犯。我想我会从这里开始。和我一起,我会解释你的路由情况将如何发展(或多或少)。

URLs are composed of a few different parts, each of which informs the browser of a particular bit of information that is required in order to download the resource that the user is attempting to access. Typically the resources that you are looking for are off on a server somewhere and the browser knows this because of pieces in the URL like 'protocol' ('http:') and 'host' ('www.mydomain.com'), so it goes off to that server to find what you're requesting. There are also 'query' parameters in URLs which provide some additional information to the server regarding a particular action, like the search terms of a search query. After the query parameters, comes the 'hash'. The hash is where the magic of single page apps happens... eh, well, kind of.....

URL 由几个不同的部分组成,每个部分都通知浏览器特定的信息位,以便下载用户尝试访问的资源。通常,您要查找的资源在某处服务器上关闭,浏览器知道这一点,因为 URL 中的部分如“协议”(“http:”)和“主机”(“www.mydomain.com”),因此它会转到该服务器以查找您所请求的内容。URL 中还有“查询”参数,它们向服务器提供有关特定操作的一些附加信息,例如搜索查询的搜索词。在查询参数之后,是“哈希”。散列是单页应用程序的魔法发生的地方......呃,嗯,有点......

First a bit about the hash. When you add a '#' to a URL, the browser then interprets the information that comes after it to be some location (element) within the currently displayed document. That means, if you have an element with an 'id' of 'main' and you add '#main' to the end of the URL, like so: 'http: //www.example.com#main', the browser will 'scroll' (typically 'jump') to the beginning of that element, so that the you can see it. Be aware, though, that if you type 'http://www.example.com/#main' (with the hash separated from the URL by a slash) then you will force a complete page reload and the browser will attempt to find a file by the name '#main' on the server (I bet it doesn't find it).

首先介绍一下哈希。当您向 URL 添加“#”时,浏览器会将它后面的信息解释为当前显示文档中的某个位置(元素)。这意味着,如果您有一个 'id' 为 'main' 的元素,并且您将 '#main' 添加到 URL 的末尾,例如:'http://www.example.com#main',浏览器将“滚动”(通常是“跳转”)到该元素的开头,以便您可以看到它。但是请注意,如果您键入“ http://www.example.com/#main”(用斜杠将哈希与 URL 分开),那么您将强制重新加载完整的页面,浏览器将尝试查找服务器上名为“#main”的文件(我敢打赌它找不到)。

The takeaway here is that the browser will not attempt to navigate away from the current document if there is a hash in the URL, the exception being of course the case mention above, and this is great because single-page apps don't want to navigate away from the pageor request a new document from the server. (See how routing is different for single-page apps?)

这里的要点是,如果 URL 中有散列,浏览器将不会尝试离开当前文档,当然上面提到的情况除外,这很好,因为单页应用程序不想离开页面或从服务器请求新文档。(了解单页应用的路由有何不同?)

Now, this whole thing about the hash isn't vital to single-page apps, as you could make one without dealing with it all. A bunch of click handlers and DOM manipulation is all you'd need really... But, that would mean that users will have no way of sharing links to particular views in your app. The URL would never change, and we would never be able to navigate to any particular view directly. We'd always be starting from the starting position of your app, which could easily be a very annoying situation.

现在,关于散列的整个事情对于单页应用程序来说并不重要,因为您可以在不处理所有内容的情况下制作一个。您真正需要的是一堆点击处理程序和 DOM 操作……但是,这意味着用户将无法共享指向您应用程序中特定视图的链接。URL 永远不会改变,我们永远无法直接导航到任何特定视图。我们总是从您的应用程序的起始位置开始,这很容易成为一个非常烦人的情况。

If your single-page app is going to have different views, and you want users to be able to navigate directly to particular ones via bookmarks or links, then you will need to implement a form of routing on the front-end in addition to the routing that you'll need to implement on the backend (routing for data API, etc.), which means that you will need to make use of the hash.

如果您的单页应用程序将有不同的视图,并且您希望用户能够通过书签或链接直接导航到特定的视图,那么除了您需要在后端实现的路由(数据 API 的路由等),这意味着您将需要使用散列。

I don't want to get into how different frameworks accomplish routing on the front-end, but it's basically a matter of updating the browser's address field when the user clicks a link, and watching the address bar to determine what the current URL is and loading the HTML that is associated with that URL into the DOM in the designated location in the document tree.

我不想深入探讨不同框架如何在前端完成路由,但基本上是在用户单击链接时更新浏览器的地址字段,并观察地址栏以确定当前 URL 是什么以及将与该 URL 关联的 HTML 加载到文档树中指定位置的 DOM 中。

So, within a single-page app, you have one route on the server that deals with rendering the app HTML document (index.html), and you have routes that are responsible for dealing with the data of your app (creating new instances in the database, logging in and out, editing or destroying instances in the DB, and fetching data...) which are called via AJAX requests.

因此,在单页应用程序中,您在服务器上有一个处理呈现应用程序 HTML 文档 (index.html) 的路由,并且您有负责处理应用程序数据的路由(在数据库、登录和注销、编辑或销毁数据库中的实例以及获取数据...),这些都是通过 AJAX 请求调用的。

This is actually a fairly complicated situation in that HTML5 allows us to be able to forgo the hash (with the help of some link rewriting on the server) and also be able to use the 'back' and 'forward' buttons as if we've actually navigated away from the original document (which we haven't because we have only pointed the browser to the exact same URL, only with modified hash values, so no new page loads have occurred). Traditional site navigation and linking can be achieved by utilizing the browser's History API, which is available for IE beginning with version 10 (I believe), the rest of the big browser vendors were already on to it quite a bit earlier, so frameworks that leverage this technology will allow your users to navigate your app without the hash in the URL. Explaining this is a diversion and not necessary for understanding routing in single-page apps, but it is interesting and you'll have to learn it eventually anyway, probably..

这实际上是一个相当复杂的情况,因为 HTML5 允许我们能够放弃哈希(借助服务器上的一些链接重写),并且还能够像我们一样使用“后退”和“前进”按钮实际上已经导航离开了原始文档(我们没有导航,因为我们只是将浏览器指向了完全相同的 URL,只有修改了哈希值,所以没有发生新的页面加载)。传统的站点导航和链接可以通过利用浏览器的 History API 来实现,该 API 从版本 10 开始可用于 IE(我相信),其他大型浏览器供应商早就已经开始使用它,因此利用框架这项技术将允许您的用户在没有 URL 散列的情况下导航您的应用程序。

AJAX should be used to request JSON from the server. AJAX requests will always hit your server because you don't include the hash symbol in AJAX requests (it would be ridiculous to do so because the hash is meant only for in-document browsing), so server-side routes must be responsible for exposing your data API (consider a RESTful one). While this is not their sole purpose in single-page apps, it is perhaps their most important one.

AJAX 应该用于从服务器请求 JSON。AJAX 请求将始终命中您的服务器,因为您没有在 AJAX 请求中包含哈希符号(这样做很荒谬,因为哈希仅用于文档内浏览),因此服务器端路由必须负责暴露您的数据 API(考虑 RESTful API)。虽然这不是它们在单页应用程序中的唯一目的,但它可能是它们最重要的目的。

Soooo, to wrap it up, you will have two sets of routes. One on the client (as part of a client-side framework like AngularJS or EmberJS, the list goes on... I prefer Angular, but there is a fairly steep learning curve for that one.), and one on the server. When you think about 'server routes' think data API. When you think of 'page routing', remember that this all gets handled on the client, by the javascript that you delivered with the initial server response (this is the one and only necessary server-side route involved with rendering HTML to the browser, loading your 'index.html' and all of the necessary scripts and stylesheets, etc). You will use express.static middleware to serve static files, so you don't have to worry about assigning routes for that stuff.

Soooo,总结一下,你将有两组路线。一个在客户端(作为像 AngularJS 或 EmberJS 这样的客户端框架的一部分,这个列表还在继续……我更喜欢 Angular,但那个有一个相当陡峭的学习曲线。),一个在服务器上。当您考虑“服务器路由”时,请考虑数据 API。当您想到“页面路由”时,请记住,这一切都在客户端处理,由您随初始服务器响应一起交付的 javascript(这是将 HTML 呈现给浏览器所涉及的唯一必要的服务器端路由,加载您的“index.html”以及所有必要的脚本和样式表等)。您将使用 express.static 中间件来提供静态文件,因此您不必担心为这些东西分配路由。

EDIT A quick mention of AJAX implementation. On the server, you will have routes similar those that Alex has provided as examples and you will make calls to those URLs from the client using whatever XMLHttpRequest (XHR) object is exposed by your framework or library of choice. It is now considered more or less standard and best practice for frameworks/libraries to implement these requests as Promises http://wiki.commonjs.org/wiki/Promises/A. You should read a bit about it on your own, but I might be able to summarize it by saying that it is an asynchronous operation analogous to 'try, catch, throw' in synchronous operations. You will instantiate a promise object and through it you will attempt to load data from the server, for instance, via GET request. Make sure that you have assigned functions to handle requests made to the URL that you made the request to (server-side route)! This object that you instantiate and subsequently make the request to the server through, promises to return the result of the request to you once it comes back from the server (no matter whether it was successful or not) If it is successful, it will call a function that you have written and will supply it with the data from the server. If it fails, it will call a different function, also written by you, and will supply it with the error object (or 'reason' for failure), so you can handle the error appropriately.

编辑 快速提及 AJAX 实现。在服务器上,您将拥有与 Alex 作为示例提供的路由类似的路由,并且您将使用您的框架或选择的库公开的任何 XMLHttpRequest (XHR) 对象从客户端调用这些 URL。现在,框架/库将这些请求实现为 Promises http://wiki.commonjs.org/wiki/Promises/A或多或少被认为是标准和最佳实践. 您应该自己阅读一些关于它的内容,但我可以通过说它是一种类似于同步操作中的“try、catch、throw”的异步操作来总结它。您将实例化一个 promise 对象,并通过它尝试从服务器加载数据,例如,通过 GET 请求。确保您已分配函数来处理对您发出请求的 URL 发出的请求(服务器端路由)!您实例化并随后通过该对象向服务器发出请求的对象,承诺一旦从服务器返回请求结果(无论是否成功),如果成功,它将调用您编写的一个函数,它将向它提供来自服务器的数据。如果失败,它将调用不同的函数,

Hope that helped answer your question.

希望对回答您的问题有所帮助。

回答by Alex Wayne

You only have to route requests you serve dynamically. Your HTML, CSS, JS are all static assets. So all you need to handling routing for is your data.

您只需要路由您动态服务的请求。你的 HTML、CSS、JS 都是静态资产。因此,您处理路由所需的只是您的数据。

It sounds like you want a Restful API, which basically means that you have URLs for specific resources, and HTTP verbs for manipulating them.

听起来您想要一个Restful API,这基本上意味着您拥有特定资源的 URL,以及用于操作它们的 HTTP 动词。

Something like:

就像是:

  • GET /books.json- Get all books
  • POST /books.json- Create a new book with properties passed in the body of the request
  • GET /books/123.json- Get book with id of 123
  • PUT /books/123.json- Update an existing book with properties passed in the body of the request
  • GET /books.json- 获取所有书籍
  • POST /books.json- 使用在请求正文中传递的属性创建一本新书
  • GET /books/123.json- 获取 ID 为 123 的书
  • PUT /books/123.json- 使用在请求正文中传递的属性更新现有书籍

This blog post seems to show how to set this up in Express.

这篇博文似乎展示了如何在 Express 中进行设置。

Once you have a sane API delivering JSON, you just make your AJAX calls use it based on what objects you want to fetch.

一旦您拥有一个提供 JSON 的健全 API,您只需根据您想要获取的对象让您的 AJAX 调用使用它。