vue来实现回到顶部代码(参考慕课网):

    <div id='goTop' @click='goTop' v-show = 'toTop'>
      <img src="./goTop.png">
    </div>

  let stop = false;                                   // 全局变量,坑处
  let timer = null;					// 全局变量,坑处

mounted() {
      this.$nextTick(function () {
         window.addEventListener('scroll', this.needToTop);  //滚动事件监听
      });
    },
    methods: {
      goTop: function() {				// 回到顶部方法
        clearInterval(timer);
        timer = setInterval(function() {
	    console.log('不妙');
            let curHeight = document.documentElement.scrollTop || document.body.scrollTop;  // 得到当前高度
            var now = curHeight;
            var speed = (0 - now) / 7;								// 随着高度减速
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
        console.log(`当前的高度应该是:` + curHeight);
	    console.log('我是零你也那我没办法');
            if (curHeight === 0) {							//当前高度为零,停止这次计时器
              clearInterval(timer);  							// C1
            }
            document.documentElement.scrollTop = curHeight + speed;			//直接给高度赋值,会调用needtotop方法
            document.body.scrollTop = curHeight + speed;				//谷歌的
            stop = false;								// A
	    console.log('回到顶部一次'); 
       }, 30);
      },
      needToTop: function() {
        let curHeight = document.documentElement.scrollTop || document.body.scrollTop;
        let viewHeight = document.documentElement.clientHeight;
        if (curHeight > viewHeight + 100) {
          this.toTop = true;                         //赋值是为了按钮的v-show='toTop'
        }
        else
        {
          this.toTop = false;
        }
        if (stop) {					//STOP
          clearInterval(timer);				//C2
	  console.log('我没了');
        }
        stop = true;					//B
        console.log('执行了一次');
      }
    }


从点击回到顶部开始,正常的执行顺序:

ABABABABABABAB......C1

如果在途中先停下来:

ABAB.....AB.....(此时stop为true,但是你突然动了滚条,-->)............STOP.........C2



好,我们逐一地把timer和stop内化成vue组件里的data:

    data() {
      return {
        dataTimer: null
      };
    },
把方法里的所有的timer改成this.dataTimer;

结果即使到了最顶端,竟然还会出现:



这是为什么????这是为什么????这是为什么????这是为什么????这是为什么????这是为什么????



我们接着把stop内化成vue组件里的data

    data() {
      return {
         dataStop: false
      };
    },


再把以上代码的stop全部换成dataStop,

问题更严重了:直接只滚动了一次



居然只执行了一次?????,



填坑:然后我在watch里面观察了这个stop,结果是,没有执行回调函数:

    watch: {
      dataStop: {
        handler: function() {
          console.log('我变了' + this.dataStop);
        }
      }



结论:

在计时器触发的时候,datastop应该是true的,当计时器又去执行滚动条监听事件的时候,虽然在执行之前已经改了this.datastop为false,但是vue里我们 并没有真正的改变过datastop,整个生命周期就是:vue方法调用vue方法,直到vue方法跑完,datastop都没有改动过



Logo

前往低代码交流专区

更多推荐