jQuery移动多页切换页面前等待ajax返回数据
Posted
技术标签:
【中文标题】jQuery移动多页切换页面前等待ajax返回数据【英文标题】:jQuery mobile multipage wait for ajax to return data before switching pages 【发布时间】:2017-09-27 01:21:34 【问题描述】:我在多页表单中使用 jQuery mobile。当用户单击标记为 Next Page 的按钮时,我想运行 AJAX 请求。根据 AJAX 请求的结果,我想阻止用户访问下一页。
我相信我遇到的问题是我的 AJAX 请求比下一页事件需要更长的时间来回复。因此,它让用户进入下一页而不让 AJAX 请求完成。
至少我认为这是正在发生的事情。有没有人遇到过这个问题或知道这个问题的解决方案?
html:
<div id="page1" data-role="page">
<div data-role="header" data-position="fixed" data-theme="d">
<a href="#page2" data-role="button" id="btnPage2" class="ui-btn-right" data-icon="arrow-r">Next Page</a>
</div>
<div role="main" class="ui-content">
<label for="testVal">Test Val:</label>
<input type="text" id="testVal" name="testVal"/>
</div>
</div>
<div id="page2" data-role="page">
<div role="main" class="ui-content">
</div>
</div>
jQuery:
$('#btnPage2').click(function()
var isValid = '';
var aValue = $('#testVal').val();
$.ajax(
type: "POST",
url: "php-file.php",
data: "something":aValue ,
success: function(data)
var json = $.parseJSON(data);
if(json.hasOwnProperty('error'))
console.log("the user is not allowed on page 2");
isValid = false;
else
isValid = true;
);
if(!isValid)
alert('sorry you can not enter page 2');
return false;
);
在上面的代码示例中,当我单击“下一页”按钮(即#btnPage2
)时,它允许我访问第 2 页,即使当我检查控制台日志并看到“该用户在页面上是不允许的” 2" .
更新:
我尝试将代码调整为以下内容。它有点工作,但只有在不允许用户访问 page2 时。 e.preventDefault
正在让 ajax 完成,但是我想不出一种强制更改 page2 的方法。如果允许用户访问 page2 行
$(":mobile-pagecontainer").pagecontainer("change", "#page2");
似乎是导致问题的原因...它只是创建了调用 pageChange 事件的无限循环。我认为这是强制将页面更改为 page2 的方法,但我认为我错了,我无法弄清楚如何强制它更改为 page2
$(document).bind('pagebeforechange', function(e, data)
var to = data.toPage,
from = data.options.fromPage;
if (typeof to === 'string')
var u = $.mobile.path.parseUrl(to);
to = u.hash || '#' + u.pathname.substring(1);
if (from) from = '#' + from.attr('id');
if (from === '#page1' && to === '#page2')
e.preventDefault();
var aValue = $('#testVal').val();
$.ajax(
type: "POST",
url: "php-file.php",
data: "something":aValue ,
cache: false,
success: function(data)
var json = $.parseJSON(data);
if(json.hasOwnProperty('canNotPass'))
alert('Sorry you can not view page 2');
else
/// if json does not contain canNotPass then continue to page2
$(":mobile-pagecontainer").pagecontainer("change", "#page2");
,
beforeSend: function()
$.mobile.loading("show");
,
complete: function()
$.mobile.loading("hide");
);
);
更新 #2
我尝试实施@deblocker 修复,但仍然遇到同样的问题。当我在 ajax 将canNotPass
设置为true
的情况下运行以下代码时,代码似乎永远不会达到测试canNotPass
的值的地步。因此,它永远不会设置e.preventDefault
,并且允许用户访问page2。
我认为解决方案与设置延迟对象有关,该对象将允许 ajax 在页面更改发生之前完成。唯一的问题是我知道如何设置/使用延迟对象。
JSFiddle
【问题讨论】:
听起来很丑,var isValid = ''
(字符串),然后isValid = true
(布尔)
在这里 pagecontainerbeforechange – How to use it 你会发现 Omar 关于这个主题的精彩帖子。
【参考方案1】:
使用按钮而不是锚点:
<button id="btnPage2" class="ui-btn-right ui-icon-arrow-r">Next Page</a>
...并通过 success
处理程序中的代码导航:
$(":mobile-pagecontainer").pagecontainer("change", "#page2")
;
顺便说一句,您还可以使用 ajax 中的一些其他处理程序:
$.ajax(
type:...
url:...
data:...
success: ...
beforeSend: function()
$.mobile.loading("show");
,
complete: function()
$.mobile.loading("hide");
,
error: function (request,error)
alert('sorry you can not enter page 2');
);
更新:
按照 Omar 的建议,在 pagecontainerbeforechange
处理程序的第一部分中,您应该中断导航,因为您已经在第 2 页的中途。因此,您无需再告诉pagecontainer
切换到pagecontainerbeforechange
事件中的page2。您应该简单地将您的 ajax 请求和您的 canNotPass
标志保留在 $('#btnPage2').click()
中。
演示:
$(document).on("pagecontainerbeforechange", function(e, ui)
var from = "#" + $(":mobile-pagecontainer").pagecontainer("getActivePage").prop("id");
var to = ui.toPage;
if (typeof ui.toPage == "string")
var u = $.mobile.path.parseUrl(to);
to = u.hash || "#" + u.pathname.substring(1);
if (from === "#page-one" && to === "#page-two")
var canNotPass = !$("#canPass").prop("checked");
if(canNotPass)
e.preventDefault();
$.mobile.activePage.find('.ui-btn-active').removeClass('ui-btn-active').blur();
);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<link rel="stylesheet" href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.css">
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.js"></script>
</head>
<body>
<div data-role="page" id="page-one">
<div data-theme="a" data-role="header" data-position="fixed">
<h1>First Page</h1>
<a href="#page-two" class="ui-btn-left">Next</a>
</div>
<div data-role="content">
<label for="canPass">Can Navigate to Page 2 ?</label>
<input data-role="flipswitch" name="canPass" id="canPass" data-on-text="Yes" data-off-text="No" type="checkbox">
</div>
<div data-theme="a" data-role="footer" data-position="fixed">
<h1>Footer</h1>
</div>
</div>
<div data-role="page" id="page-two">
<div data-theme="a" data-role="header" data-position="fixed">
<h1>Second Page</h1>
<a href="#page-one" class="ui-btn-left">Back</a>
</div>
<div data-role="content">
</div>
<div data-theme="a" data-role="footer" data-position="fixed">
<h1>Footer</h1>
</div>
</div>
</body>
</html>
EDIT2:(来源:Omar)- 以下是如何将直接导航设置为“受保护”页面
$(document).on("pagecontainerbeforechange", function(e, ui)
/* in case user enter foo.com/#page2 directly */
if (typeof ui.toPage === "object" && ui.absUrl === undefined && ui.toPage[0].id == "page2")
/* make ajax call */
var ajaxCall = true;
if (ajaxCall)
$.noop
else
ui.toPage = "#noAccessPage"
/* internal navigation from page1 to page2 */
if (typeof ui.toPage === "string" && ui.absUrl !== undefined && $.mobile.path.parseUrl(ui.absUrl).hash == "#page2")
/* make ajax call */
var ajaxCall = true;
if (ajaxCall)
$.noop
else
ui.toPage = "#noAccessPage"
);
【讨论】:
正确答案。我还要添加一些代码来防止用户通过直接输入 URL ***.com/a/26833994/1771795 来访问页面,因为它是一个多页面模型,toPage 应该是一个“字符串”,仅此而已。 @Omar 感谢您的建议。我尝试实现您建议的代码,但我一生都无法弄清楚如何让它工作。我最终用我的想法更新了我的帖子。我是否走在正确的轨道上? 仍然遇到问题。我根据您的最新建议设置了一个 JSFiddle 并编辑了我的原始帖子。也许你可以看看它。 JSFiddle @Austin jsfiddle.net/zccj6hua/2 deblocker 您可以在答案中包含代码。 @Omar 尝试将一个实际的 ajax 表达式放在一起,就像我在更新 #2 中所做的那样。将变量设置为 true 并对其进行测试可以正常工作,但 ajax 称它为似乎导致问题的原因。一旦你引入了一个 ajax 调用,你的代码就不再工作了。【参考方案2】:感谢 Omar 和 deblocker 在这个问题上花费这么多时间。不幸的是,我无法在不干扰其他页面交互的情况下实施您的建议。下面列出了我想出的唯一可行的解决方案。不幸的是,该解决方案不使用处理页面更改事件的内置散列函数。我只是使用一个普通按钮并为其分配点击侦听器。有点笨拙,但它似乎是在我的情况下它可以工作的唯一方法。
<button id="btnNewPage">Go To Page 2</button>
$(document).ready(function()
$("#btnPageNew").click(function()
var testVal = $('#testVal').val();
var canNotPass = promiseTest(testVal);
canNotPass.done(function(data)
var json = $.parseJSON(data);
console.log(json);
if(json.hasOwnProperty('error'))
// user can not access the next page
console.log('can not pass');
$.mobile.activePage.find('.ui-btn-active').removeClass('ui-btn-active').blur();
else
// allow user to access the next page
$(":mobile-pagecontainer").pagecontainer("change", "#page2");
);
);
);
function promiseTest(aValue)
return $.ajax(
type: "POST",
url: "php-file.php",
data: "something":aValue ,
cache: false
);
【讨论】:
以上是关于jQuery移动多页切换页面前等待ajax返回数据的主要内容,如果未能解决你的问题,请参考以下文章