接上篇 https://www.cnblogs.com/chenyingying0/p/12623653.html
下拉刷新
下拉刷新--变化提示文字
base/scroll/index.vue
<template> <!-- wiper会实例化构造函数,生成swiper实例 --> <!-- ref="swiper"能够获取到这个swiper实例 --> <swiper :options="swiperOption" ref='swiper'> <div class="mine-scroll-pull-down" v-if="pullDown"> <!-- ref="pullDownLoading" -- 获取下拉的loading --> <me-loading :text="pullDownText" inline ref="pullDownLoading" /> </div> <swiper-slide> <slot></slot> </swiper-slide> <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 } from './config'; export default { name:"MeScroll", components:{ Swiper, SwiperSlide, MeLoading }, props:{//过滤器 scrollbar:{ type:Boolean, default:true }, data:{//热门推荐加载完成后传递过来的recommends数据 type:[Array,Object] }, pullDown:{ type:Boolean, default:false } }, data(){ return { pullDownText:PULL_DOWN_TEXT_INIT,//设置初始化文字 swiperOption:{ direction:'vertical',//垂直方向 slidesPerView:'auto',//一次显示几张 freeMode:true,//任意滑动多少距离 setWrapperSize:true,//根据内容设置容器尺寸 scrollbar:{ el:this.scrollbar?'.swiper-scrollbar':null, hide:true //滚动条自动隐藏 }, on:{ //swiper配置时会触发sliderMove方法,这里调用时执行自定义的scroll方法 sliderMove:this.scroll } } } }, methods:{ update(){//不知道怎么写就去swiper官网查api console.log(this.$refs.swiper);//打印swiper实例 this.$refs.swiper && this.$refs.swiper.$swiper.update();//调用swiper.update()更新滚动条 }, scroll(){ const swiper=this.$refs.swiper.$swiper; console.log(swiper.translate);//打印出滚动条滚过的距离 if(swiper.translate>0){//下拉 if(!this.pullDown){//如果不需要下拉刷新 return; } if(swiper.translate>PULL_DOWN_HEIGHT){ this.$refs.pullDownLoading.setText(PULL_DOWN_TEXT_START); }else{ this.$refs.pullDownLoading.setText(PULL_DOWN_TEXT_INIT); } } } }, watch:{//检测数据变化的事件 data(){ this.update();//data数据变化时执行update函数 } } } </script> <style lang="scss" scoped> @import '~assets/scss/mixins'; .swiper-container{ width:100%; height:100%; overflow:hidden; & .swiper-slide{ height:auto; } } //默认是不显示的 .mine-scroll-pull-down{ position:absolute; left:0; bottom:100%; width:100%; height:80px; } </style>
base/loading/index.vue
<template> <div class="mine-loading" :class="{'me-loading-inline':inline}"> <span class="mine-loading-indicator" v-if="indicator==='on'" > <img src="./loading.gif" alt=""> </span> <span class="mine-loading-text" v-if="loadingText">{{loadingText}}</span> </div> </template> <script> export default { name:"MeLoading", props:{//过滤器 indicator:{ type:String, default:'on', validator(value){ return ['on','off'].indexOf(value)>-1; } }, text:{ type:String, default:'加载中...' }, inline:{ type:Boolean, default:false } }, data(){ return{ loadingText:this.text } }, methods:{ setText(text){ this.loadingText=text; } }, watch:{ text(text){ this.loadingText=text; } } } </script> <style lang="scss" scoped> @import '~assets/scss/mixins'; .mine-loading{ width:100%; height:100%; @include flex-center(column); //图文左右排列时 &.me-loading-inline{ flex-direction: row; .mine-loading-indicator ~ .mine-loading-text{ margin-top:0px; margin-left:7px; } } .mine-loading-indicator{ } // 存在.mine-loading-indicator和.mine-loading-text时 .mine-loading-indicator ~ .mine-loading-text{ margin-top:7px; } } </style>
base/scroll/config.js
export const PULL_DOWN_HEIGHT=100; export const PULL_DOWN_TEXT_INIT='再拉,再拉就刷新给你看'; export const PULL_DOWN_TEXT_START='够了啦,松开人家嘛'; export const PULL_DOWN_TEXT_ING='刷的好累呀,喵~'; export const PULL_DOWN_TEXT_END='刷新完啦';
pages/home/index.vue
<template> <div class="home"> <header class="g-header-container"> <!-- 没有内容自闭合即可--> <home-header/> </header> <!-- 滚动条接收到数据后开始更新 --> <!-- pullDown是布尔值,可以使用简写直接传入,不加冒号 --> <me-scroll :data="recommends" pullDown> <home-slider /> <home-nav /> <!-- 接收热门推荐加载完毕的消息 --> <home-recommend @loaded="getRecommends" /> </me-scroll> <div class="g-backup-container"></div> <!-- 当前页面存在二级页面时需要使用router-view --> <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:{ HomeHeader, HomeSlider, MeScroll, HomeNav, HomeRecommend }, data(){ return{ recommends:[] } }, methods:{ getRecommends(recommends){ this.recommends=recommends; }, updateScroll(){ } } } </script> <style lang="scss" scoped> // 引入前面需要加波浪线,否则会报错 @import "~assets/scss/mixins"; .home{ overflow:hidden; width:100%; height:100%; background:$bgc-theme; } </style>
效果图
下拉刷新--松手刷新
修改base/scroll/index.vue
<template> <!-- wiper会实例化构造函数,生成swiper实例 --> <!-- ref="swiper"能够获取到这个swiper实例 --> <swiper :options="swiperOption" ref='swiper'> <div class="mine-scroll-pull-down" v-if="pullDown"> <!-- ref="pullDownLoading" -- 获取下拉的loading --> <me-loading :text="pullDownText" inline ref="pullDownLoading" /> </div> <swiper-slide> <slot></slot> </swiper-slide> <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 } from './config'; export default { name:"MeScroll", components:{ Swiper, SwiperSlide, MeLoading }, props:{//过滤器 scrollbar:{ type:Boolean, default:true }, data:{//热门推荐加载完成后传递过来的recommends数据 type:[Array,Object] }, pullDown:{ type:Boolean, default:false } }, data(){ return { pulling:false,//是否正在下拉 pullDownText:PULL_DOWN_TEXT_INIT,//设置初始化文字 swiperOption:{ direction:'vertical',//垂直方向 slidesPerView:'auto',//一次显示几张 freeMode:true,//任意滑动多少距离 setWrapperSize:true,//根据内容设置容器尺寸 scrollbar:{ el:this.scrollbar?'.swiper-scrollbar':null, hide:true //滚动条自动隐藏 }, on:{ //swiper配置时会触发sliderMove方法,这里调用时执行自定义的scroll方法 sliderMove:this.scroll, touchEnd:this.touchEnd//touchEnd是swiper提供的滚动结束的函数,this.touchEnd是我们自己写的函数 } } } }, methods:{ update(){//不知道怎么写就去swiper官网查api //console.log(this.$refs.swiper);//打印swiper实例 this.$refs.swiper && this.$refs.swiper.$swiper.update();//调用swiper.update()更新滚动条 }, 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.pullDownLoading.setText(PULL_DOWN_TEXT_START); }else{ this.$refs.pullDownLoading.setText(PULL_DOWN_TEXT_INIT); } } }, touchEnd(){ const swiper=this.$refs.swiper.$swiper; //如果正在下拉中,不会再次执行 if(this.pulling) return; 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.pullDownLoading.setText(PULL_DOWN_TEXT_ING);//设置正在刷新中的文字 this.$emit("pull-down",this.pullDownEnd);//触发消息,传递结束下拉的函数 } }, pullDownEnd(){ const swiper=this.$refs.swiper.$swiper; this.pulling=false; this.$refs.pullDownLoading.setText(PULL_DOWN_TEXT_END);//设置加载结束后的文字 swiper.allowTouchMove=true;//可以触摸 swiper.setTransition(swiper.params.speed);//设置初始速度 swiper.params.virtualTranslate=false;//可以回弹 swiper.setTranslate(0);//移动到最初的位置 } }, watch:{//检测数据变化的事件 data(){ this.update();//data数据变化时执行update函数 } } } </script> <style lang="scss" scoped> @import '~assets/scss/mixins'; .swiper-container{ width:100%; height:100%; overflow:hidden; & .swiper-slide{ height:auto; } } //默认是不显示的 .mine-scroll-pull-down{ position:absolute; left:0; bottom:100%; width:100%; height:80px; } </style>
修改pages/home/index.vue
<template> <div class="home"> <header class="g-header-container"> <!-- 没有内容自闭合即可--> <home-header/> </header> <!-- 滚动条接收到数据后开始更新 --> <!-- pullDown是布尔值,可以使用简写直接传入,不加冒号 --> <!-- 接收到pull-down消息后,触发pullToRefresh方法 --> <me-scroll :data="recommends" pullDown @pull-down="pullToRefresh"> <home-slider /> <home-nav /> <!-- 接收热门推荐加载完毕的消息 --> <home-recommend @loaded="getRecommends" /> </me-scroll> <div class="g-backup-container"></div> <!-- 当前页面存在二级页面时需要使用router-view --> <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:{ HomeHeader, HomeSlider, MeScroll, HomeNav, HomeRecommend }, data(){ return{ recommends:[] } }, methods:{ getRecommends(recommends){ this.recommends=recommends; }, updateScroll(){ }, pullToRefresh(end){ setTimeout(()=>{ console.log("下拉刷新"); end(); },1000); } } } </script> <style lang="scss" scoped> // 引入前面需要加波浪线,否则会报错 @import "~assets/scss/mixins"; .home{ overflow:hidden; width:100%; height:100%; background:$bgc-theme; } </style>
效果图
更新幻灯片
真正实现通过下拉刷新,更新幻灯片
修改src/api/home.js
import axios from 'axios'; import {SUCC_CODE,TIMEOUT,HOME_RECOMMEND_PAGE_SIZE,JSONP_OPTIONS} from './config'; import jsonp from 'assets/js/jsonp'; // shuffle打乱数组顺序的方法 const shuffle=(arr)=>{ const arrLength=arr.length; let i=arrLength; let rndNum; while(i--){ //如果当前索引不等于随机数索引,则交换这两个索引的位置 if(i!==(rndNum=Math.floor(Math.random()*arrLength))){ //这是一种新的交换写法 ES6解构 [arr[i],arr[rndNum]]=[arr[rndNum],arr[i]]; } } return arr; } //获取幻灯片数据 ajax export const getHomeSliders=()=>{ //演示超时错误 return axios.get('http://www.imooc.com/api/home/slider',{ timeout:TIMEOUT }).then(res=>{ //console.log(res); if(res.data.code===SUCC_CODE){ //这段代码的作用主要是演示下拉刷新的效果 //每次刷新会加载出不同数量,不同顺序的轮播图 let sliders=res.data.slider; const slider=[sliders[Math.floor(Math.random()*sliders.length)]];//slider是从sliders中随机取出一张图片,并包装成数组 sliders=shuffle(sliders.filter(()=>Math.random()>=0.5));//50%的概率,真就返回,假就剔除 if(sliders.length===0){ sliders=slider;//如果不幸一张都没有,就把之前随机的那张赋值给sliders } return sliders; //return res.data.slider; } throw new Error('没有成功获取到数据'); }).catch(err=>{ console.log(err); //错误处理 return [{ linkUrl:'www.baidu.com', picUrl:require('assets/img/404.png') }] }).then(data=>{//获取轮播图数据后,延迟一秒再显示 return new Promise(resolve=>{ setTimeout(()=>{ resolve(data); },1000); }) }); } //获取热门推荐数据 export const getHomeRecommend=(page=1,psize=HOME_RECOMMEND_PAGE_SIZE)=>{ const url='https://ju.taobao.com/json/tg/ajaxGetItemsV2.json'; const params={ page, psize, type:0, frontCatId:''//type和frontCatId是根据给定的淘宝接口来添加的 } //调用jsonp获取数据 return jsonp(url,params,JSONP_OPTIONS).then(res=>{ if(res.code==='200'){ return res; } throw new Error('没有成功获取到数据'); }).catch(err=>{ if(err){ console.log(err); } }).then(res=>{ //延迟一秒返回数据 return new Promise(resolve=>{ setTimeout(()=>{ resolve(res); },1000); }) }) }
pages/home/slider.vue
<template> <div class="slider-wrapper"> <!-- sliders没加载时显示loading --> <Meloading v-if="!sliders.length"></Meloading> <!-- 分开传才能分开校验,因此不直接传入对象 --> <MeSlider :data="sliders" :direction="direction" :loop="loop" :interval="interval" :pagination="pagination" v-else > <swiper-slide v-for="(item,index) in sliders" :key="index"> <a :href="item.linkUrl" class="slider-link"> <img :src="item.picUrl" class="slider-img"> </a> </swiper-slide> </MeSlider> </div> </template> <script> import MeSlider from 'base/slider'; import { SwiperSlide } from 'vue-awesome-swiper'; import { sliderOptions } from './config'; import { getHomeSliders } from 'api/home'; import Meloading from 'base/loading'; export default { name:"HomeSlider", components:{ MeSlider, SwiperSlide, Meloading }, data(){ return{ direction:sliderOptions.direction, loop:sliderOptions.loop, interval:sliderOptions.interval, pagination:sliderOptions.pagination, sliders:[],//这是从服务器读取 } }, created(){ //一般在created里获取远程数据 this.getSliders(); }, methods:{ //api update(){ return this.getSliders(); }, getSliders(){ return getHomeSliders().then(data=>{ //console.log(data); this.sliders=data; }); } } } </script> <style lang="scss" scoped> // 引入前面需要加波浪线,否则会报错 @import "~assets/scss/mixins"; .slider-wrapper{ width:100%; height:183px; } .slider-link{ display:block; } .slider-link, .slider-img{ width:100%; height:100%; } </style>
pages/home/index.vue
<template> <div class="home"> <header class="g-header-container"> <!-- 没有内容自闭合即可--> <home-header/> </header> <!-- 滚动条接收到数据后开始更新 --> <!-- pullDown是布尔值,可以使用简写直接传入,不加冒号 --> <!-- 接收到pull-down消息后,触发pullToRefresh方法 --> <me-scroll :data="recommends" pullDown @pull-down="pullToRefresh"> <home-slider ref="slider" /> <home-nav /> <!-- 接收热门推荐加载完毕的消息 --> <home-recommend @loaded="getRecommends" /> </me-scroll> <div class="g-backup-container"></div> <!-- 当前页面存在二级页面时需要使用router-view --> <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:{ HomeHeader, HomeSlider, MeScroll, HomeNav, HomeRecommend }, data(){ return{ recommends:[] } }, methods:{ getRecommends(recommends){ this.recommends=recommends; }, updateScroll(){ }, pullToRefresh(end){ this.$refs.slider.update().then(end); } } } </script> <style lang="scss" scoped> // 引入前面需要加波浪线,否则会报错 @import "~assets/scss/mixins"; .home{ overflow:hidden; width:100%; height:100%; background:$bgc-theme; } </style>
base/slider/index.vue
<template> <div class="mine-slider"> <!-- 动态的属性前面加冒号 --> <swiper :options="swiperOption" class="swiper-container" :key="keyId"> <slot></slot> <div class="swiper-pagination" v-if="pagination" slot="pagination"></div> </swiper> </div> </template> <script> import { Swiper } from 'vue-awesome-swiper'; export default { name:"MeSlider", components: { Swiper }, props:{ direction:{ type:String, default:'horizontal', validator(value){ // 返回true则验证通过 return [ 'horizontal', 'vertical' ].indexOf(value)>-1; } }, interval:{//自动轮播 type:Number, default:3000, validator(value){ return value>=0; } }, loop:{//无缝滚动 type:Boolean, default:true }, pagination:{//分液器 type:Boolean, default:true }, data:{ type:Array, default(){ return []; } } }, data(){ return{ keyId:Math.random(), } }, watch:{ data(newData){ if(newData.length===0) return; this.swiperOption.loop=newData.length<=1?false:this.loop;//每次刷新后重新判断是否需要滚动 this.keyId=Math.random(); } }, created(){ this.init(); }, methods:{ init(){ this.swiperOption={ watchOverflow:true,//只有一张图片时不设置滚动效果 direction:this.direction,//滚动方向 autoplay:this.interval?{ delay:this.interval, disableOnInteraction:false//手指滑动时是否停止自动轮播 }:false, slidesPerView:1,//同时显示几张图片 loop:this.data.length<=1?false:this.loop,//是否开启无缝滚动,1张图片不需要滚动 pagination:{//分页器 el:this.pagination?'.swiper-pagination':null } } } } } </script> <style lang="scss" scoped> @import '~assets/scss/mixins'; .swiper-container{ width:100%; height:100%; } </style>
效果图
来源:https://www.cnblogs.com/chenyingying0/p/12635080.html