下拉加载成功得到数据了,但是想往下拉查看下面的商品列表,却还是在下拉加载,也下不去

来源:6-1 上拉加载更多

qq_慕无忌9185596

2019-09-23 16:28:11

//home下的index.vue
<template>
  <div class="home">
    <div class="g-header-container">
      <home-header></home-header>
    </div>
    <ytang-scroll
      :finished="finished"
      pullDown
      pullUp
      @pull-down-fun="pullToRefresh"
      @pull-up-fun="pullToLoadMore"
    >
      <home-slider ref="slider"></home-slider>
      <home-nav></home-nav>
      <home-seal @loaded="getFinished" ref="recommend"></home-seal>
    </ytang-scroll>
    <div class="g-backtop-container"></div>
    <router-view></router-view>
  </div>
</template>

<script>
  import HomeHeader from './header';
  import HomeSlider from './slider';
  import HomeNav from './navigation';
  import HomeSeal from './hotseal';
  import ytangScroll from 'base/scroll/scroll';
  export default {
    name: 'Home',
    components: {
      HomeHeader,
      HomeSlider,
      ytangScroll,
      HomeNav,
      HomeSeal
    },
    data() {
      return {
        finished: false
      };
    },
    methods: {
      getFinished(data) {
        if (data === 'finished') {
          this.finished = true;
        }
      },
      pullToRefresh(end) {
        this.$refs.slider.update().then(end);
        // setTimeout(() => {
        //   console.log('刷新成功');
        //   end();
        // }, 1000);
      },
      pullToLoadMore(more) {
        this.$refs.recommend.update().then(() => {
          console.log('加载成功');
          more();
        }).catch(err => {
          if (err) {
            console.log(err);
          }
          more();
        });
      }
    }
  };
</script>

<style lang="scss" scoped>
  @import "~assets/scss/mixins";

  .home{
    width: 100%;
    height: 100%;
    overflow: hidden;
    background-color: $bgc-theme;
  }
</style>
//scroll.vue
<template>
  <swiper :options="swiperOption" ref='swiper'>
    <div class="mine-scroll-pull-down" v-if="pullDown">
      <me-loading :text="pullDownText" inline ref="pullDownLoading"></me-loading>
    </div>
    <swiper-slide>
      <slot></slot>
    </swiper-slide>
    <div class="mine-scroll-pull-up" v-if="pullUp">
      <me-loading :text="pullUpText" inline ref="pullUpLoading"></me-loading>
    </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/loading';
  import {PULL_DOWN_HEIGHT, PULL_DOWN_TEXT_INIT, PULL_DOWN_TEXT_START, PULL_DOWN_TEXT_ING, PULL_DOWN_TEXT_END, PULL_UP_TEXT_INIT, PULL_UP_HEIGHT, PULL_UP_TEXT_START, PULL_UP_TEXT_ING, PULL_UP_TEXT_END} from './config';

  export default {
    name: 'Scroll',
    props: {
      scrollbar: {
        type: Boolean,
        default: true
      },
      finished: {
        type: Boolean
      },
      pullDown: {
        type: Boolean,
        default: false
      },
      pullUp: {
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        pulling: false,
        pullDownText: PULL_DOWN_TEXT_INIT,
        pullUpText: PULL_UP_TEXT_INIT,
        swiperOption: {
          direction: 'vertical',
          slidesPerView: 'auto',
          freeMode: true,
          setWrapperSize: true,
          scrollbar: {
            el: this.scrollbar ? '.swiper-scrollbar' : null,
            hide: true
          },
          on: {
            sliderMove: this.scroll,
            touchEnd: this.touchEnd
          }
        }
      };
    },
    components: {
      swiper,
      swiperSlide,
      MeLoading
    },
    watch: {
      finished() {
        this.updataScroll();
      }
    },
    methods: {
      updataScroll() {
        this.$refs.swiper && this.$refs.swiper.swiper.update();
      },
      scroll() {
        const swiper = this.$refs.swiper.swiper;
        if (this.pulling) {
          return;
        }
        if (swiper.translate > 0) {
          if (!this.pullDown) {
            return;
          }
          if (swiper.translate > PULL_DOWN_TEXT_END) {
            this.$refs.pullDownLoading.setText(PULL_DOWN_TEXT_START);
          } else {
            this.$refs.pullDownLoading.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.pullUpLoading.setText(PULL_UP_TEXT_START);
          } else {
            this.$refs.pullUpLoading.setText(PULL_UP_TEXT_INIT);
          }
        }
      },
      touchEnd() {
        if (this.pulling) {
          return;
        }

        const swiper = this.$refs.swiper.swiper;
        if (swiper.translate > 0) {
          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.pullDownLoading.setText(PULL_DOWN_TEXT_ING);
          this.$emit('pull-down-fun', this.pullDownFun);
        } 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.pullUpLoading.setText(PULL_UP_TEXT_ING);
            this.$emit('pull-up-fun', this.pullUpEnd);
          }
        }
      },
      pullDownFun() {
        const swiper = this.$refs.swiper.swiper;
        this.pulling = false;
        this.$refs.pullDownLoading.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.pullUpLoading.setText(PULL_UP_TEXT_END);
        swiper.params.virtualTranslate = false;
        swiper.allowTouchMove = true;
        console.log('ture');
      }
    }
  };

