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
- 参与学习 人
- 提交作业 209 份
- 解答问题 3299 个
本路径是通过ES6基础知识、运用Zepto、Swiper、fullPag等移动端常用工具包、以及当下流行框架Vue,结合多个实战案例,还原真实开发场景,最终实现手机端购物商城网页开发。
了解课程
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星