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>";
}

收到响应,并将新表单添加到页面。但在提交表单之前,当您单击文本区域时,会引发警报。当请求从服务器返回时,这不再起作用(警报只是一个示例;实际上没有执行JavaScript代码)。我整天都在做这件事,一个解决方案会让我开心!

编辑Doug 下面的回答解决了我的问题,但我认为值得一提的是,由于 gengkev 在这个问题下面的评论,我还发现,在用新内容替换这些元素之前,使用 innerHTML 不仅会删除使用它的元素的内容,还会删除其他构造,例如子元素中的数据和事件处理程序。因此,当我将具有 innerHTML 属性的行替换为时,我上面放置的代码也可以很好地工作:

$('#ajax-response')append(xhr.responseText);

谢谢你们的帮助,伙计们!

好的,

我已经创建了以下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'
     });
});
如果我

正确理解了你的问题:

当您将 html 替换为 AJAX 时,新的 html 要求您将事件 hoock 重新添加到其中。因此,当您收到 AJAX 响应时,只需重新运行您的

$("form").submit(...) 

钩。

我明白你的意思,一旦你完成了所有这些事情,你需要绑定元素。一种方法是使用 Jquery 和 Use $.live 函数。您可以在javascript中绑定元素,如下所示

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);
});

这里的问题是事件委派。当页面加载时,它会将当时的所有事件绑定到 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);
            });
        }
    });
});