根据 Ajax 请求更新整个页面
我有一个 AJAX 请求,可能有两种可能的结果:
- 服务器响应一条消息,我应将其放入
- 服务器响应 HTML 页面,在本例中我需要替换当前页面与新页面并更改地址(客户端在请求之前知道地址)。
如果我有需要处理这两种情况的 AJAX 请求,解决方案是什么?
url = "http://example.com"
ajax.request(callback)
function callback(response) {
if (case2(response)) {
history.pushState({}, "New page", url);
document.innerHTML = response
} else {
updateDiv(response)
}
}
我对实现第一个分支的正确方法感兴趣,或者服务器是否可以以某种方式组成一个标头,使浏览器能够像通常的 HTTP 响应一样处理响应并更新页面位置和内容,例如使用给定内容进行重定向。
我知道服务器可以返回链接而不是页面,但在这种情况下,客户端需要一个额外的阶段 - 重定向,然后在服务器上填充新页面。
I have an AJAX request that can have two possible outcomes:
- The server responds with a message which I should place in a
<div>
- The server responds with an HTML page, in this case I need to substitute current page with a new one and change the address (the client knows the address before a request).
What would be the solution if I have the AJAX request that needs to handle both of these cases?
url = "http://example.com"
ajax.request(callback)
function callback(response) {
if (case2(response)) {
history.pushState({}, "New page", url);
document.innerHTML = response
} else {
updateDiv(response)
}
}
I'm interested in a correct way to implement the first branch, or if the server can somehow compose a headers that will make browser to handle a response as a usual HTTP response and update a page location and content, something like redirect with given content.
I understand that the server can return a link instead of a page, but in this case one additional stage will be needed on a client - redirect and then populating the new page on the server.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
坦率地说,我认为这种方法基本上被设计所打破。你不应该在那个地方做出那个决定。例如,ajax 响应只能发出信号,表明应该加载整个新页面,然后在对新 URL 的第二个(非 ajax)请求上生成新内容。
如果您被迫采用已经采取的方式,并且响应内容不是很大,您可以尝试 Javascript-URI。基本上,
javascript:"string"
形式的 URI 将加载一个新页面,该页面是该字符串的源代码。因此,如果response
已经是一个字符串,只需将javascript:response
分配给window.location.href
就足够了。也许你必须事先做一些逃避。我不知道这种方法的跨浏览器兼容性如何。也是可以的。
其变体是不使用变量名称,而是使用实际的字符串数据构建 URL。 。
当然,这样会生成相当大的 URI 并且您将始终在地址栏中看到 Javascript-URI。
更新
类似的方法是在数据 URI 中使用 base64 编码。 维基百科条目解释了它的工作原理,包括一个 JavaScript 示例。但是,您必须对内容进行 base64 编码不知何故。 (注意:您可以使用带或不带 base64 编码的数据 URI。您必须了解什么可以为您的特定内容提供更短的 URI。)
Quite frankly, I think that approach is basically broken by design. You shouldn't have to make that decision at that place. For example, the ajax response could only signal that a whole new page should be loaded and the new content then be generated on a second (non-ajax) request to a new URL.
In case you're forced to take the way you already go, and provided the response content is not very large, you could try Javascript-URIs. Basically, an URI in the form of
javascript:"string"
will load a new page which that string is the source code for. So, ifresponse
already is a string, just assigningjavascript:response
towindow.location.href
should suffice. Maybe you have to do some escaping beforehand. And I don't know, how cross-browser-compatible this approach is.is also possible.
A variant of this is building the URL not with the variable name, but with the actual string data. Like
This will, of course, generate pretty large URIs. And you'll always have the Javascript-URI in the address bar.
UPDATE
A similar approach is to use base64 encoding in a data URI. The Wikipedia entry explains how it works, including a javascript example. However, you'd have to base64-encode the content somehow. (Note: You can use data URIs with or without the base64 encoding. You have to see what gives you shorter URIs for your specific content.)
我曾经遇到过类似的问题。返回完整的错误页面而不是简单的 HTML 片段。我们最终通过改变逻辑解决了这个问题,但这是我找到的解决方案之一:
我们放弃这个的原因是 IE 上存在一些问题。我没有浪费任何时间来调查原因,但在尝试写入字符串时它引发了“访问被拒绝”异常。我认为有一些
标签使 IE 感到困惑,或者可能是条件注释,我不确定。 (当我使用一些简单的页面时,它起作用了......)
底线是:您不必这样做,但如果您无能为力(例如返回 url 字符串),则上面的代码可能会起作用。
I had a similar issue once. A full error page was returned instead of a simple HTML snippet. We eventually fixed this by changing the logic, but here is one of the solutions I found:
The reason we abandoned this is that on IE there were some problems. I didn't loose any time to investigate why, but it threw an 'Access denied' exception when attempting to write the string. I think there were some
<meta>
tags that confused IE, or maybe conditional comments, I'm not sure. (It worked when I used some simple pages...)Bottom line is: you shouldn't have to do this, but if there is nothing else you can do (like returning an url string) the code above might work.
如果响应是有效的 XML,这真的很容易。
It's really easy if the response is valid XML.
由于请求是更新答案,因此这是我使用 HTML5 的 History API 的解决方案jQuery。通过将 PHP 和 HTML 部分合并到一个文件中,它应该可以轻松运行。
我的解决方案允许 AJAX 返回以下内容:
容器。
history.pushState()
将当前 URL 添加到浏览器的历史记录中,并替换浏览器上的整个 HTML包含从 AJAX 返回的 HTML 的页面。PHP
这只是 PHP 脚本通过 AJAX 调用时需要返回的示例。它展示了如何对标志进行编码以确定 AJAX 调用是否应该更新容器或加载新页面,以及如何通过
JS
因为我使用的是 jQuery,所以我们就从它开始吧。以下代码将 AJAX POST 提交到服务器,即 URL test.php 处的上述 PHP 脚本。请注意,它还将 POST 参数
ajax
设置为true
,使 PHP 脚本能够检测到它收到了 AJAX 请求。dataType
字段告诉 jQuery 服务器的响应将采用 JSON 格式,并且它应该在响应回调中将该 JSON 解码为 JSON 对象。最后,成功接收 AJAX 响应时触发的success
回调根据服务器发送的标志确定要执行的操作。HTML
这里是我测试的文件的完整 HTML 源代码。我在 FF4 - FF8 中测试过。请注意,jQuery 提供了 ready 方法来阻止 JS 在 DOM 加载之前执行。我还使用了 Google 的 jQuery 托管,因此您无需将 jQuery 的副本上传到您的服务器来进行测试。
Since the request is for an updated answer, here's my solution using HTML5's History API with jQuery. It should run easily by combining the PHP and HTML parts into one file.
My solution allows for AJAX to return the following:
<div>
container.history.pushState()
to add the current URL to the browser's history and replaces the entire HTML on the page with the HTML returned from AJAX.PHP
This is just a sample of what the PHP script will need to return when it is invoked via AJAX. It shows how to encode flags to determine whether the AJAX call should update the container or load a new page, and how to return its result via JSON through json_encode. For completeness, I named this script test.php.
JS
Since I am using jQuery, lets start with that. The following submits an AJAX POST to the server, to the above PHP script at URL test.php. Note that it also sets the POST parameter
ajax
to betrue
, enabling the PHP script to detect that it received an AJAX request. ThedataType
field tells jQuery that the server's response will be in JSON, and that it should decode that JSON to a JSON object in the response callback. Finally, thesuccess
callback, which is fired when the AJAX response is successfully received, determines what to do based on the flags sent from the server.HTML
Here is the complete HTML source of my tested file. I tested it in FF4 - FF8. Note that jQuery provides the
ready
method to prevent the JS from executing until the DOM is loaded. I've also used Google's hosting of jQuery, so you do not need to upload a copy of jQuery to your server to test this.给 body
一个 id,你的另一个 div 将为
现在你的ajax看起来像
Give an id to body
<body id="page">
and your other div will be<div id="message"></div>
now your ajax will look like正如 T-Bull 所说...整个过程在这里都是错误的...
您只是将事情过于复杂化了,而且您实际上知道:
停止复杂化并开始做好...
$_SESSION['tmp_client_id'] = 'client_'.session_id();
如果客户端已经订阅了,无论如何,将内容放入临时表或另一个会话变量等中...$_POST
变量存储在tmp_client_tbl
中,并使用其唯一的tmp_client_id
或仅$_SESSION['client_'.session_id()] = json_encode( $_POST);
if( isset($_SESSION['client_'.session_id()])) {
如果是这样,让我们再次显示带有填充字段的表单:} else {
显示空表格;从 tmp_client_tbl 中选择*,其中 tmp_client_id = '{$_SESSION['tmp_client_id']}'
或json_decode($_SESSION['client_'.session_id()]);
$form_data = $mysql_rows;
或$json_array;
foreach($form_data as $name => $value) { echo "<输入 name='$name' value='$value' />" }
以忍者的方式假设您有这样一种表单构建器数组,其中$form = array('text' => array('name','lastname'), 'select' => ; array('countries'), ... )
,或者简单地通过其中字段值已被空预污染变量;
session_destroy();
或unset($_SESSION['client_'.session_id()]);
as T-Bull say... the whole process is wrong here....
you simply are over-complicating things and you know that infact:
stop complicating and start do it well...
$_SESSION['tmp_client_id'] = 'client_'.session_id();
obviously is better if the client is already subscribed, anyway, put stuff in temp table OR into another session var etc...$_POST
variable insidetmp_client_tbl
with it's uniquetmp_client_id
OR just$_SESSION['client_'.session_id()] = json_encode($_POST);
</div>
if( isset($_SESSION['client_'.session_id()])) {
if so let's display the form again with filled fields:} else {
display empty form;SELECT * FROM tmp_client_tbl WHERE tmp_client_id = '{$_SESSION['tmp_client_id']}'
ORjson_decode($_SESSION['client_'.session_id()]);
$form_data = $mysql_rows;
OR$json_array;
foreach($form_data as $name => $value) { echo "<input name='$name' value='$value' />" }
in a ninja way that assume you have such kind of form builder array where$form = array('text' => array('name','lastname'), 'select' => array('countries'), ... )
, OR simply by<input name='lastname' value='{$lastname}' />
where the fields values are pre-polutated with empty vars;session_destroy();
orunset($_SESSION['client_'.session_id()]);