vivo-ui
Version:
vivo ui component lib for vue
267 lines (239 loc) • 8.35 kB
Markdown
# load-more 加载更多
> load-more是一个加载更多组件,支持拉动加载和滚动加载。**(v0.0.15中新增,由之前的refresh组件修改过来)**
[下拉加载demo](demo/components/load-more/pull-down.html ':ignore')
[上划加载demo](demo/components/load-more/scroll-up.html ':ignore')
## 使用方法
```
<template>
<div>
上划加载
<load-more class="load-more" :pull="false" :duration="duration" direction="top"
@appear="appear" @load="load">
<div slot="loading" class="loading" :style="loadingStyle">
<span class="icon" v-show="['init','loading'].includes(status)"></span>
<span class="text">{{text}}</span>
</div>
<div class="content">
<div v-for="(value,index) in list" :key="index">{{value}}</div>
</div>
</load-more>
</div>
</template>
<style>
.load-more {
height: 400px;
border: 1px solid;
}
.loading {
font-size: 0;
line-height: 1rem;
text-align: center;
}
.loading .icon {
display: inline-block;
vertical-align: middle;
margin-right: .2rem;
width: .7rem;
height: .7rem;
background: center no-repeat url(./loading.gif);
background-size: contain;
}
.loading .text {
vertical-align: middle;
color: #d37123;
font-size: .5rem;
}
.content {
background: grey;
}
</style>
<script>
import {LoadMore} from 'vivo-ui'
export default {
components: {
LoadMore
},
data() {
return {
duration: 400,
text: '正在加载',
status: 'init', // 状态,包含init、loading、complete三种
work: true,
list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
}
},
computed: {
loadingStyle() {
return {
transitionDuration: `${this.status === 'init' ? this.duration : 0}ms`
}
}
},
methods: {
appear() { // 手指松开
this.status = 'init'
this.text = '正在加载'
},
load(callback){
if (this.work) {
this.status = 'loading'
setTimeout(function () {
const length = this.list.length
this.status = 'complete'
this.text = '加载完成'
this.list.push(length + 1, length + 2, length + 3)
this.list.push(length + 1, length + 2, length + 3)
this.list.length > 40 && (this.work = false)
callback()
}.bind(this), 2000)
} else {
this.status = 'complete'
this.text = '没有更多内容了~'
setTimeout(callback, 1000)
}
}
}
}
</script>
```
```
<template>
<div>
下拉加载
<load-more class="load-more" :pull="true" :duration="duration" direction="top"
@change="change" @release="release" @load="load">
<div slot="loading" class="loading" :style="loadingStyle">
<span class="icon" :style="iconStyle" v-show="['init','loading'].includes(status)"></span>
<span class="text">{{text}}</span>
</div>
<div class="content">
<div v-for="(value,index) in list" :key="index">{{value}}</div>
</div>
</load-more>
</div>
</template>
<style>
.load-more {
height: 400px;
border: 1px solid;
}
.loading {
font-size: 0;
line-height: 1rem;
text-align: center;
}
.loading .icon {
display: inline-block;
vertical-align: middle;
margin-right: .2rem;
width: .7rem;
height: .7rem;
background: center no-repeat;
background-size: contain;
}
.loading .text {
vertical-align: middle;
color: #d37123;
font-size: .5rem;
}
.content {
background: grey;
}
</style>
<script>
import {LoadMore} from 'vivo-ui'
export default {
components: {
LoadMore
},
data() {
return {
duration: 500, // 必须保证loading的transitionDuration与duration属性一致
text: '下拉加载',
status: 'init', // 状态,包含init、loading、complete三种
isPulling: false, // 是否正在pull
progress: 0, // pull距离百分比
work: true,
list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
}
},
computed: {
loadingStyle() {
return {
transform: this.status === 'init' ? `scale(${Math.min(this.progress / 100, 1)})` : '',
transitionDuration: `${this.status === 'init' && !this.isPulling ? this.duration : 0}ms`
}
},
iconStyle(){
return {
transform: this.status === 'init' ? `rotate(${3.6 * this.progress}deg)` : '',
backgroundImage: (() => {
switch (this.status) {
case 'init':
return `url(${require('./loading.png')})`
case 'loading':
return `url(${require('./loading.gif')})`
}
})(),
transitionDuration: `${this.status === 'init' && !this.isPulling ? this.duration : 0}ms`
}
}
},
methods: {
change(progress) {
this.isPulling = true
this.progress = progress
this.status = 'init'
this.text = progress > 100 ? '松开加载' : '下拉加载'
},
release(progress) { // 手指松开
this.isPulling = false
this.progress = progress >= 100 ? 100 : 0
},
load(callback){
if (this.work) {
this.status = 'loading'
this.text = '正在加载'
setTimeout(function () {
const length = this.list.length
this.list.push(length + 1, length + 2, length + 3)
this.list.push(length + 1, length + 2, length + 3)
this.list.length > 40 && (this.work = false)
this.status = 'complete'
this.text = '加载完成'
this.progress = 0
callback()
}.bind(this), 2000)
} else {
this.progress = 0
this.status = 'complete'
this.text = '没有更多内容了~'
setTimeout(callback, 1000)
}
}
}
}
</script>
```
## 属性
名称|类型|必填|默认值|描述
:-:|:-:|:-:|:-:|:-:
direction|`String`|`N`|`top`|加载loading元素所在的位置,支持`top`,`bottom`,`left`,`right`
pull|`Boolean`|`N`|`true`|是pull加载还是scroll加载,true表示pull
work|`Boolean`|`N`|`true`|是否还需要加载,false表示不再需要加载了,此时loading元素将不再显示。不过可以设置work为true,然后控制loading逻辑来实现自定义效果,如demo中那样
duration|`Number`|`N`|`400`|loading元素的过渡时间
pullThreshold|`Number`|`N`|`100`|为pull模式时,触发加载动作的拉动距离,单位px,scroll模式无效。**在移动端注意要根据不同设备像素比设置不同阈值,否则用户感知的拉动距离不一致**
scrollThreshold|`Number`|`N`|`0`|为scroll模式时,触发加载动作的阈值,单位px,pull模式无效 **(如scrollThreshold为50,则表示距离滚动到末尾还差50px时就触发加载动作,常用来进行预加载).在移动端注意要根据不同设备像素比设置不同阈值)**
angle|`Number`|`N`|`45`|pull或者scroll有效的角度,比如direction为top或者bottom,angle为30,则表示手指初始滑动的方向与垂直方向的夹角要<=30度,否则无法pull或者scroll
## 插槽
名称|必填|说明
:-:|:-:|:-:
默认|`Y`|内容区域
loading|`N`|loading元素区域
## 事件
名称|参数|说明
:-:|:-:|:-:
change|`{progress}`|pull模式才有效,手指pull时触发,progress表示相对于pullThreshold拉动的距离百分比
release|`{progress}`|pull模式才有效,手指pull松开时触发,progress表示相对于pullThreshold拉动的距离百分比
appear|`-`|scroll模式才有效,当loading元素出现时触发
load|`{callback}`|触发加载动作时触发,**当数据更新完成后一定要执行回调函数,否则loading元素不会隐藏,且无法再次触发加载**