gpt4 book ai didi

JavaScript函数offsetLeft-缓慢返回值(主要是IE9)

转载 作者:数据小太阳 更新时间:2023-10-29 06:12:56 25 4
gpt4 key购买 nike

我在调试新闻动态时遇到了很多困难-我是使用JavaScript从头开始编写的。

除了IE9(以及某些移动浏览器,Opera Mobile)运行缓慢的浏览器外,它在大多数浏览器上都可以正常工作。

使用开发人员工具>探查器使我能够找到问题的根本原因。

这是对offsetLeft的调用,以确定是否旋转代码行进器,即第一个元素成为最后一个元素。

function NeedsRotating() {
var ul = GetList();
if (!ul) {
return false;
}
var li = GetListItem(ul, 1);
if (!li) {
return false;
}
if (li.offsetLeft > ul.offsetLeft) {
return false;
}
return true;
}

function MoveLeft(px) {
var ul = GetList();
if (!ul) {
return false;
}
var li = GetListItem(ul, 0);
if (!li) {
return false;
}
var m = li.style.marginLeft;
var n = 0;
if (m.length != 0) {
n = parseInt(m);
}
n -= px;
li.style.marginLeft = n + "px";
li.style.zoom = "1";
return true;
}

返回值似乎要花费300毫秒以上,而股票行情应该每10毫秒向左移动1个像素。

是否有已知的解决方法?

谢谢

最佳答案

DOM操作

我同意@samccone的观点,即如果GetList()GetListItem()每次都在执行DOM操作,则应尽量保存对那些调用所检索的元素的引用,并减少DOM操作。

then I can just manipulate that variable and hopefully it won't go out of sync with the "real" value by calling offsetLeft.



您只需将对DOM元素的引用存储在变量中。因为它是引用,所以它才是真正的值(value)。这是完全相同的对象。例如。:
var li = ul.getElementsByTagName( "li" )[ index ];

该存储对DOM对象的引用。您可以随时从该对象读取 offsetLeft,而无需执行另一个DOM操作(例如 getElementsByTagName)来检索该对象。

另一方面,以下内容只会存储该值,而不会保持同步:
var offsetLeft = ul.getElementsByTagName( "li" )[ index ].offsetLeft;

offsetLeft

如果 offsetLeft确实是一个瓶颈,是否有可能您可以改写一下以减少阅读量呢?在这种情况下,每次轮换出第一项内容时,您是否可以为新的第一项内容读取一次 offsetLeft,然后仅在每次调用 MoveLeft()时将该值减一,直到达到 0(或其他任何值)?例如。
function MoveLeft( px ) {

current_offset -= px;

如果您想更加积极地避免 offsetLeft,也许可以做一些事情,一次读取每个列表项的宽度,一次读取第一项的 offsetLeft,然后使用这些值确定何时旋转,而无需再次调用 offsetLeft

全局变量

I think I get it... so elms["foo"] would have to be a global variable?

I think really I just need to use global variables instead of calling offsetLeft every 10 ms.



您不需要使用全局变量,实际上您应该避免使用它-这是一个糟糕的设计。在不使用全局变量的情况下,至少可以采用两种良好的方法:
  • 您可以将整个程序包装在一个闭包中:
    ( function () {

    var elements = {};


    function NeedsRotating() {

    ...

    }


    function example() {

    // The follow var declaration will block access
    // to the outer `elements`

    var elements;

    }


    // Rest of your code here

    } )();
    elements的作用域是包含它的匿名函数。它不是全局变量,因此在匿名函数之外不可见。只要您在内部函数中未声明相同名称的变量,匿名函数内的任何代码(包括函数(在本例中为NeedsRotating()))都将可见。
  • 您可以将所有内容封装在一个对象中:
    ( function () {

    var ticker = {};

    ticker.elements = {};


    // Assign a method to a property of `ticker`

    ticker.NeedsRotating = function () {

    // All methods called on `ticker` can access its
    // props (e.g. `elements`) via `this`

    var ul = this.elements.list;

    var li = this.elements.list_item;


    // Example of calling another method on `ticker`

    this.do_something();

    } ;


    // Rest of your code here


    // Something like this maybe

    ticker.start();

    } )();

    在这里,我再次将所有内容包装在一个匿名函数中,因此,即使ticker也不是全局变量。

  • 对评论的回应

    首先,对于 setTimeout,最好这样做:
    t = setTimeout( TickerLoop, i );

    而不是:
    t = setTimeout("TickerLoop();", i);

    在JS中,函数是一流的对象,因此您可以将实际的函数对象作为参数传递给 setTimeout,而不是传递字符串,就像使用 eval一样。

    您可能需要考虑使用 setInterval而不是 setTimeout

    Because surely any code executed in setTimeout would be out of scope of the closure?



    实际上并非如此。在定义函数时形成闭包。因此,通过 setTimeout调用函数不会干扰函数对封闭变量的访问。这是一个简单的演示代码段:
    ( function () {

    var offset = 100;


    var whatever = function () {

    console.log( offset );

    };


    setTimeout( whatever, 10 );

    } )();

    但是, setTimeout将干扰方法中 this的绑定(bind),如果将所有内容封装在一个对象中,这将是一个问题。以下内容将不起作用:
    ( function () {

    var ticker = {};

    ticker.offset = 100;


    ticker.whatever = function () {

    console.log( this.offset );

    };


    setTimeout( ticker.whatever, 10 );

    } )();

    ticker.whatever内部, this不会引用 ticker。但是,您可以在此处使用匿名函数来形成闭包来解决该问题:
    setTimeout( function () { ticker.whatever(); }, 10 );

    Should I store it in a class variable i.e. var ticker.SecondLiOffsetLeft = GetListItem(ul, 1).offsetLeft then I would only have to call offsetLeft again when I rotate the list.

    I think that's the best alternative to a global variable?



    关键的事情是:
  • 每次旋转列表时,请一次访问offsetLeft
  • 如果将列表项存储在变量中,则可以访问它们的offsetLeft属性,而无需重复执行诸如getElementsByTagName()这样的DOM操作来获取列表对象。

  • 如果将所有内容包装在一个对象中,则#2中的变量可以是一个对象属性,也可以是一个可以通过其闭包作用域访问的变量。我可能会将其包装在一个对象中。

    我更新了“DOM操作”部分以阐明,如果存储对DOM对象的引用,它将是完全相同的对象。您不想直接存储 offsetLeft,因为那样只会存储值,并且不会保持同步。

    但是,您决定存储它们(例如,对象属性或变量),则可能应该一次检索所有 li对象并将它们存储在类似数组的结构中。例如。
    this.li = ul.getElementsByTagName( "li" );

    每次旋转时,请以某种方式指明当前项目,例如:
    this.current_item = ###;

    // or

    this.li.current = this.li[ ### ];


    // Then

    this.li[ this.current_item ].offsetLeft

    // or

    this.li.current.offsetLeft

    或者,如果您愿意,可以将 li对象存储在数组中,并针对每次旋转进行此操作:
    this.li.push( this.li.shift() );

    // then

    this.li[0].offsetLeft

    关于JavaScript函数offsetLeft-缓慢返回值(主要是IE9),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9928016/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com