Javascript对AJAX调用的不同变量作用域

Javascript different variable scope on AJAX call

本文关键字:变量 作用域 AJAX 调用 Javascript      更新时间:2023-09-26

我在编写的一个简单滑块脚本中的变量作用域有问题(由于带宽低,我不想使用现成的解决方案)。滑块脚本在静态加载的页面(http)和通过AJAX加载的内容上都被调用。在静态加载的页面上(因此没有AJAX),脚本似乎工作得很完美。然而,当通过AJAX调用时,调用的方法找不到DOM的元素,这会停止滑块所需的必要动画。

所有事件都是通过甚至委托(使用jQuery的on()函数)来处理的,但这并没有提供解决方案。我确信这与脚本的结构和变量范围有关,但无法确定如何更改结构。因此,我正在寻找一种在这两种情况下都能工作的解决方案(称为普通或通过AJAX)。

我试图在每个函数中声明所需的变量,但由于函数范围的原因,这导致了一些错误,比如我为动画设置的间隔的乘积。希望有人能在正确的方向上帮助我。

// Slider function
(function (window, undefined) {
    var console = window.console || undefined, // Prevent a JSLint complaint 
        doc = window.document,
        Slider = window.Slider = window.Slider || {},
        $doc = $(doc),
        sliderContainer = doc.getElementById('slider_container'),
        $sliderContainer = $(sliderContainer),
        $sliderContainerWidth = $sliderContainer.width(),
        slider = doc.getElementById('slider'),
        $slider = $(slider),
        $sliderChildren = $slider.children(),
        $slideCount = $sliderChildren.size(),
        $sliderWidth = $sliderContainerWidth * $slideCount;
    $sliderControl = $(doc.getElementById('slider_control')),
    $prevButton = $(doc.getElementById('prev')),
    $nextButton = $(doc.getElementById('next')),
    speed = 2000,
    interval,
    intervalSpeed = 5000,
    throttle = true,
    throttleSpeed = 2000;
    if (sliderContainer == null) return; // If slider is not found on page return           
    // Set widths according to the container and amount of children 
    Slider.setSliderWidth = function () {
        $slider.width($sliderWidth);
        $sliderChildren.width($sliderContainerWidth);
    };
    // Does the animation
    Slider.move = function (dir) {
        // Makes use of variables such as $sliderContainer, $sliderContainer width, etc.
    };
    // On ajax call
    $doc.on('ajaxComplete', document, function () {
        Slider.setSliderWidth();
    });
    // On doc ready
    $(document).ready(function () {
        Slider.setSliderWidth();
        interval = window.setInterval('Slider.move("right")', intervalSpeed);
    });
    // Handler for previous button
    $doc.on('click', '#prev', function (e) {
        e.preventDefault();
        Slider.move('left');
    });
    // Handler for next button
    $doc.on('click', '#next', function (e) {
        e.preventDefault();
        Slider.move('right');
    });
    // Handler for clearing the interval on hover and showing next and pervious button  
    $doc.on('hover', '#slider_container', function (e) {
        if (e.type === 'mouseenter') {
            window.clearInterval(interval);
            $sliderControl.children().fadeIn(400);
        }
    });
    // Handler for resuming the interval and fading out the controls
    $doc.on('hover', '#slider_control', function (e) {
        if (e.type !== 'mouseenter') {
            interval = window.setInterval('Slider.move("right")', intervalSpeed);
            $sliderControl.children().fadeOut(400);
        }
    });
})(window);

HTML示例结构:

<div id="slider_control">
   <a id="next" href="#next"></a>
   <a id="prev" href="#prev"></a>
</div>
<div id="slider_container">
   <ul id="slider">
      <li style="background-color:#f00;">1</li>
      <li style="background-color:#282">2</li>
      <li style="background-color:#ff0">3</li>
   </ul>
</div>

我注意到你有

Slider.setSliderWidth = function() {
    $slider.width($sliderWidth);
    $sliderChildren.width($sliderContainerWidth);
};

它在ajax上被调用完成。

您是否使用ajax更新DOM,从而提供一个可以通过doc.getElementById('slider')访问的新DOM元素?那么您的var slider和jquery var $slider很可能指向已经不存在的东西(即使有一个以slider为id的dom元素)。为了纠正这种情况,无论何时调用替换该元素的ajax,都要使用相同的初始化来重新初始化slider$slider,以指向新的jquery封装的元素。

slider = doc.getElementById('slider');
$slider = $(slider);

编辑:

我不确定您将如何处理可变范围问题,但请看一下这个例子。

<pre>
<script> 
(function(){
   var a  = "something";
   function x (){
      a += "else";
   }
   function y() {
      a = "donut";
   }
   function print (){
      document.write(a +"'n");
   }
   print ();
   x();
   print ();
   y();
   print ();
   x();
   print ();
})();
document.write(typeof(a) + "'n");
</script>
</pre>

输出到pre标签

something
somethingelse
donut
donutelse
undefined

这与你已经在做的没有什么不同。只要a不是方法的参数,并且没有在嵌套作用域中用var声明,那么在function(window,undefined){ ...}方法中定义的代码中对a的所有引用都将引用该a,因为a是由var本地定义的。有道理吗?

首先,您可以使用jQuery方法替换所有getElementById。即用$('#next') 替换$(doc.getElementById('next'))

我认为,当您使用on时,它不会像您所假设的那样在元素中搜索选择器。所以你必须使用:

$doc.on('click', '#slider_control #prev',function(e){
    e.preventDefault();
    Slider.move('left');
});

等等,什么通过Ajax加载?滑块html代码?在这种情况下,Slider已经"创建",并且您的许多变量将不指向任何位置(因为这些DOM元素在初始化变量时并不存在)。他们也永远不会这么做。