在构造函数中创建DOM元素,陷阱,坏习惯?

时间:2014-12-15 13:05:40

标签: javascript dom

我正在制作媒体播放器。目前,我将所需的一切(DOM参考,参数等)存储在通过media元素上的expando属性附加的对象文字中。不太理想。

无论如何,我一直在阅读不同的设计模式(模块,单身等等...... this之类的东西),试图学习一些东西,找到一些东西,这些东西。经过测试和验证......但我没有想到私下创建和存储DOM元素或在构造函数中添加事件监听器。

也许它只是常识,我不知道它?我真的不知道。我遇到的部分问题是"这个"关键词。例如......

function MakeObject () {
   this.elm = document.createElement('tagName');
   this.otherElm = document.createElement('tagName');
}
MakeObject.protoype.doSomething = function () {
   //"this" refers to instance of MakeObject
   this.elm.something = foo;
   this.otherElm.somethingElse = bar;
};
var instance = new MakeObject();
// With an event listener on instance.elm, "this" no longer refers to instance
// For whatever reason I need to avoid bind.
instance.elm.addEventListener('event', instance.doSomething, false); //blah!

所以,问题......

在构造函数中插入问题 ...是不好的做法,使它们可用于构造函数的任何实例?

  1. 使用关键字" var"存储变量(特别是创建了DOM元素)?
  2. 分配事件监听器?
  3. 我尽力提出一些事情......只是不知道它是否安全"在内存泄漏,循环引用以及DOM缓存附带的所有其他陷阱中。

    我在这个例子中使用了一个媒体播放器,但它很可能是任何东西。


    <video src='awesomevid.ext'></video>
    ...
    var MediaControl = (function () {
        function playToggle (vid, button) {
           if (vid.paused) {
               vid.play();
               button.textContent = 'Pause';
           }
           else {
               vid.pause();
               button.textContent = 'Play';
           }
        }
        function Constructor (vid) {
            var playButton = document.createElement('button');
            this.play = function () {
                playToggle(vid, playButton);
            }
            button.addEventListener('click', this.play, false);
            vid.parentNode.insertBefore(playButton, vid.nextSibling);
        }
        return Constructor;
    }());
    
    var control = new MediaControl( document.querySelector('video') );
    control.play(); // both control and button can play/pause video
    

1 个答案:

答案 0 :(得分:2)

如果你有一个与DOM元素相关的对象,那么肯定会将它作为对象的属性。

例如,任何MVC系统都可能将DOM元素作为其视图的属性。我不会完全称之为&#34;缓存&#34;,因为缓存指的是你可以通过一点点计算得到的东西;它只是&#34;存储&#34;。

如果通过&#34;在构造函数中缓存&#34;你的意思是

function MyConstructor(elt) {
    this.hide = function() { elt.classList.add('hide'); };
}

所以elt是私有的,嗯,这仅仅是私有地持有一个值而不是在实例的属性中持有它之间的区别:

function MyConstructor(elt) {
    this.elt = elt; 
}
MyConstructor.prototype.hide = function() {
    this.elt.classList.add('hide');
};

选择哪种方法主要取决于设计因素,可以认为是最佳实践。

在任何一种情况下,hide方法基本上都是从对象委托给DOM元素。它是一种经典的代表团模式,并没有任何错误,事实上,它很好,干净,易于理解。添加事件侦听器也是如此。如果你有一个包含,包装或连接到DOM元素的对象,通常是一对一的关系,你会在哪里放置这样的功能?

您询问了如何在对象中保存/缓存DOM元素,但也存在首先如何/在何处创建DOM元素的问题。在某些情况下,DOM元素可能已经在HTML或模板中定义,并且对象的用户只需将其传递给构造函数或某些初始化例程。如果DOM元素是对象的内在个性的一部分,那么我们可能希望对象为我们创建它。是否最好在构造函数本身或初始化程序中执行此操作,这是一个意见问题。