我试图弄清楚为什么我的功能在更改html代码后停止工作。
我有一个div:
<div class="float">
<div class="box" data-speed="3" data-direction="X"><h1>Hola</h1></div>
<div class="box" data-speed="2" data-direction="X"><h1>chau</h1></div>
</div>
和jquery代码:
$(function() {
$('.box').moveIt();
});
//move elements in different speeds
$.fn.moveIt = function () {
var win = $(window);
var it = $(this);
var instances = [];
$(this).each(function (){
instances.push(new moveItItem($(this)));
});
$('.parallax').on('scroll', function() {
instances.forEach(function(inst){
var wrap = inst.el.parents('.float');
var scrol = win.scrollTop()-wrap.offset().top;
inst.update(scrol);
});
});
}
var moveItItem = function(el){
this.el = $(el);
this.speed = parseInt(this.el.attr('data-scroll-speed'));
this.direction = this.el.attr('data-direction');
};
moveItItem.prototype.update = function(scrollTop){
var pos = scrollTop / this.speed;
this.el.css('transform', 'translate'+this.direction+'(' + -pos + 'px)');
};
好的,直到这里一切正常,当我滚动元素.box
相应地翻译。
但是现在我想在ajax调用之后修改类.float
中的html
//after ajax
$.ajax({
url: 'do_content.php'
}).done(function(result) {
//result = <div class="box" data-speed="3" data-direction="X"><h1>Como estas?</h1></div>
$('.float').html(result);
});
当我再次触发滚动后,该功能看起来看起来很破碎,我收到了这条消息:
Uncaught TypeError: Cannot read property 'top' of undefined
at http://localhost/ophelia/public/js/control.js?v=1487219951:197:45
at Array.forEach (native)
at HTMLDivElement.<anonymous> (http://localhost/ophelia/public/js/control.js?v=1487219951:195:13)
at HTMLDivElement.dispatch (http://localhost/ophelia/public/utilities/jquery/jquery-3.1.1.min.js:3:10315)
at HTMLDivElement.q.handle (http://localhost/ophelia/public/utilities/jquery/jquery-3.1.1.min.js:3:8342)
我知道只有当我用类.box
更改元素时才显示此消息(我试图仅更改h1
并且它没有破坏但我想改变所有内容以改变速度)
如何重新启动此功能?
我尝试使用$('.box').moveIt();
再次调用它,但仍然收到相同的错误
我知道这是一个很长的问题,但没有找到解释我问题的另一种方法
答案 0 :(得分:2)
这是因为绑定到侦听器的html元素已被替换。 就像在这里fiddle一样..警报有效,但是在更改html之后,它没有。这是因为旧元素已被新元素替换。
您可以使用jQuery中的on
函数来解决此问题,例如fiddle
答案 1 :(得分:1)
您可以绑定div.float
上的活动并通过element.children
移动每.box
答案 2 :(得分:1)
正如已经指出的那样(但可能不那么清楚),问题是您在特定时刻使用页面中存在的元素附加事件处理程序(我想到instances
var)。然后你替换它们,但你的处理程序已经设置为使用类.parallax滚动元素并已使用instances
的实例注册,依此类推。
一种方法是使用委托方法重写代码。
事件处理程序仅绑定到当前选定的元素;他们 在您的代码调用.on()时必须存在。
委派事件的优势在于它们可以处理来自的事件 稍后添加到文档中的后代元素
事件委派方法仅将事件处理程序附加到一个 元素,tbody和事件只需要升级一个级别 (从点击的tr到tbody):
$( "#dataTable tbody" ).on( "click", "tr", function() {
console.log( $( this ).text() );
});
但它可能很复杂,因为你应该深入重构你的代码。
否则你可以按照以下方式重写你的功能(对不起,我不能制作小提琴)
$(function() {
$('.parallax').moveIt();
});
//move elements in different speeds
$.fn.moveIt = function () {
var win = $(window);
var it = $(this);
//REMOVED
//var instances = [];
// $(this).each(function (){
// instances.push(new moveItItem($(this)));
// });
$(this).on('scroll', function() {
$('.box').each(function(){
var inst=new moveItItem($(this));
var wrap = inst.el.parents('.float');
var scrol = win.scrollTop()-wrap.offset().top;
inst.update(scrol);
});
});
}
...... and so on