</script>
<style lang="scss" scoped>
  .swiper-container{
    height: 100%;
    width: 100%;
    overflow: hidden;
  }
  .swiper-slide{
    height: auto;
  }

  .mine-scroll-pull-up,
  .mine-scroll-pull-down {
    position: absolute;
    left: 0;
    width: 100%;
  }
  .mine-scroll-pull-down {
    bottom: 100%;
    height: 80px;
  }

  .mine-scroll-pull-up {
    top: 100%;
    height: 30px;
  }
</style>
//loading.vue
<template>
    <div class="ytang-loading" :class="{'loading-inline': inline}">
      <span class="ytang-loading-img" v-if="indicator === 'on'">
        <slot><img src="./loading.gif" alt="loading"></slot>
      </span>
      <span class="ytang-loading-text" v-if="loadingText">{{loadingText}}</span>
    </div>
</template>

<script>
  export default {
    name: 'Loading',
    props: {
      indicator: {
        type: String,
        default: 'on',
        validator(value) {
          return ['on', 'off'].indexOf(value) > -1;
        }
      },
      text: {
        type: String,
        default: '加载中...'
      },
      inline: {
        type: Boolean,
        default: true
      }
    },
    data() {
      return {
        loadingText: this.text
      };
    },
    watch: {
      text(text) {
        this.loadingText = text;
      }
    },
    methods: {
      setText(text) {
        this.loadingText = text;
      }
    }
  };
</script>

<style lang="scss" scoped>
  @import "~assets/scss/mixins";

  .ytang-loading{
    width: 100%;
    height: 100%;
    @include flex-center(column);

    &.loading-inline{
      flex-direction: row;

      .ytang-loading-img ~ .ytang-loading-text{
        margin-top: 0;
        margin-left: 6px;
      }
    }
  }
  .ytang-loading-img ~ .ytang-loading-text{
    margin-top: 6px;
    margin-left: 0;
  }
</style>
//hotseal.vue(recommend.vue)
<template>
  <div class="home-seal">
    <h3 class="home-seal-title">热卖推荐</h3>
    <div class="seal-loading" v-if="!sealList.length">
      <ytang-loading></ytang-loading>
    </div>
    <ul class="home-seal-list" v-else>
      <li
        class="list-link"
        v-for="(item, index) in sealList"
        :key="index"
      >
        <router-link :to="{name: 'home-commodity', params:{id: item.baseinfo.itemId}}" class="list-link-a">
          <div class="list-link-imgdiv">
            <img v-lazy="item.baseinfo.picUrlNew" alt="image" class="list-link-img">
          </div>
          <p class="list-link-name">{{item.name.shortName}}</p>
          <p class="list-link-originPrice"><del>¥{{item.price.origPrice}}</del></p>
          <p class="list-link-info">
            <span class="info-price">¥<strong class="info-price-num">{{item.price.actPrice}}</strong></span>
            <span class="info-count">{{item.remind.soldCount}}件已售</span>
          </p>
        </router-link>
      </li>
    </ul>
  </div>
</template>

