6-1上拉加载更多

6-1上拉加载更多

scroll/index

<template>
 <swiper :options="sliderOption" ref="swiper">
   <div class="mine-scroll-pull-down" v-if="pullDown">
     <me-loading
:text="pullDownText"
inline
       ref="loadingDown"
/>
   </div>
   <swiper-slide>
     <slot></slot>
   </swiper-slide>
   <div class="mine-scroll-pull-up" v-if="pullUp">
     <me-loading
:text="pullUpText"
inline
       ref="loadingUp"
/>
   </div>
   <div class="swiper-scrollbar" v-if="scrollbar" slot="scrollbar"></div>
 </swiper>
</template>

<script>
import {swiper, swiperSlide} from 'vue-awesome-swiper';
import MeLoading from 'base/loading';
import {PULL_DOWN_HEIGHT, PULL_DOWN_TEXT_INIT, PULL_DOWN_TEXT_START, PULL_DOWN_TEXT_ING, PULL_DOWN_TEXT_END, PULL_UP_HEIGHT, PULL_UP_TEXT_INIT, PULL_UP_TEXT_START, PULL_UP_TEXT_ING, PULL_UP_TEXT_END} from './config';
export default {
   name: 'MeScroll',
components: {
     swiper,
swiperSlide,
MeLoading
   },
props: {
     scrollbar: {
       type: Boolean,
default: true
},
data: {
       type: [Array, Object]
     },
pullDown: {
       type: Boolean,
default: false
},
pullUp: {
       type: Boolean,
default: false
}
   },
data() {
     return {
       pulling: false,
pullDownText: PULL_DOWN_TEXT_INIT,
pullUpText: PULL_UP_TEXT_INIT,
sliderOption: {
         direction: 'vertical',
freeMode: true,
slidesPerView: 'auto',
setSlideWrapperSize: true,
scrollbar: {
           el: this.scrollbar ? '.swiper-scrollbar' : null,
hide: true
},
on: {
           sliderMove: this.scroll,
touchEnd: this.touchEnd
}
       }
     };
},
watch: {
     data() {
       this.$refs.swiper.swiper && this.$refs.swiper.update();
}
   },
methods: {
     scroll() {
       const swiper = this.$refs.swiper.swiper;
// 监控什么时候出现回到顶部
if (this.pulling) {
         return;
}
       console.log(swiper.translate);
if (swiper.translate > 0) { // 下拉
if (!this.pullDown) {
           return;
}
         if (swiper.translate > PULL_DOWN_HEIGHT) {
           this.$refs.loadingDown.setText(PULL_DOWN_TEXT_START);
} else {
           this.$refs.loadingDown.setText(PULL_DOWN_TEXT_INIT);
}
       } else if (swiper.isEnd) {
         if (!this.pullUp) {
           return;
}
         const isPullUp = Math.abs(swiper.translate) + swiper.height - PULL_UP_HEIGHT > parseInt(swiper.$wrapperEl.css('height'));
if (isPullUp) {
           this.$refs.loadingUp.setText(PULL_UP_TEXT_START);
} else {
           this.$refs.loadingUp.setText(PULL_UP_TEXT_INIT);
}
       }
     },
touchEnd() {
       if (this.pulling) {
         return;
}
       const swiper = this.$refs.swiper.swiper;
if (swiper.translate > PULL_DOWN_HEIGHT) { // 下拉
if (!this.pullDown) {
           return;
}
         this.pulling = true;
swiper.allowTouchMove = false; // 禁止触摸
swiper.setTransition(swiper.params.speed);
swiper.setTranslate(PULL_DOWN_HEIGHT);
swiper.params.virtualTranslate = true; // 定住不给回弹
this.$refs.loadingDown.setText(PULL_DOWN_TEXT_ING);
this.$emit('pull-down', this.pullDownEnd);// 触发一个事件
} else if (swiper.isEnd) { // 是否处于底部
const totalHeight = parseInt(swiper.$wrapperEl.css('height'));
const isPullUp = Math.abs(swiper.translate) + swiper.height - PULL_UP_HEIGHT > totalHeight;
if (isPullUp) { // 上拉
if (!this.pullUp) {
             return;
}
           this.pulling = true;
swiper.allowTouchMove = false; // 禁止触摸
swiper.setTransition(swiper.params.speed);
swiper.setTranslate(-(totalHeight + PULL_UP_HEIGHT - swiper.height));
swiper.params.virtualTranslate = true; // 定住不给回弹
this.$refs.loadingUp.setText(PULL_UP_TEXT_ING);
this.$emit('pull-up', this.pullUpEnd);
}
       }
     },
pullDownEnd() {
       const swiper = this.$refs.swiper.swiper;
this.pulling = false;
this.$refs.loadingDown.setText(PULL_DOWN_TEXT_END);
swiper.params.virtualTranslate = false;
swiper.allowTouchMove = true;
swiper.setTransition(swiper.params.speed);
swiper.setTranslate(0);
},
pullUpEnd() {
       const swiper = this.$refs.swiper.swiper;
this.pulling = false;
this.$refs.loadingUp.setText(PULL_UP_TEXT_END);
swiper.params.virtualTranslate = false;
swiper.allowTouchMove = true;
}
   }
 };
</script>

<style lang="scss" scoped>
.swiper-container {
   overflow: hidden;
width: 100%;
height: 100%;
}
 .swiper-slide {
   height: auto;
}
 .mine-scroll-pull-down {
   position: absolute;
width: 100%;
text-align: center;
color: #000;
bottom: 100%;
height: 80px;
}
 .mine-scroll-pull-up {
   top: 100%;
height: 30px;
}
</style>

recommend.vue

