js setInterval 在类的函数里调用类的方法

一.setInterval 与 setTimeout区别:

`setInterval('func1()',1000)`

在1秒后执行该函数;

idTime = setInterval('func2()',1000)
clearInterval(idTime);

每秒都执行一次,直到调用clearInterval后为结束。
两个函数都为全局函数,在该函数内部如果调用this指针,该指针指向的是window对象!

二.如何用setInterval来调用类的方法呢?
为什么会存在这种情况?
在调用setInterval(func(),1000)的时,大多是在某个函数体类。在该函数里面,会有上下文关联,比如:变量,或者func() 方法本身就需要调用类的某些属性。
有点绕,是时候上例子了

function SimpleDialog(props) {
  AbstractDialog.call(this, props);
}

inheritPrototype(SimpleDialog, AbstractDialog);

SimpleDialog.prototype.timeShow = function () {
  this.onload();
  var dialog = document.getElementById('divDialog');
  dialog.style.opacity = 1;

  var changeOpacity = function () {
    console.log('last');
    var opacity = dialog.style.opacity;
    dialog.style.opacity = opacity - 0.1;

    if (Number(dialog.style.opacity) === Number(0)) {
      this.closeDialog();
      clearInterval(idTime);
    }
  };

  var THIS = this;
  // 这里加的this是windows,将changeOpacity this指向simpleDialog来调用他的
  var idTime = setInterval(function () { changeOpacity.call(THIS); }, 100);
  console.log(idTime);
  dialog.onmouseenter = function (event) {
    document.getElementById('divDialog').style.opacity = 1;
    event.stopPropagation();
    clearInterval(idTime);
    console.log('onmouseenter');
  };

  dialog.onmouseleave = function (e) {
    clearInterval(idTime);
    idTime = setInterval(function () { changeOpacity.call(THIS); }, 100);
    // this.idTime如果声明为内部对象会存在问题
  };
};

以上为部分关键代码示例:
SimpleDialog类继承于AbstractorDialog,其中timeShow()方法为自定义方法,目的是实现弹出对话框的渐进消失效果。
主要实现了如下功能

  • 对话框弹出后,渐进透明,直到关闭
  • 当鼠标移动到对话框上时 触发onmouseenter事件,重置对话框透明属性为1,并停止渐进效果
  • 当鼠标移除对话框后,触发onmouseout事件,对话继续渐进透明,直到关闭。

(有关对话框的设计,改天再开个口)
很容易想到第一步,如何设置变化?
查到有setInterval(func1(),1000) 可以设置为每秒执行,1000以毫秒为单位。
第二步,如何监听变化,执行到某一步的时候结束程序?
自然想到这部监听要在func1()里面来做。

针对这里的需求来第一版本:

function changeOpacity() {
    console.log('last');
    var opacity = document.getElementById('divDialog').style.opacity;
    document.getElementById('divDialog').style.opacity = opacity - 0.1;
    if (Number(document.getElementById('divDialog').style.opacity) === Number(0)) {
        closeDialog();
        clearInterval(idTime);
    }
};

var idTime;
function closeDialog() {
    var props = {
        'title': '日期格式有误,请重新填写'
    };
    var diglog = new AbstractDialog(props);
    diglog.closeDialog();
}

SimpleDialog.prototype.timeShow = function() {
    this.onload();
    var dialog = document.getElementById('divDialog');
    dialog.style.opacity = 1;

    // 这里加的this是windows,将changeOpacity this指向simpleDialog来调用他的
    idTime = setInterval('changeOpacity()', 100);
    console.log(idTime);
    dialog.onmouseenter = function(event) {
        document.getElementById('divDialog').style.opacity = 1;
        event.stopPropagation();
        clearInterval(idTime);
        console.log('onmouseenter');
    };

    dialog.onmouseleave = function(e) {
        clearInterval(idTime);
        idTime = setInterval('changeOpacity()', 100);
        // this.idTime如果声明为内部对象会存在问题
    };
};

这个代码不痛快的地方在哪里呢?
首先在SimpleDialog.prototype.timeShow 为Dialog的初始化方法,在里面调用了基类的onload初始化函数,并在设定了onmousenter与onmouseleave两个事件。事件中添加setInterval 方法!
第二定义两个全局函数 一个为closeDialog() 调用基类的closeDialog()来移动对话框
第三,定义setInterval的回调函数 changeOpacity
第四,为了使changOpacity 在 opactiy==0时, 调用clearInterval,需将句柄idTime设置为全局变量

第二点与第四点简直不能忍~这里回答了为什么需在类内调用windows的全局方法。

首先查到setInterval()在类中调用的如下方法:

            function Person(name){
                this.name=name;
                var f=function(){alert('My name is '+this.name)};



                // setTimeout(f,50); //错误

                var THIS=this;
                setTimeout(function(){f.apply(THIS)},50); //正确,通用
                setTimeout(function(){f.call(THIS)},50); //正确,通用
            }
            new Person('Jack');

这里的回调函数f实质上是一个闭包,但能满足作为setInterval回调函数的需求!其次闭包能截取上下文的变量,这可以解决idTime作为全局变量的问题,(闭包的实质是一个全局对象,所有的该闭包函数,都指向这个对象)。
其次,调用call函数将this 指向Dialog。那么就可以在闭包中调用this.closeDialog()来关闭窗体了

   var THIS=this;
   //如果直接写成f.apply(this)},这个this将会指向window对象,而window对象没有closeDialog功能~。
   setTimeout(function(){f.apply(THIS)},50); //正确,通用

于是有了下代码

SimpleDialog.prototype.timeShow = function () {
  this.onload();
  var dialog = document.getElementById('divDialog');
  dialog.style.opacity = 1;

  var changeOpacity = function () {
    var opacity = dialog.style.opacity;
    dialog.style.opacity = opacity - 0.1;
    if (Number(dialog.style.opacity) === Number(0)) {
      this.closeDialog();
      clearInterval(idTime);
    }
  };
  var THIS = this;
  // 这里加的this是windows,将changeOpacity this指向simpleDialog来调用他的
  var idTime = setInterval(function () { changeOpacity.call(THIS); }, 100);
  console.log(idTime);
  dialog.onmouseenter = function (event) {
    document.getElementById('divDialog').style.opacity = 1;
    event.stopPropagation();
    clearInterval(idTime);
    console.log('onmouseenter');
  };

  dialog.onmouseleave = function (e) {
    clearInterval(idTime);
    idTime = setInterval(function () { changeOpacity.call(THIS); }, 100);
    // this.idTime如果声明为内部对象会存在问题
  };

三 渐进消失效果 只是修改了opacity属性 就不表了

实现效果如下

这里写图片描述

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值