【问题标题】:Write a wrapper object in Javascript用 Javascript 编写一个包装器对象
【发布时间】:2011-02-02 19:25:52
【问题描述】:

首先,如果我的问题措辞不正确,请允许我道歉 - 我不是专业的编码员,所以我的术语可能很奇怪。我希望我的代码不会太尴尬:(

我有一个fade() 方法,可以通过鼠标悬停来淡入淡出图像。我想使用一个包装对象(我认为这是正确的术语)来保存图像元素和一些必需的属性,但我不知道如何实现这一点。 fade() 是从 HTML 中调用的,旨在无需太多额外设置即可放入页面(以便我可以轻松地将新的褪色图像添加到任何 HTML),就像这样:

<div id="obj" onmouseover="fade('obj', 1);" onmouseout="fade('obj', 0);">

fade(obj, flag) 方法启动一个淡入图像的 SetInterval,当指针移开时,间隔被清除并创建一个新的 SetInterval 以淡出图像。为了保存不透明度状态,我为对象添加了一些属性:obj.opacityobj.upTimerobj.dnTimer

一切正常,但我不喜欢向 HTML 元素添加属性的想法,因为这可能会导致将来某些其他方法会覆盖这些属性。理想情况下,我认为应该涉及一个包装器对象,但我不知道如何在不添加代码以在页面加载时创建对象的情况下干净地完成此操作。如果有人有任何建议,我将不胜感激!

这是我的推子方法:

var DELTA = 0.05;

function fade(id, flag) {

  var element = document.getElementById(id);
  var setCmd = "newOpacity('" + id + "', " + flag + ")";

  if (!element.upTimer) {
    element.upTimer = "";
    element.dnTimer = "";
  }
  if (flag) {
    clearInterval(element.dnTimer);
    element.upTimer = window.setInterval(setCmd, 10);
  } else {
    clearInterval(element.upTimer);
    element.dnTimer = window.setInterval(setCmd, 10);
  }
}

function newOpacity(id, flag) {

  var element = document.getElementById(id);

  if (!element.opacity) {
    element.opacity = 0;
    element.modifier = DELTA;
  }

  if (flag) {
    clearInterval(element.dnTimer)
    element.opacity += element.modifier;
    element.modifier += DELTA;  // element.modifier increases to speed up fade
    if (element.opacity > 100) {
      element.opacity = 100;
      element.modifier = DELTA;
      return;
    }
    element.opacity = Math.ceil(element.opacity);
  } else {
    clearInterval(element.upTimer)
    element.opacity -= element.modifier;
    element.modifier += DELTA;  // element.modifier increases to speed up fade
    if (element.opacity < 0) {
      element.opacity = 0;
      element.modifier = DELTA;
      return;
    }
    element.opacity =
      Math.floor(element.opacity);
  }
  setStyle(id);
}

function setStyle(id) {

  var opacity = document.getElementById(id).opacity;

  with (document.getElementById(id)) {
    style.opacity = (opacity / 100);
    style.MozOpacity = (opacity / 100);
    style.KhtmlOpacity = (opacity / 100);
    style.filter = "alpha(opacity=" + opacity + ")";
  }
}

【问题讨论】:

    标签: javascript methods correctness


    【解决方案1】:

    您是对的,在您的 HTML 中添加处理程序并不好。您也失去了将多个事件处理程序附加到一个对象的可能性。

    不幸的是,微软在附加事件处理程序方面采取了自己的方式。但是你应该能够编写一个小的包装函数来处理这个问题。

    具体内容,建议阅读quirksmode.org - Advanced event registration models

    W3C 兼容浏览器的示例(IE 不兼容):不要在 HTML 中添加事件处理程序,而是获取对元素的引用并调用 addEventListener

    var obj = document.getElementById('obj');
    
    obj.addEventListener('mouseover', function(event) {
        fade(event.currentTarget, 1);
    }, false);
    
    obj.addEventListener('mouseout', function(event) {
        fade(event.currentTarget, 0);
    }, false);
    

    如您所见,我直接传递了对该对象的引用,因此在您的 fade 方法中,您已经拥有对该对象的引用。

    您可以将其包装在一个接受 ID(或引用)的函数中,并且每次您想将事件处理程序附加到某个元素时,您只需将 ID(或引用)传递给此函数。

    如果你想让你的代码可重用,我建议把所有东西都放到一个对象中,像这样:

    var Fader = (function() {
       var DELTA = 0.05;
       function newOpacity() {}
    
       function setStyle() {}
    
       return {
           fade: function(...) {...},
    
           init: function(element) {
               var that = this;
               element.addEventListener('mouseover', function(event) {
                   that.fade(event.currentTarget, 1);
               }, false);
    
               element.addEventListener('mouseout', function(event) {
                   that.fade(event.currentTarget, 0);
               }, false);
           }
       };
    }())
    

    使用对象来保存函数可以减少对全局命名空间的污染。

    那么你可以这样称呼它:

    Fader.init(document.getElementById('obj'));
    

    上面代码的解释:

    我们有一个即时函数(function(){...}()),这意味着该函数被一次性定义和执行(())。此函数返回一个对象(return {...};{..} 是对象文字符号),它具有属性initfade。这两个属性都包含可以访问立即函数中定义的所有变量的函数(它们是闭包)。这意味着他们可以访问外部无法访问的newOpacitysetStyle。返回的对象赋值给Fader变量。

    【讨论】:

    • 感谢 Felix,我宁愿避免使用 JQuery,直到我可以学习 Javascript 的技巧,这将有很大帮助。虽然,我现在完全被 Javascript 变量的范围迷惑了。我不明白为什么在返回块之外可以看到init()fade():/
    • @SpaceJunk:请看我的更新。我希望这有帮助。可以看到函数,因为return {...}实际上不是块,它是定义对象的对象字面量表示法。这将是相同的:var obj = {init: function() {...}}; return obj;。请注意,我还稍微更改了代码并将DELTA 移到了立即函数中。这应该更适合您的代码。如果您还有其他问题,请尽管提问。
    【解决方案2】:

    这并不能直接回答您的问题,但您可以使用 jQuery 库。很简单,你只需要在顶部添加一个脚本标签:

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js">
    

    然后你的 div 看起来像:

    <div id="obj" onmouseover="$('#obj').fadeIn()" onmouseout="$('#obj').fadeOut()">
    

    jQuery 将为您处理所有浏览器依赖项,因此您不必担心诸如 firefox 和 mozilla 之间的差异之类的事情......

    【讨论】:

      【解决方案3】:

      如果你想保持你的 HTML 干净,你应该考虑使用 JQuery 来设置事件。

      您的 HTML 将如下所示:-

      <div id="obj">
      

      你的 JavaScript 看起来像这样:-

      $(document).ready(function() {
          $("#obj").mouseover(function() {
              Page.fade(this, 1);
            }).mouseout(function(){
              Page.fade(this, 0);
            });
      });
      
      var Page = new function () {
          // private-scoped variable
          var DELTA = 0.05;
      
          // public-scoped function
          this.fade = function(divObj, flag) {
             ...
          };
      
          // private-scoped function
          var newOpacity = function (divObj, flag) {
             ...
          };
      
          // private-scoped function
          var setStyle = function (divObj) {
              ...
          };
      };
      

      我在您的 Javascript 中引入了一些范围概念,以确保您不会遇到函数覆盖问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-08
        相关资源
        最近更新 更多