JavaScript 页面收到 AJAX 响应后不再执行
JavaScript no longer executes after page receives AJAX response
我正在执行 AJAX 请求,PHP 脚本接收并发回响应。在发出请求之前,我的 JavaScript 代码可以正常工作,但是从服务器收到响应后,所有 JavaScript 代码都变得毫无用处。下面的代码只是为了说明会发生什么,它做得非常完美:
HTML:
<script src="http://code.jquery.com/jquery-1.9.1.min.js" type="text/javascript"></script>
<form method='post' action=''>
<textarea cols='30' rows='5' name='test'></textarea>
<input type='submit' value='ok' />
</form>
<div id='ajax-response'></div>
JavaScript:
$('textarea').click(function() {
alert('ouch!');
});
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function() {
if (xhr.readyState == 4){
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
document.getElementById('ajax-response').innerHTML = xhr.responseText;
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
}
$('form').submit(function(event) {
if(typeof(FormData) != 'undefined') {
var oform = this;
event.preventDefault();
xhr.open('post', '', false);
xhr.send(new FormData(oform));
}
});
处理AJAX请求的PHP脚本:
if (isset($_POST['test'])) {
echo "<form method='post' action=''>
<textarea cols='30' rows='5' name='test2'></textarea>
<input type='submit' value='ok' />
</form>";
}
已收到响应,新表单已添加到页面。但是在提交表单之前,当您单击文本区域时,会抛出警报。当来自服务器的请求 returns 时,这不再有效(警报只是一个例子;实际上没有 JavaScript 代码被执行)。我整天都在做这个,一个解决方案会让我开心!
编辑
Doug 下面的回答解决了我的问题,但我认为值得一提的是,由于 gengkev 在这个问题下方的评论,我还发现使用 innerHTML
不仅会删除使用它的元素的内容,还会删除其他内容在用新内容替换这些元素之前,从子元素构建数据和事件处理程序等。因此,当我将具有 innerHTML
属性的行替换为:
时,我放在上面的代码也能正常工作
$('#ajax-response')append(xhr.responseText);
感谢大家的帮助!
我明白你的意思了,你需要在完成所有这些事情后绑定元素。一种方法是使用 Jquery 并使用 $.live 函数。您可以将 javascript 中的元素绑定为 under
function live(eventType, elementId, cb) {
document.addEventListener(eventType, function (event) {
if (event.target.id === elementId) {
cb.call(event.target, event);
}
});
}
live("click", "test", function (event) {
alert(this.id);
});
如果我正确理解你的问题:
当您将 html 替换为 AJAX 时,新的 html 需要您重新添加事件 hoocks。因此,当您收到 AJAX 响应时,只需重新运行
$("form").submit(...)
挂钩。
好的,我已经创建了以下 JSFiddle:
http://jsfiddle.net/zLAht/24/
这就是你想要的,对吗?
您的代码最初的方式 Ajax 请求没有替换提交区域,但根据您的问题听起来像是问题。
HTML
<body>
<div id='ajax-response'>
<form method='post' action=''>
<textarea cols='30' rows='5' name='test'></textarea>
<input id='sub' type='button' value='ok' />
</form>
</div>
</body>
JavaScript:
$('textarea').click(function() {alert('ouch!');});
$('#sub').click(function(event) {
$.ajax({
cache:false,
type: 'POST',
url: '/echo/html/',
data: {
html:"<form method='post' action=''><textarea cols='30' rows='5' name='test2'></textarea><input type='submit' value='ok' /></form>"
},
success: function(data) {
$('#ajax-response').html(data);
$('textarea').click(function() {alert('ouch!');});
},
error:function(error){
alert('there was an error');
},
dataType: 'html'
});
});
这里的问题是事件委托。当页面加载时,它将当时的所有事件绑定到 DOM 中执行和可用的所有元素。由于这种行为,可以说替换页面上的元素将删除以前绑定的事件。最好以这样一种方式处理元素,即它们的事件绑定到不会被替换的静态父元素,并且事件可以冒泡到。
就是说,您已经包含了 jQuery 库,所以所有代码都将集中于此,这样我们就可以保持凝聚力:
jQuery(function($){ //setup the ready handler and alias the $ symbol as to not interfere
//for the purpose of this example, our 'body' will be the static element.
var $static = $('body');
$static.on('click', 'textarea', function(){
//the event is delegated, all textareas will receive this, present and future.
});
//again, we delegate the event to all forms present and future
$static.on('submit', 'form', function(event) {
event.preventDefault();
if(typeof(FormData) != 'undefined') {
var oform = this;
//a well supported method of file uploads using jQuery's Ajax and HTML5's FormData object.
$.ajax({
type: $(oform).prop('method'),
url: $(oform).prop('action'),
contentType: false,
processData: false,
cache: false,
data: new FormData(oform),
}).on('success', function(resp){
//do whatever on ajax success
}).on('error', function(s,c,e){
console.warn(s, c, e);
});
}
});
});
我正在执行 AJAX 请求,PHP 脚本接收并发回响应。在发出请求之前,我的 JavaScript 代码可以正常工作,但是从服务器收到响应后,所有 JavaScript 代码都变得毫无用处。下面的代码只是为了说明会发生什么,它做得非常完美:
HTML:
<script src="http://code.jquery.com/jquery-1.9.1.min.js" type="text/javascript"></script>
<form method='post' action=''>
<textarea cols='30' rows='5' name='test'></textarea>
<input type='submit' value='ok' />
</form>
<div id='ajax-response'></div>
JavaScript:
$('textarea').click(function() {
alert('ouch!');
});
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function() {
if (xhr.readyState == 4){
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
document.getElementById('ajax-response').innerHTML = xhr.responseText;
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
}
$('form').submit(function(event) {
if(typeof(FormData) != 'undefined') {
var oform = this;
event.preventDefault();
xhr.open('post', '', false);
xhr.send(new FormData(oform));
}
});
处理AJAX请求的PHP脚本:
if (isset($_POST['test'])) {
echo "<form method='post' action=''>
<textarea cols='30' rows='5' name='test2'></textarea>
<input type='submit' value='ok' />
</form>";
}
已收到响应,新表单已添加到页面。但是在提交表单之前,当您单击文本区域时,会抛出警报。当来自服务器的请求 returns 时,这不再有效(警报只是一个例子;实际上没有 JavaScript 代码被执行)。我整天都在做这个,一个解决方案会让我开心!
编辑
Doug 下面的回答解决了我的问题,但我认为值得一提的是,由于 gengkev 在这个问题下方的评论,我还发现使用 innerHTML
不仅会删除使用它的元素的内容,还会删除其他内容在用新内容替换这些元素之前,从子元素构建数据和事件处理程序等。因此,当我将具有 innerHTML
属性的行替换为:
$('#ajax-response')append(xhr.responseText);
感谢大家的帮助!
我明白你的意思了,你需要在完成所有这些事情后绑定元素。一种方法是使用 Jquery 并使用 $.live 函数。您可以将 javascript 中的元素绑定为 under
function live(eventType, elementId, cb) {
document.addEventListener(eventType, function (event) {
if (event.target.id === elementId) {
cb.call(event.target, event);
}
});
}
live("click", "test", function (event) {
alert(this.id);
});
如果我正确理解你的问题:
当您将 html 替换为 AJAX 时,新的 html 需要您重新添加事件 hoocks。因此,当您收到 AJAX 响应时,只需重新运行
$("form").submit(...)
挂钩。
好的,我已经创建了以下 JSFiddle: http://jsfiddle.net/zLAht/24/
这就是你想要的,对吗?
您的代码最初的方式 Ajax 请求没有替换提交区域,但根据您的问题听起来像是问题。
HTML
<body>
<div id='ajax-response'>
<form method='post' action=''>
<textarea cols='30' rows='5' name='test'></textarea>
<input id='sub' type='button' value='ok' />
</form>
</div>
</body>
JavaScript:
$('textarea').click(function() {alert('ouch!');});
$('#sub').click(function(event) {
$.ajax({
cache:false,
type: 'POST',
url: '/echo/html/',
data: {
html:"<form method='post' action=''><textarea cols='30' rows='5' name='test2'></textarea><input type='submit' value='ok' /></form>"
},
success: function(data) {
$('#ajax-response').html(data);
$('textarea').click(function() {alert('ouch!');});
},
error:function(error){
alert('there was an error');
},
dataType: 'html'
});
});
这里的问题是事件委托。当页面加载时,它将当时的所有事件绑定到 DOM 中执行和可用的所有元素。由于这种行为,可以说替换页面上的元素将删除以前绑定的事件。最好以这样一种方式处理元素,即它们的事件绑定到不会被替换的静态父元素,并且事件可以冒泡到。
就是说,您已经包含了 jQuery 库,所以所有代码都将集中于此,这样我们就可以保持凝聚力:
jQuery(function($){ //setup the ready handler and alias the $ symbol as to not interfere
//for the purpose of this example, our 'body' will be the static element.
var $static = $('body');
$static.on('click', 'textarea', function(){
//the event is delegated, all textareas will receive this, present and future.
});
//again, we delegate the event to all forms present and future
$static.on('submit', 'form', function(event) {
event.preventDefault();
if(typeof(FormData) != 'undefined') {
var oform = this;
//a well supported method of file uploads using jQuery's Ajax and HTML5's FormData object.
$.ajax({
type: $(oform).prop('method'),
url: $(oform).prop('action'),
contentType: false,
processData: false,
cache: false,
data: new FormData(oform),
}).on('success', function(resp){
//do whatever on ajax success
}).on('error', function(s,c,e){
console.warn(s, c, e);
});
}
});
});