<template>
   <div class="recommend">
     <h1 class="recommend-title">热卖推荐</h1>
     <div class="loading" v-if="!recommends.length">
       <me-loading inline/>
     </div>
     <ul class="recommend-list" v-else>
       <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 v-lazy="item.baseinfo.picUrlNew" class="recommend-img"></p>
           <p class="recommend-name">{{item.name.shortName}}</p>
           <p class="recommend-origPrice"><strike>¥{{item.price.origPrice}}</strike></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/home';
import MeLoading from 'base/loading';
export default {
   name: 'recommend',
components: {
     MeLoading
   },
data() {
     return {
       recommends: [],
totalPage: 1,
curPage: 1
};
},
created() {
     this.getRecommend();
},
methods: {
     // API
update() {
       return this.getRecommend();
},
getRecommend() {
       if (this.curPage > this.totalPage) {
         return Promise.reject(new Error('没有更多了'));
}
       return getHomeRecommend(this.curPage).then(data => {
         return new Promise(resolve => {
           if (data) {
             this.curPage++;
this.totalPage = data.totalPage;
this.recommends = this.recommends.concat(data.itemList);
this.$emit('loaded', this.recommends);
resolve();
}
         });
});
}
   }
 };
</script>

<style lang="scss" scoped>
@import "~assets/scss/mixins";
.recommend {
   width: 100%;
position: relative;
&-title {
     position: relative;
width: 100%;
text-align: center;
padding: 10px 0;
font-size: $font-size-l;
&:before,
&:after {
       content: '';
position: absolute;
width: 40%;
height: 1px;
background-color: #ddd;
top: 50%;
}
     &:before {
       left: 0;
}
     &:after {
       right: 0;
}
 }
   &-list {
     @include flex-between();
flex-wrap: wrap;
}
   &-item {
     width: 49%;
background-color: #fff;
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.12);
margin-bottom: 8px;
}
   &-link {
     display: block;
}
   &-pic {
     position: relative;
width: 100%;
padding-top: 100%;
margin-bottom: 5px;
}
   &-img {
     width: 100%;
height: 100%;
position: absolute;
top:0;
left:0;
}
   &-name {
     height: 36px;
padding: 0 5px;
margin-bottom: 8px;
line-height: 1.5;
     @include multiline-ellipsis();
}
   &-origPrice {
     padding: 0 5px;
margin-bottom: 8px;
color: #ccc;
}
   &-info {
     width: 100%;
     @include flex-between();
padding: 0 5px;
margin-bottom: 8px;
}
   &-price {
     color: #f10414;
&-num {
       font-size: $icon-font-size-m;
}
   }
   &-count {
     color: #b8b8b8;
}
 }
 .loading {
   padding-top: 100px;
}
</style>

hoime/index.vue

<template>
   <div class="home">
     <header class="g-header-container">
       <home-header/>
     </header>
     <me-scroll
:data="recommends"
pullDown
       pullUp
       @pull-down ="pullDownToRefurbish"
@pull-up ="pullToLoadMore"
>
       <home-slider ref="slider"/>
       <home-nav/>
       <home-recommend @loaded="getRecommends" ref="recommend"/>
     </me-scroll>
     <div class="g-backtop-container"></div>
     <router-view></router-view>
   </div>
</template>

<script>
import MeScroll from 'base/scroll';
import HomeHeader from './header';
import HomeSlider from './slider';
import HomeNav from './nav';
import HomeRecommend from './recommend';
export default {
   name: 'Home',
components: {
     MeScroll,
HomeHeader,
HomeSlider,
HomeNav,
HomeRecommend
   },
data() {
     return {
       recommends: []
     };
},
methods: {
     getRecommends(recommends) {
       this.recommends = recommends;
},
pullDownToRefurbish(end) {
       this.$refs.slider.update().then(end);
// setTimeout(() => {
       //   console.log('下拉刷新');
       //   end();
       // }, 1000);
},
pullToLoadMore(end) {
       this.$refs.recommend.update().then(end).catch(err => {
         if (err) {
           console.log(err);
}
         end();
});
}
   }
 };
</script>

<style lang="scss" scoped>
@import '~assets/scss/mixins';
.home {
   background-color:$bgc-theme;
width: 100%;
height: 100%;
}
</style>

我这里得问题是, 上拉,直接滑倒顶部, 而且,touchend里得end if 没有执行。  我找不出原因, 和源码文件一 一 兑过了,麻烦老师,找下 。 实在是搞不定!!!

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
卡布琦诺 2018-12-24 11:33:32

为了准确的帮助同学解答疑惑,这里跟同学确认一下,同学是要实现上拉加载更多功能吗?

  • 提问者 丛从绿草 #1
    是啊 , 我这里是上拉内容加载了, 就是滚动条会自动向上到顶部, 我看视频不会出现这情况, 在6-1这节中。
    2018-12-25 10:35:53
  • 提问者 丛从绿草 #2
    这里可以远程协助下嘛 ? 我弄了一天了,搞不起来。找不到哪里原因,我这里 向上拉, 滚动条自动回到顶部,向上拉的内容,跑到底部菜单上面,是不是定位出了问题啊? 可是下拉都正常的。
    2018-12-25 11:53:08
  • 提问者 丛从绿草 #3
    如果,我把top: 100%; 改成 bottom: 100%, 它就和下拉一样一个位置。top就是不会在下面显示, 它就是滚动到最上面之后再显示,
    2018-12-25 11:56:24
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
热门框架Vue开发WebApp 18版
  • 参与学习           人
  • 提交作业       209    份
  • 解答问题       3299    个

本路径是通过ES6基础知识、运用Zepto、Swiper、fullPag等移动端常用工具包、以及当下流行框架Vue,结合多个实战案例,还原真实开发场景,最终实现手机端购物商城网页开发。

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师