zoukankan      html  css  js  c++  java
  • vue使用vue-awesome-swiper实现上拉加载更多的效果

    效果图

    src/components/scroll/index.vue

    <template>
        <!-- 通过ref可以获取到dom对象 -->
        <swiper class="swiper" :options="swiperOption" ref="swiper">
          <div class="mine-scroll-pull-down">
              <me-loading :text="pullDownText" inline ref="pullDownLoading" />
          </div>
          <swiper-slide>
              <!-- 所有内容放在插槽里 -->
              <slot></slot>
          </swiper-slide>
          <div class="mine-scroll-pull-up">
              <me-loading :text="pullUpText" inline ref="pullUpLoading" />
          </div>
          <div class="swiper-scrollbar" slot="scrollbar"></div>
      </swiper>
    </template>
    
    <script>
      import { Swiper, SwiperSlide } from 'vue-awesome-swiper';
      import 'swiper/css/swiper.css';
      import MeLoading from 'components/loading';
    
      export default {
        name: 'Scrollbar',
        title: 'Scrollbar',
        components: {
          Swiper,
          SwiperSlide,
          MeLoading
        },
        data() {
          return {
            pulling:false,//是否正在下拉中
            pullDownText:'向下拉动会重新加载幻灯片哦',
            pullUpText:'向上拉动会加载更多哦',
            swiperOption: {
              scrollbar: {
                el: '.swiper-scrollbar',
                hide: true
              },
              direction:'vertical',
              slidesPerView:'auto',
              freeMode:true,
              setWrapperSize:true,
              on:{//下拉刷新时触发的事件
                sliderMove:this.sliderMove,//一开始使用sliderMove,有bug
                touchEnd:this.touchEnd
              }
            },
          }
        },
        props:{
          recommends:{
            type:[Array,Object],
            default(){
              return [];
            }
          }
        },
        watch:{//当recommends值发生改变时
          recommends(){
            this.$refs.swiper && this.$refs.swiper.$swiper.update();//更新滚动条长度
          }
        },
        methods:{
          sliderMove(){
            if(this.pulling) return;//正在下拉中,则不重复下拉
    
            const swiper=this.$refs.swiper.$swiper;
    
            if(swiper.translate>0){//向下拉
              if(swiper.translate>100){//超出规定的高度
                this.$refs.pullDownLoading.setText("开始下拉...");
              }else{
                this.$refs.pullDownLoading.setText("向下拉动会重新加载幻灯片哦");
              }
            }else if(swiper.isEnd){//上拉
    
              //是否达到上拉的触发条件
              //swiper的位移加上swiper的高度(617px)-50px的值如果大于当前内容高度
              //swiper.translate这个属性可以获取到wrapper的位移,其实可以理解为滚动条滚动的距离
              //swiper.height这个属性获取swiper容器的高度, 也就是显示区域的高度
              //50px是我们设置的一个值。为了让页面不是到达最低部的时候,可以提前加载内容
              //parseInt(swiper.$wrapperEl.css('height'))是wrapper的HTML元素的height属性, 也就是所有内容的高度
              const isPullUp=Math.abs(swiper.translate)+swiper.height-50 > parseInt(swiper.$wrapperEl.css('height'));
    
              if(isPullUp){//开始上拉
                this.$refs.pullUpLoading.setText("开始上拉");
              }else{//保持初始化
                this.$refs.pullUpLoading.setText('向上拉动会加载更多哦');
              }
            }
          },
          touchEnd(){
    
            if(this.pulling) return;//正在下拉中,则不重复下拉
    
            const swiper=this.$refs.swiper.$swiper;
            
            if(swiper.translate>100){
    
              this.pulling=true;//正在下拉中
    
              swiper.allowTouchMove=false;//禁止触摸
              swiper.setTransition(swiper.params.speed);//设置初始速度
              swiper.setTranslate(100);//移动到设定的位置(拖动过度时回到设置的位置)
              swiper.params.virtualTranslate=true;//定住不给回弹
              this.$refs.pullDownLoading.setText("正在下拉中...");//设置正在刷新中的文字
              this.$emit("pull-down",this.pullDownEnd);//触发消息,传递结束下拉的函数
            }else if(swiper.isEnd){//上拉
              //是否达到上拉的触发条件
              const isPullUp=Math.abs(swiper.translate)+swiper.height-30>parseInt(swiper.$wrapperEl.css('height'));
    
              if(isPullUp){//开始上拉
                
                this.pulling=true;
    
                swiper.allowTouchMove=false;//禁止触摸
                swiper.setTransition(swiper.params.speed);//设置初始速度
                swiper.setTranslate(-(parseInt(swiper.$wrapperEl.css('height'))+50-swiper.height));//超过拉动距离时回弹
                swiper.params.virtualTranslate=true;//定住不给回弹
                this.$refs.pullUpLoading.setText("正在上拉中...");//设置正在刷新中的文字
                this.$emit("pull-up",this.pullUpEnd);//触发消息,传递结束下拉的函数
              }
            }
          },
          pullDownEnd(){
            const swiper=this.$refs.swiper.$swiper;
    
            this.pulling=false;//下拉结束
    
            this.$refs.pullDownLoading.setText("下拉结束");//设置加载结束后的文字
            swiper.allowTouchMove=true;//可以触摸
            swiper.setTransition(swiper.params.speed);//设置初始速度           
            swiper.params.virtualTranslate=false;//可以回弹
            swiper.setTranslate(0);//移动到最初的位置
            
          },
          pullUpEnd(){
            const swiper=this.$refs.swiper.$swiper;
    
            this.pulling=false;
    
            this.$refs.pullUpLoading.setText("上拉结束");//设置加载结束后的文字
            swiper.allowTouchMove=true;//可以触摸           
            swiper.params.virtualTranslate=false;//可以回弹
          }
        }
      }
    </script>
    
    <style lang="scss" scoped>
        .swiper-container{
          100%;
          height:100%;
          overflow:hidden;
        }
        .swiper-slide{
          height:auto;
        }
        .mine-scroll-pull-down{
            position:absolute;
            left:0;
            bottom:100%;
            100%;
            height:80px;
        }
        .mine-scroll-pull-up{
            position:absolute;
            left:0;
            top:100%;
            100%;
            height:30px;
        }
    </style>

    src/pages/home/index.vue

    <template>
        <div class="home">
            <scrollbar :data="recommends" @pull-down="pullRefresh" @pull-up="loadMore">
                <slider ref="mySwiper" />
                <home-nav />
                <!-- 热门推荐加载完成后更新滚动条 -->
                <recommend @loaded="updateScroll" ref="recommend" />
            </scrollbar>
            <!-- 该页面自己的子路由 -->
            <router-view></router-view>
        </div>
    
    </template>
    
    <script>
    import Slider from 'components/slider';
    import Scrollbar from 'components/scroll';
    import HomeNav from './nav';
    import Recommend from './recommend';
    
    export default {
        name:"Home",
        components:{
            Slider,   
            Scrollbar,
            HomeNav,
            Recommend    
        },
        data(){
            return{
                recommends:[]
            }
        },
        methods:{
            updateScroll(recommends){
                this.recommends=recommends;
            },
            pullRefresh(end){//刷新轮播图
                this.$refs.mySwiper.getSliders().then(end);
            },
            loadMore(end){//加载更多
                this.$refs.recommend.getRecommends().then(end).catch(err=>{
                    if(err){//没有更多图片了
                        console.log(err);
                    }
                    end();
                });
            }
        }
    }
    </script>
    
    <style scoped>
        .home{
            100%;
            height:100%;
        }
    </style>

    src/pages/home/recommend.vue

    <template>
        <div class="recommend">
            <h3 class="recommend-title">热卖推荐</h3>
            <div class="loading-container" v-if="!recommends.length">
                <me-loading inline />
            </div>
            <ul class="recommend-list">
                <li class="recommend-item" v-for="(item,index) in recommends" :key="index">
                    <router-link class="recommend-link" :to="{name:'home-product',params:{id:item.baseinfo.itemId}}">
                        <!-- <p class="recommend-pic"><img class="recommend-img" :src="item.baseinfo.picUrl"></p> -->
                        <p class="recommend-pic"><img class="recommend-img" v-lazy="item.baseinfo.picUrl"></p>
                        <p class="recommend-name">{{item.name.shortName}}</p>
                        <p class="recommend-oriPrice"><del>¥{{item.price.origPrice}}</del></p>
                        <p class="recommend-info">
                            <span class="recommend-price">¥<strong class="recommend-price-num">{{item.price.actPrice}}</strong></span>
                            <span class="recommend-count">{{item.remind.soldCount}}件已售</span>
                        </p>
                    </router-link>
                </li>
            </ul>
        </div>
    </template>
    
    <script>
    import {getHomeRecommend} from 'api/recommend';
    import MeLoading from 'components/loading';
    
    export default {
        name:"Recommend",
        data(){
            return {
               recommends:[],
               curPage:1,
               totalPage:1
            }
        },
        components:{
            MeLoading
        },
        created(){
            this.getRecommends();        
        },
        methods:{
            getRecommends(){           
                if(this.curPage>this.totalPage) return Promise.reject(new Error('没有更多了'));
    
                return getHomeRecommend(this.curPage).then(data=>{
                    return new Promise(resolve=>{
                  
                        if(data){
                            //console.log(data);
                            
                            this.curPage++;
                            this.totalPage=data.totalPage;
    
                            // concat合并数组内容,每次获取的数据都追加进来
                            this.recommends=this.recommends.concat(data.itemList);
    
                            this.$emit("loaded",this.recommends);//热门推荐区域加载完毕后触发消息
                            resolve();
                        }
                    })
                });
            }
        }
    }
    </script>
    
    <style lang="scss" scoped>
    
        .recommend{
            position:relative;
            100%;
            padding:10px 0;
            font-size:14px;
            text-align:center;
            background:#fff;
        }
        .recommend-list{
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap:wrap;
        }
        .recommend-title{
            margin-bottom:15px;
            position:relative;
    
            &:before,
            &:after{
                content:"";
                display:block;
                position:absolute;
                top:50%;
                40%;
                height:1px;
                background:#ddd;
            }
    
            &:before{
                left:0;        
            }
    
            &:after{
                right:0;
            }
        }
        .recommend-item{
            49%;
            background:#fff;
            box-shadow:0 1px 1px 0 rgba(0,0,0,0.12);
            margin-bottom:8px;
        }
        .recommend-link{
            display:block;
        }
        .recommend-pic{
            position:relative;
            100%;
            padding-top:100%;// 可以实现高度与宽度一致
            margin-bottom:5px;
        }
        .recommend-img{
            100%;
            position:absolute;
            top:0;
            left:0;
            height:100%;
        }
        .recommend-name{
            height:40px;
            padding:0 5px;
            margin-bottom:8px;
            line-height:1.5;
            overflow: hidden;
            text-overflow: ellipsis;
            display: -webkit-box;
            -webkit-line-clamp: 2;
            -webkit-box-orient: vertical;
            white-space: normal !important;
            word-wrap: break-word;
            text-align:left;
    
        }
        .recommend-oriPrice{
            padding:0 5px;
            margin-bottom:8px;
            color:#ccc;
            text-align:left;
        }
        .recommend-info{
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding:0 5px;
            margin-bottom:8px;
        }
        .recommend-price{
            color:#e61414;
    
            &-num{
                font-size:20px;
            }
        }
        .recommend-count{
            color:#999;
        }
        .loading-container{
            padding-top:80px;
        }
         
    </style>

    src/api/recommend.js

    import jsonp from 'assets/js/jsonp';
    
    //获取热门推荐数据
    export const getHomeRecommend=(page=1,psize=20)=>{
        const url='https://ju.taobao.com/json/tg/ajaxGetItemsV2.json';
        const params={
            page,
            psize,
            type:0,
            frontCatId:''//type和frontCatId是根据给定的淘宝接口来添加的
        }
    
        //调用jsonp获取数据
        return jsonp(url,params,{
            param:'callback'
        }).then(res=>{
            if(res.code==='200'){
                console.log("加载更多...");
                return res;
            }
    
            throw new Error('没有成功获取到数据');
        }).catch(err=>{
            if(err){
                console.log(err);
            }
            
        });
        
    }
  • 相关阅读:
    Spring Boot 使用 Micrometer 集成 Prometheus 监控 Java 应用性能
    Prometheus 通过 consul 实现自动服务发现
    Prometheus 通过 consul 分布式集群实现自动服务发现
    使用 PushGateway 进行数据上报采集
    AlertManager 之微信告警模板,UTC时间错8个小时的解决办法
    Prometheus 监控报警系统 AlertManager 之邮件告警
    Elasticsearch:使用 IP 过滤器限制连接
    Elasticsearch:创建 API key 接口访问 Elasticsearch
    Elasticsearch:反向代理及负载均衡在 Elasticsearch 中的应用
    Kibana:如何周期性地为 Dashboard 生成 PDF Report
  • 原文地址:https://www.cnblogs.com/chenyingying0/p/12643943.html
Copyright © 2011-2022 走看看