<script>
  import {getHomeSeal} from 'api/home';
  import ytangLoading from 'base/loading/loading';

  export default {
    name: 'HotSeal',
    components: {
      ytangLoading
    },
    data() {
      return {
        sealList: [],
        curPage: 1,
        totalPage: 1
      };
    },
    created() {
      this.getSealList();
    },
    methods: {
      update() {
        return this.getSealList();
      },
      getSealList() {
        if (this.curPage > this.totalPage) {
          return Promise.reject(new Error('没有更多了'));
        }
        return getHomeSeal(this.curPage).then(data => {
          return new Promise(resolve => {
            if (data) {
              this.curPage++;
              this.totalPage = data.totalPage;
              this.sealList = this.sealList.concat(data.itemList);
              this.$emit('loaded', 'finished');
              resolve();
            }
          });
        });
      }
    }
  };
</script>

<style lang="scss" scoped>
  @import "~assets/scss/mixins";

  .home-seal{
    .seal-loading{
      padding-top: 100px;
    }
    &-title{
      position: relative;
      width: 100%;
      padding: 10px 0;
      font-size: $font-size-l;
      text-align: center;

      &:before,
      &:after{
        content: '';
        position: absolute;
        top: 50%;
        width: 40%;
        height: 1px;
        background-color: #ddd;
      }
      &:before{
        left: 0;
      }
      &:after{
        right: 0;
      }
    }
    &-list{
      @include flex-between();
      flex-wrap: wrap;
      .list-link{
        width: 49%;
        background-color: #fff;
        box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.12);
        margin-bottom: 8px;
        &-a{
          display: block;
        }
        &-imgdiv{
          position: relative;
          width: 100%;
          padding-top: 100%;
          margin-bottom: 5px;
        }
        &-img{
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
        }
        &-name {
          height: 36px;
          padding: 0 5px;
          margin-bottom: 8px;
          line-height: 1.5;
          @include multiline-ellipsis();
        }
        &-originPrice {
          padding: 0 5px;
          margin-bottom: 8px;
          color: #ccc;
        }

        &-info {
          @include flex-between();
          padding: 0 5px;
          margin-bottom: 8px;

          .info-price {
            color: #e61414;
            &-num{
              font-size: 20px;
            }
          }

          .info-count {
            color: #999;
          }
        }
      }
    }
  }
</style>
//home.js
import axios from 'axios';
import jsonp from 'assets/js/jsonp';
import {SUCC_CODE, TIMEOUT, HOME_RECOMMEND_PAGE_SIZE, jsonpOptions} from './config';

const shuffle = (arr) => {
  const arrLength = arr.length;
  let i = arrLength;
  let rndNum;

  while (i--) {
    if (i !== (rndNum = Math.floor(Math.random() * arrLength))) {
      [arr[i], arr[rndNum]] = [arr[rndNum], arr[i]];
    }
  }

  return arr;
};

export const getHomeSlider = () => {
  return axios.get('http://www.imooc.com/api/home/slider', {timeout: TIMEOUT}).then(res => {
    if (res.data.code === SUCC_CODE) {
      let sliders = res.data.slider;
      const slider = [sliders[Math.floor(Math.random() * sliders.length)]];
      sliders = shuffle(sliders.filter(() => Math.random() >= 0.5));
      if (sliders.length === 0) {
        sliders = slider;
      }
      return sliders;
    }

    throw new Error('没有请求成功哦~');
  }).catch(err => {
    if (err) {
      console.log(err);
    }

    return [{
      linkUrl: 'https://www.imooc.com',
      picUrl: require('assets/img/404.png')
    }];
  });
};

export const getHomeSeal = (page = 1, psize = HOME_RECOMMEND_PAGE_SIZE) => {
  const url = 'https://ju.taobao.com/json/tg/ajaxGetItemsV2.json';
  const params = {
    page,
    psize,
    type: 0,
    frontCatId: ''
  };

  return jsonp(url, params, jsonpOptions).then(res => {
    if (res.code === '200') {
      return res;
    }
    throw new Error('没有成功获取到数据!');
  }).catch(err => {
    if (err) {
      console.log(err);
    }
  });
};


写回答

1回答

qq_慕无忌9185596

提问者

2019-09-23

我知道原因了老师,因为每次请求热卖商品都是要刷新滚动条的,我也的确做了这部分处理,但是不像项目那样传的是请求列表结果,而是自己定义的一个布尔量,这样处理对首次加载没问题,把false变成true可以在滚条组件监听到改变从而更新滚动条,可是继续加载后布尔值还是true,并没有改变,所以也就没有更新滚动条了,从而导致问题,现已解决,还是乖乖把监听变量换成返回的list数组了,谢谢老师

0

0 学习 · 10739 问题

查看课程