1. 程式人生 > >Vant list 與better-scroll與下拉重新整理(其實是上拉載入)

Vant list 與better-scroll與下拉重新整理(其實是上拉載入)

發現件事情,我好想把下拉重新整理和下拉載入搞反了,所以其實這篇記錄的是上拉載入,emmm。。

先是用了vant的LIst下拉重新整理,然後發現better-scroll中這個外掛沒有用,然後自己寫了個監聽!最後發現一篇文章有封裝scroll中下拉重新整理!這個過程也是莫名其妙了。

1、首先是用了Vant的List實現

Vant List官網
這部分就是官網的例子修改了點。注意一個引數:immediate-check 是否在初始化時立即執行滾動位置檢查,預設是true,就在created的時候就執行一次onLoad載入,如果你的程式碼不需要一開始就執行onLoad,設定為false.

<
template> <van-list v-model="loading" :finished="finished" @load="onLoad" :loading-text="loadText"> //基本用法就這個樣子了 //這裡就放自己的資料了,隨便弄點資料吧! <div v-for="goods in goodsInfo"> <delete-goods-list :goods="goods"></delete-goods-list> </div> </van-list> </template>
<script type="text/ecmascript-6"> //設定一個每次載入的資料個數 const loadNumUp = 5; data() { return { loading: false, finished: false, loadText:'載入中…', pageNum:1, upGoodsInfo: [], } }, methods: { //只要檢測到你在下拉,預設距離底部300px時就重新整理
onLoad() { console.log('下拉重新整理'); // 非同步更新資料,要看效果,官網的例子是通過setTimeOut進行延時模擬非同步更新,把延時時間調大點效果就很明顯。 //這裡我是向伺服器發請求獲得的資料,伺服器端是分頁的。 let postInfoUp = { "data": { //引數為每次訪問的個數和頁數 "limit": loadNum, "page": ++this.pageNum, } }; this.$api.Goods.getAllGoods(postInfoUp) .then(res => { if (res.data.code === 200) { let re = res.data.data.list; if (re.length !== 0) { //新增資料拼接在後面 this.upGoodsInfo = this.upGoodsInfo.concat(ss); } // 載入狀態結束 this.loadingUp = false; // 資料全部載入完成 if (this.upGoodsInfo.length >= this.totalNumUp) { this.finishedUp = true; this.loadText = "載入完成"; console.log('沒資料要載入了') } }else{ this.finished = true; } }); }, } </script>

注意事項:

vant中的list實際上監聽的是scroll事件,當你下拉時,觸發onLoad事件,並將loading設定為true。
但這個元件不適用於better-scroll,如果你整個頁面用了better-scroll,那麼你滾動要監聽的事件是touchstart和touchend,因為它模擬的就是手機端手勢,監聽web端的滾動scroll是沒有任何變化的。

2、在better-scroll下,下拉重新整理

這篇文章在vue下將better-scroll重新封裝,除了原本良好的使用者體驗,還包含下拉重新整理,上拉載入功能。
當 better-scroll 遇見 Vue
但是,我寫的時候並沒有看到這個,宛如一個瞎子 ̄ω ̄~
好吧,既然list不監聽touchstart和touchend,那就自己寫吧。

<div >
    <div v-for="goods in goodsInfo">
           <delete-goods-list :goods="goods"></delete-goods-list>
    </div>
    //加個載入提示,
    <p  v-show="showLoad">載入中……}</p>
    
    //要是想用LIst的提示,把這裡最外層的div改成
    //<van-list  v-model="loading"  loading-text="載入中……" >即可。
 
</div>

data() {
            return {
                goodsInfo: [],
                loading: false,
                finished: false, 
                showLoad:false,    
           }
} ,
//監聽
 mounted() {
            let startx, starty;
            let self = this;
            //手指接觸螢幕
            document.addEventListener('touchstart', (e) => {
                startx = e.touches[0].pageX;
                starty = e.touches[0].pageY;
            });

            //手指離開螢幕
            document.addEventListener("touchend", function (e) {

                let endx = e.changedTouches[0].pageX;
                let endy = e.changedTouches[0].pageY;
                let direction = getDirection(startx, starty, endx, endy);
                //當手勢向上滑動,載入
                if (direction === 1) {
                 	self.showLoad = true;//顯示載入提示
                    console.log("向上滑動!", self.finished);
                    if (self.finished === false) {
                        self.loading = true;
                        self.onLoad();
                        self.$refs.mScroll._initScroll();
                    }
                }

      });

 },
 methods: {
	onLoad() {
            if (this.loading === true && this.finished === false) {

                  // 非同步更新資料,跟用list時的onLoad中程式碼是一樣的
	                  ....
	                   // 載入狀態結束
                      this.loading = false;
              		  this.showLoad = false;
              		  ......
           }
     }
}

getDirection獲取方向,這個也是搬運呀,原部落格

export  function  getDirection(startx, starty, endx, endy) {
    var angx = endx - startx;
    var angy = endy - starty;
    var result = 0;
    //如果滑動距離太短
    if (Math.abs(angx) < 2 && Math.abs(angy) < 2) {
        return result;
    }
    var angle = getAngle(angx, angy);
    //1:向上; 2:向下; 3:向左; 4:向右
	//這裡利用的角度,手勢是向上,列表向下滑動。即end在start上方,
	//此時angx為正,angy為負,位於第四象限,限定<-45即是垂直方向。
    if (angle >= -135 && angle <= -45) {
        result = 1;
    } else if (angle > 45 && angle < 135) {
        result = 2;
    } else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
        result = 3;
    } else if (angle >= -45 && angle <= 45) {
        result = 4;
    }
    return result;
};

function getAngle(angx, angy) {
    return Math.atan2(angy, angx) * 180 / Math.PI;
};

3、用封裝了better-scroll的下拉重新整理

// 是否派發頂部下拉事件,用於下拉重新整理
if (this.pulldown) {
	this.scroll.on('touchend', (pos) => {
	    // 下拉動作
	    if (pos.y > 50) {
	        this.$emit('pulldown')
	    }
	})
}
...

上面的這部分程式碼用下面的程式碼替代

if (this.pulldown) {
	console.log('pulldown');
	let startx, starty;
	let self = this;
	//手指接觸螢幕
	document.addEventListener('touchstart', (e) => {
	
	    startx = e.touches[0].pageX;
	    starty = e.touches[0].pageY;
	});
	
	//手指離開螢幕
	document.addEventListener("touchend", function (e) {
	
	    let endx = e.changedTouches[0].pageX;
	    let endy = e.changedTouches[0].pageY;
	    let direction = getDirection(startx, starty, endx, endy);
	    //當手勢向上滑動,載入
	    if (direction === 1) {
	    	//向父元件傳送 下拉請求,執行相應函式
	        self.$emit('pulldown');
	    }
	});
}

頁面HTML

<template>
    <div class="deleteGoods">
        <scroll class="vertical-fixed" 
                :data="goodsInfo"
                :pulldown="pulldown" @pulldown="onLoad" >
            <div class="vertical-fixed-wrapper" >

                    <div v-for="goods in goodsInfo">
                        <delete-goods-list :goods="goods"></delete-goods-list>
                    </div>

                    <!--這裡加height: 0 ,是因為會出現當display:none時還是佔據了空間,
                       所以設定高度為0,margin-top: 10px是為了首次載入的時候,動畫與top有距離-->
                    <div v-show="showLoad" style="height: 0;  margin-top: 10px">
                        <van-loading type="spinner" style="margin: 0 auto"  ></van-loading>
                    </div>
            </div>
        </scroll>
    </div>
</template>

//onload()還是和上面一樣的