1. 程式人生 > >vue填坑之回到頂部:

vue填坑之回到頂部:

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都沒有改動過