基于vue上拉加载vue-infinite-scroll的实现

宗政功
2023-12-01

1.html

<div class="container">
    <!--左右滑动--推荐用户-->
    <div class="slide-box" ref="user">
        <div class="slide-item" v-for="user in shareData.users">
            <div @click="goUserPage(user.id)">
                <img src="../../assets/image/default.png" alt="" v-if="user.avatar===''">
                <img :src="imgburl+user.avatar" v-else>
                <p v-if="user.nickname===''">{{default_name}}</p>
                <p v-else>{{user.nickname}}</p>
            </div>
        </div>
    </div>
    <div class="bg">
        <div class="pub-dynamic">
            <div class="pub-l">大家的动态</div>
            <div class="pub-r">
                <span :class="{active: switchType==='hottest' }" @click="switchShareList('hottest')">最热</span> |
                <span :class="{active: switchType==='latest' }" @click="switchShareList('latest')">最新</span>
                <div class="dot" v-if="switchType==='hottest'"></div>
            </div>
        </div>
    </div>
    <!--动态列表-->
    <div class="mov clearfix" v-if="shareData.moments.length===0">
        <img src="../../assets/image/none.png" alt="" style="width: 100px;height:100px;margin-top: 100px">
    </div>
    <div class="mov" v-else>
        <div class="clearfix">
            <div class="mov-container" v-for="(item,index) in shareData.moments" @click="goDetail(index)"
                 :key="index">
                <div class="mov-item">

                    <div class="mov-img" :style="{backgroundImage: 'url(' + imgburl+item.moment.cover + ')'}"
                         v-if="item.moment.cover">
                        <img src="../../assets/image/player.png" class="player" v-if="item.moment.type==='2'">
                        <div class="mov-con">{{item.moment.content}}</div>
                    </div>
                    <div class="mov-img mov-default-img" v-else>
                        <div class="mov-con">{{item.moment.content}}</div>
                    </div>

                    <div class="mov-data">
                        <div class="mov-data-l" @click.prevent.stop="goUserPage(item.user.id)">
                            <!--当用户头像为空时-->
                            <div v-if="item.user.avatar.trim()===''">
                                <img src="../../assets/image/default.png">
                                <span>{{default_name}}</span>
                            </div>
                            <!--当用户头像不为空时-->
                            <div v-else>
                                <img :src="imgburl+item.user.avatar">
                                <span v-if="item.user.nickname.trim()===''">{{item.user.nickname}}</span>
                                <span v-else>{{default_name}}</span>
                            </div>
                        </div>
                        <div class="mov-data-r">
                            <img src="../../assets/image/care-heart.png" v-if="item.moment.liked==='0'">
                            <img src="../../assets/image/care-red-heart.png" v-else>
                            <span>{{item.moment.like}}</span>
                        </div>
                    </div>
                </div>

            </div>
        </div>
    </div>

    <!--底部-->
    <div v-infinite-scroll="loadMore" infinite-scroll-disabled="load"
         infinite-scroll-distance="10">
        <div class="look loading" v-if="load === true">正在加载中...</div>
        <div class="look" v-if="ended === '1'&&shareData.moments.length>=10">被你看光光啦~</div>
    </div>

</div>

2.js

async function getShareList(type, last_id) {
    let res = await ax.get('/moments/share', {
        type    : type,
        per_page: 10,
        order: 'positive',
        last_id : last_id
    });
    return res.data
}

export default {
    async asyncData() {
        let res = await ax.get('/share');
        return {
            shareData: res.data
        }
    },
    name   : "share",
    data   : function () {
        return {
            switchType  : 'hottest',
            imgburl     : oss,
            ended       : '0',
            load        : false,
            default_name: '钦家用户'
        }
    },
    methods: {
        //切换分享列表类型 hottest:最热 latest:最新
        async switchShareList(type) {
            if (type !== this.switchType) {
                this.switchType = type;
                this.load = false;
                let list = await getShareList(type, 0);
                this.shareData.moments = list.moments;
                this.ended = list.ended;
            }
        },

        //监听滑动页面底部加载更多操作
        async loadMore() {
            if (this.ended !== '1' && this.shareData.moments.length >=10) {
                this.load = true;
                this.getMoreData();
            }
        },

        //加载更多数据
        async getMoreData() {
            let curData = this.shareData.moments;
            let list = await getShareList(this.switchType, curData[curData.length - 1]['moment']['id']);
            if (list) {
                this.ended = list.ended;
                this.shareData.moments = this.shareData.moments.concat(list.moments);
                this.load = false;
            }
        },

        //跳转到原生页面-动态详情
        goDetail(index) {

            let data = this.shareData.moments;

            let para = {
                view  : 'dynamicDetails',
                id    : data[index].moment.id,
                type  : this.switchType,
                lastid: index > 0 ? data[index - 1]['moment']['id'] : 0
            };

            openAppFrame(para, res => {
                log('打开发布动态页面成功:' + JSON.stringify(res))
            })
        },

        //跳转到用户个人信息页面
        goUserPage(userid) {
            const burl = location.protocol + '//' + location.host;
            openAppFrame({
                view: 'jump',
                url : burl + 'user/' + userid,
            }, res => {
                console.log('jump跳转:' + JSON.stringify(res))
            })
        }
    },
    mounted() {
        setTitle("分享");
    }
}

注意:坑
1.v-infinite-scroll='loadMore',不要写成 v-infinite-scroll='loadMore()'
2.注意在js里面判断请求数据的时机,因为假如content区域的高度超不过视口高度的话,v-infinite-distance='10'早已经触发。
3.开关load刚开始设置为false,----------触发时设为true,-----------请求完数据时设置为false

 类似资料: