3

我编写了这个简单的类来创建一个带有消息的 div 元素,该消息应该在给定时间后消失。这很好用,但是当使用它创建多条消息时,隐藏和销毁功能将仅适用于最后创建的消息。

这是我的课:

function message(text, duration){
    var self = this;

    function init(){
        this.obj = document.createElement("div");
        this.obj.setAttribute("class", "message");
        this.obj.appendChild(document.createTextNode(text));
        document.body.appendChild(this.obj);
        setTimeout(function(){self.display.call(this);}, 20);
        setTimeout(function(){self.hide.call(this);}, duration);
        setTimeout(function(){self.destroy.call(this);}, duration+1000);
    }

    this.display = function(){
        this.obj.setAttribute("class", "message display");
    }

    this.hide = function(){
        this.obj.setAttribute("class", "message gone");
    }

    this.destroy = function(){
        document.body.removeChild(this.obj);
    }

    init();
}

这有效:

new message("This will be removed in 5 seconds.", 5000);

这不起作用:

new message("This will not be shown", 2000);
new message("This will be removed after 2 seconds", 5000);

可能有一些参考错误,但我无法发现任何错误。

4

3 回答 3

2

你非常接近一个可行的解决方案。我在这里修复了代码:http: //jsfiddle.net/GTpKV/

您(正确地)self引用了这个,但是在您的代码中您仍然使用this(this在使用内部函数时会丢失,并且您还直接调用 init ,这意味着在这种情况下this将引用window。如果您使用this.init()它会正确创建引用在对象上,但超时会搞砸事情)。最安全的方法(我已经采取)是简单地将所有出现的 替换thisself。另一个想法是分析上下文何时正确,何时不正确。但是由于您已经在 中具有正确绑定的上下文self,因此您不妨使用它。这是在 JSFiddle 链接中找到的更正代码:

function message(text, duration){
    var self = this;

    function init(){
        self.obj = document.createElement("div");
        self.obj.setAttribute("class", "message");
        self.obj.appendChild(document.createTextNode(text));
        document.body.appendChild(self.obj);
        setTimeout(function(){self.display();}, 20);
        setTimeout(function(){self.hide();}, duration);
        setTimeout(function(){self.destroy();}, duration+1000);
    }

    this.display = function(){
        self.obj.setAttribute("class", "message display");
    }

    this.hide = function(){
        self.obj.setAttribute("class", "message gone");
    }

    this.destroy = function(){
        document.body.removeChild(self.obj);
    }

    init();
}

new message("This will not be shown", 2000);
new message("This will be removed in 5 seconds.", 5000);
于 2013-07-11T22:39:19.840 回答
1

我相信这些this变成window

setTimeout(function(){self.display.call(this);}, 20);
setTimeout(function(){self.hide.call(this);}, duration);
setTimeout(function(){self.destroy.call(this);}, duration+1000);

所以尝试:

setTimeout(function(){self.display()}, 20);
setTimeout(function(){self.hide()}, duration);
setTimeout(function(){self.destroy()}, duration+1000);

另外,为什么不使用self其余代码:

function init(){
    self.obj = document.createElement("div");
    self.obj.setAttribute("class", "message");
    self.obj.appendChild(document.createTextNode(text));
    document.body.appendChild(self.obj);
    setTimeout(function(){self.display()}, 20);
    setTimeout(function(){self.hide()}, duration);
    setTimeout(function(){self.destroy()}, duration+1000);
}

this.display = function(){
    self.obj.setAttribute("class", "message display");
}

this.hide = function(){
    self.obj.setAttribute("class", "message gone");
}

this.destroy = function(){
    document.body.removeChild(self.obj);
}

(我想我都得到了……如果我错过了一个地方,请告诉我)

于 2013-07-11T22:34:49.107 回答
0

也许您可以尝试将此作为解决方案。去掉你的init功能,改this里面setTimeoutself,去掉不必要的call

Javascript

function message(text, duration) {
    var self = this;

    this.display = function () {
        this.obj.setAttribute("class", "message display");
    }

    this.hide = function () {
        this.obj.setAttribute("class", "message gone");
    }

    this.destroy = function () {
        document.body.removeChild(this.obj);
    }

    this.obj = document.createElement("div");
    this.obj.setAttribute("class", "message");
    this.obj.appendChild(document.createTextNode(text));
    document.body.appendChild(this.obj);
    setTimeout(function () {
        self.display(self);
    }, 20);
    setTimeout(function () {
        self.hide(self);
    }, duration);
    setTimeout(function () {
        self.destroy(self);
    }, duration + 1000);
}

new message("This will not be shown", 2000);
new message("This will be removed after 2 seconds", 5000);

jsfiddle 上

于 2013-07-11T22:48:22.227 回答