如何中断触发网页滚动的Javascript代码行?
我的网页在切换标签时会滚动,我正在试图找出是什么导致了这个滚动。我可以确认我观察到的行为实际上是一个滚动,而不是由于如何中断触发网页滚动的Javascript代码行?,javascript,jquery,angularjs,debugging,browser,Javascript,Jquery,Angularjs,Debugging,Browser,我的网页在切换标签时会滚动,我正在试图找出是什么导致了这个滚动。我可以确认我观察到的行为实际上是一个滚动,而不是由于窗口中页面高度的变化。页面偏移量在切换选项卡时发生变化 如何找到导致此滚动的代码 我尝试在Chrome中添加滚动事件侦听器断点,但调用堆栈仅列出此调用: elemData.handle(jquery.js:4334)它指向滚动事件处理代码:eventHandle=elemData.handle=function(e){…}未捕获触发此滚动事件的调用 然后我阅读了关于使用Javasc
窗口中页面高度的变化。页面偏移量在切换选项卡时发生变化
如何找到导致此滚动的代码
我尝试在Chrome中添加滚动事件侦听器断点,但调用堆栈仅列出此调用:
elemData.handle(jquery.js:4334)
它指向滚动事件处理代码:eventHandle=elemData.handle=function(e){…}
未捕获触发此滚动事件的调用
然后我阅读了关于使用Javascript的Object.defineProperty()
方法设置属性更改断点的教程:并为window.pageYOffset
编写了一个自定义setter方法,但它不会在页面滚动时触发。以下是我使用的代码:
Object.defineProperty(window,'pageYOffset',{
set:function(val){
window.pageYOffset=val;
debugger;
}
});
我们是否可以使用上述任一方法来识别滚动触发代码?有没有其他方法可以让人们完成这项任务?我评论道:
如果您单击以激活表的对象是锚定,并且您使用href=“#tabname”
标识该选项卡,则可能是浏览器本身导致了滚动:它正试图转到该锚定目标。因此,您将无法在其上设置断点。但如果我是对的,幸运的是,您不必这样做:只需阻止click
事件的默认操作(即跟随链接),即可停止滚动
你的答复是:
关于锚定标记的ID导致浏览器滚动到该元素的说法是正确的。我通过反复试验找到了它,但仍然想了解是否有办法通过断点捕获有问题的代码
恐怕您不能在浏览器的代码中设置断点。唯一能弄明白这一点的方法就是你和我的做法:反复尝试,知道是什么原因造成的,等等
关于defineProperty()方法,我应该如何构造setter方法以避免递归?我遵循我链接的博客模板
在这种情况下(可能还有很多其他情况),您可能当然不能这样做,因为此属性可能只是窗口对象中某些内部信息的访问器。这个特殊属性的行为实际上非常有趣(无论如何,在Chrome上):它是由窗口设置的,除非您将它设置为不同的值。将其设置为不同的值a)不会滚动窗口,B)使属性停止告诉您窗口滚动了多远(即使您再次移动它)
在一般情况下,您只能在以下情况下使用该文章中的技巧:
- 该属性是可配置的
- 属性当前既没有getter也没有setter
…在这种情况下,您可以这样做(但更多的cmoplete版本请参见下文):
注意我们是如何接管存储值的责任的。我们可以将它存储在对象上的另一个属性上(例如,\uuuuuuuuuuuuuuuuuuuuuuidden\uuuuuuuuuuuufoo
),但是闭包中的变量更容易、更安全
以下是更全面的版本:
//用于捕获属性更改的函数
函数callbackOnChange(obj、propName、cb){
var值=对象[propName];
var desc=Object.getOwnPropertyDescriptor(obj,propName);
//如果属性尚不存在,描述符将为null
//在对象上,或者因为它根本不存在*,
//或者因为对象正在继承它。任何一种方式都是
//我们想做的很好
如果(描述!=null){
如果(!desc.configurable){
抛出新错误(“无法重新配置属性“+propName+”);
}
如果(描述集){
抛出新错误(“属性“+propName+”有一个setter”);
}
if(desc.get){
抛出新错误(“属性“+propName+”有一个getter”);
}
如果(!desc.writable){
抛出新错误(“属性“+propName+”不可写,因此永远不会更改”);
}
}
Object.defineProperty(obj,propName{
可枚举:描述可枚举,
get:function(){
返回值;
},
set:函数(newValue){
值=新值;
cb(obj、propName、newValue);
}
});
}
//创建对象和属性
var obj={
傅:“酒吧”
};
//设置值,无通知
obj.foo=“update1”;
//捕获更改
试一试{
callbackOnChange(obj,“foo”,函数(o,propName,newValue){
log(propName+“更改为”+newValue);
//可以使用调试器;在这里
});
}捕获(e){
log(“无法捕获更改:+e.message”);
}
//设置值,我们就会收到通知
obj.foo=“update2”;//收到通知
如果您单击以激活表的对象是锚定,并且您使用href=“#tabname”
来标识该选项卡,则可能是浏览器本身导致了滚动:它正试图转到该锚定目标。因此,您将无法在其上设置断点。但是,如果我是对的,幸运的是,您不必这样做:只需阻止单击事件的默认操作(即跟随链接),这将停止滚动。defineProperty
调用也不起作用。(我并不奇怪它没有这样做;主机提供的对象不按JS规则播放。)如果有,你已经得到了堆栈溢出,因为set
函数中的代码当然是在给属性赋值……该属性递归地调用set
函数,直到堆栈用完为止。谢谢!关于锚定标记的ID导致浏览器滚动到该元素的说法是正确的。我通过反复试验找到了它,但仍然想了解是否有办法通过断点捕获有问题的代码。关于defineProperty()
方法,我应该如何构造t
(function() {
var value = obj.theProperty;
Object.defineProperty(obj, "theProperty", {
enumerable: desc.enumerable,
get: function() {
return value;
},
set: function(newValue) {
value = newValue;
// It changed
}
});
})();