ScrollView 滚动区域/下拉刷新
用于模拟原生的滚动区域,并支持下拉刷新和加载更多 1.5.0+
引入
import { ScrollView, ScrollViewRefresh, ScrollViewMore } from 'mand-mobile'
Vue.component(ScrollView.name, ScrollView)
使用指南
ScrollViewRefresh
为组件库内置的下拉刷新组件,仅用于作为视觉展示,需在插槽refresh)中使用,下拉刷新组件也可自定义
ScrollViewMore
为组件库内置的加载更多组件,仅用于作为视觉展示,需在插槽more)中使用,加载更多组件也可自定义
代码演示
基础 添加内容
请在移动设备中扫码预览
<template>
<div class="md-example-child md-example-child-scroll-view md-example-child-scroll-view-0">
<md-scroll-view
ref="scrollView"
@scroll="$_onScroll"
>
<div
v-for="i in list"
class="scroll-view-item"
:key="i"
@click="$_onItemClick(i)"
>
{{i}}
</div>
</md-scroll-view>
</div>
</template>
<script>
import {ScrollView, Toast} from 'mand-mobile'
export default {
name: 'scroll-view-demo-0',
components: {
[ScrollView.name]: ScrollView,
},
data() {
return {
list: 5,
}
},
mounted() {
window.ScrollViewTrigger0 = () => {
this.addItems()
}
},
methods: {
$_onItemClick(i) {
Toast.info(`Click ${i}`)
},
$_onScroll({scrollLeft, scrollTop}) {
console.log(`[Mand Mobile ScrollView - demo0 - onScroll] scrollLeft: ${scrollLeft}, scrollTop: ${scrollTop}`)
},
addItems() {
this.list += 5
// 如果把autoReflow设置为false, 需调用reflowScroller
this.$refs.scrollView.reflowScroller()
},
},
}
</script>
<style lang="stylus">
.md-example-child-scroll-view-0
height 400px
.scroll-view-item
padding 30px 0
text-align center
font-size 28px
font-family DINAlternate-Bold
border-bottom .5px solid #efefef
</style>
加载更多
请在移动设备中扫码预览
<template>
<div class="md-example-child md-example-child-scroll-view md-example-child-scroll-view-2">
<md-scroll-view
ref="scrollView"
:scrolling-x="false"
@endReached="$_onEndReached"
>
<div
v-for="i in list"
:key="i"
class="scroll-view-list"
>
<p class="scroll-view-item">{{i}}</p>
</div>
<md-scroll-view-more
slot="more"
:is-finished="isFinished"
>
</md-scroll-view-more>
</md-scroll-view>
</div>
</template>
<script>
import {ScrollView, ScrollViewMore} from 'mand-mobile'
export default {
name: 'scroll-view-demo-2',
components: {
[ScrollView.name]: ScrollView,
[ScrollViewMore.name]: ScrollViewMore,
},
data() {
return {
list: 10,
isFinished: false,
}
},
methods: {
$_onEndReached() {
if (this.isFinished) {
return
}
// async data
setTimeout(() => {
this.list += 5
if (this.list >= 20) {
this.isFinished = true
}
this.$refs.scrollView.finishLoadMore()
}, 1000)
},
},
}
</script>
<style lang="stylus">
.md-example-child-scroll-view-2
height 800px
.scroll-view-item
padding 30px 0
text-align center
font-size 32px
font-family DINAlternate-Bold
border-bottom .5px solid #efefef
</style>
配合TabBar
请在移动设备中扫码预览
<template>
<div class="md-example-child md-example-child-scroll-view md-example-child-scroll-view-4">
<md-scroll-view
ref="scrollView"
:scrolling-x="false"
@scroll="$_onScroll"
>
<md-tab-bar
slot="header"
ref="tabBar"
:default-index="activeBlockIndex - 1"
:titles="tabBarTitles"
:show-ink-bar="true"
:key="activeBlockIndex"
@indexChanged="$_onTabChange"
></md-tab-bar>
<div
v-for="i in category"
:key="i"
class="scroll-view-category"
>
<div
v-for="j in list"
:key="j"
class="scroll-view-list"
>
<p class="scroll-view-item">{{`${i} - ${j}`}}</p>
</div>
</div>
</md-scroll-view>
</div>
</template>
<script>
import {ScrollView, TabBar} from 'mand-mobile'
export default {
name: 'scroll-view-demo-3',
components: {
[ScrollView.name]: ScrollView,
[TabBar.name]: TabBar,
},
data() {
return {
category: 5,
list: 5,
dimensions: [],
scrollY: 0,
isManual: false,
}
},
computed: {
tabBarTitles() {
return this.dimensions.map((item, index) => {
return index + 1
})
},
activeBlockIndex() {
let activeIndex = 1
this.dimensions.forEach((dimension, index) => {
if (this.scrollY >= dimension[0] && this.scrollY <= dimension[1]) {
activeIndex = index + 1
}
})
return activeIndex
},
},
mounted() {
// 如果内容发生变化,需重新初始化block和scroller
this.$_initScrollBlock()
// this.$refs.scrollView.reflowScroller()
},
methods: {
$_initScrollBlock() {
const blocks = this.$el.querySelectorAll('.scroll-view-category')
let offset = 0
Array.prototype.slice.call(blocks).forEach((block, index) => {
const innerHeight = block.clientHeight
this.$set(this.dimensions, index, [offset, offset + innerHeight])
offset += innerHeight
})
},
$_onScroll({scrollTop}) {
if (!this.isManual) {
this.scrollY = scrollTop
}
},
$_onTabChange(index) {
const offsetTop = this.dimensions[index][0]
this.isManual = true
this.$refs.scrollView.scrollTo(0, offsetTop, true)
setTimeout(() => {
this.scrollY = offsetTop
this.isManual = false
}, 500)
},
},
}
</script>
<style lang="stylus">
.md-example-child-scroll-view-4
position relative
height 800px
.md-tab-bar
box-shadow 0 2px 8px #f0f0f0
.scroll-view-container
padding-top 80px
.scroll-view-item
padding 30px 0
text-align center
font-size 32px
border-bottom .5px solid #efefef
</style>
下拉刷新 触发下拉刷新
请在移动设备中扫码预览
<template>
<div class="md-example-child md-example-child-scroll-view md-example-child-scroll-view-1">
<md-scroll-view
ref="scrollView"
:scrolling-x="false"
@refreshing="$_onRefresh"
>
<md-scroll-view-refresh
slot="refresh"
slot-scope="{ scrollTop, isRefreshActive, isRefreshing }"
:scroll-top="scrollTop"
:is-refreshing="isRefreshing"
:is-refresh-active="isRefreshActive"
></md-scroll-view-refresh>
<div
v-for="i in list"
:key="i"
class="scroll-view-list"
>
<p class="scroll-view-item">{{i}}</p>
</div>
</md-scroll-view>
</div>
</template>
<script>
import {ScrollView, ScrollViewRefresh} from 'mand-mobile'
export default {
name: 'scroll-view-demo-0',
components: {
[ScrollView.name]: ScrollView,
[ScrollViewRefresh.name]: ScrollViewRefresh,
},
data() {
return {
list: 5,
}
},
mounted() {
window.ScrollViewTrigger1 = () => {
this.$refs.scrollView.triggerRefresh()
}
},
methods: {
$_onRefresh() {
// async data
setTimeout(() => {
this.list += 5
this.$refs.scrollView.finishRefresh()
}, 2000)
},
},
}
</script>
<style lang="stylus">
.md-example-child-scroll-view-1
height 800px
.scroll-view-item
padding 30px 0
text-align center
font-size 28px
font-family DINAlternate-Bold
border-bottom .5px solid #efefef
</style>
粘性标题
请在移动设备中扫码预览
<template>
<div class="md-example-child md-example-child-scroll-view md-example-child-scroll-view-3">
<md-scroll-view
ref="scrollView"
:scrolling-x="false"
@scroll="$_onScroll"
>
<div
v-for="i in category"
:key="i"
class="scroll-view-category"
>
<p class="scroll-view-category-title">{{ i }}</p>
<div
v-for="j in list"
:key="j"
class="scroll-view-list"
>
<p class="scroll-view-item">{{`${i} - ${j}`}}</p>
</div>
</div>
</md-scroll-view>
<p v-if="activeBlockIndex > 0" class="scroll-view-striky-title">{{ activeBlockIndex }}</p>
</div>
</template>
<script>
import {ScrollView} from 'mand-mobile'
export default {
name: 'scroll-view-demo-3',
components: {
[ScrollView.name]: ScrollView,
},
data() {
return {
category: 5,
list: 5,
dimensions: [],
scrollY: 0,
}
},
computed: {
activeBlockIndex() {
let activeIndex = -1
this.dimensions.forEach((dimension, index) => {
if (this.scrollY >= dimension[0] && this.scrollY <= dimension[1]) {
activeIndex = index + 1
}
})
return activeIndex
},
},
mounted() {
// 如果内容发生变化,需重新初始化block和scroller
this.$_initScrollBlock()
// this.$refs.scrollView.reflowScroller()
},
methods: {
$_initScrollBlock() {
const blocks = this.$el.querySelectorAll('.scroll-view-category')
let offset = 0
Array.prototype.slice.call(blocks).forEach((block, index) => {
const innerHeight = block.clientHeight
this.$set(this.dimensions, index, [offset, offset + innerHeight])
offset += innerHeight
})
},
$_onScroll({scrollTop}) {
this.scrollY = scrollTop
},
},
}
</script>
<style lang="stylus">
.md-example-child-scroll-view-3
position relative
height 800px
.scroll-view-striky-title
position absolute
top 0
left 0
right 0
.scroll-view-category-title, .scroll-view-striky-title
padding 10px 0
text-align center
font-size 32px
font-family DINAlternate-Bold
background-color #f0f0f0
.scroll-view-item
padding 30px 0
text-align center
font-size 32px
border-bottom .5px solid #efefef
</style>
API
ScrollView Props
属性 | 说明 | 类型 | 默认值 | 备注 |
---|---|---|---|---|
scrolling-x | 水平滚动 | Boolean | true | - |
scrolling-y | 垂直滚动 | Boolean | true | - |
bouncing | 可回弹 | Boolean | true | - |
autoReflow 1.5.3+ | 内容发生变化时自动重置滚动区域尺寸 | Boolean | false | 当设置为false 时,内容发生变化需手动调用reflowScroller |
endReachedThreshold | 触发到达底部的提前量 | Number | 0 | 单位px |
ScrollViewRefresh Props
属性 | 说明 | 类型 | 默认值 | 备注 |
---|---|---|---|---|
scroll-top | 距离顶部距离 | Number | 0 | 单位px |
is-refresh-active | 释放可刷新状态 | Boolean | false | - |
is-refreshing | 刷新中状态 | Boolean | false | - |
refresh-text | 待刷新文案 | String | 下拉刷新 | - |
refresh-active-text | 释放可刷新文案 | String | 释放刷新 | - |
refreshing-text | 刷新中文案 | String | 刷新中… | - |
ScrollViewMore Props
属性 | 说明 | 类型 | 默认值 | 备注 |
---|---|---|---|---|
is-finished | 全部已加载 | Boolean | false | - |
loading-text | 加载中文案 | String | 更多加载中… | - |
finished-text | 全部已加载文案 | String | 全部已加载 | - |
ScrollView Slots
default
滚动区域内容插槽,当内容发生变化是,需要调用reflowScroller
重置滚动区域,参考reflowScroller)
refresh
下拉刷新组件插槽,可如下使用slot-scoped
获取相关滚动状态(不兼容slot-scoped
时滚动状态也可通过事件中动态设置)
<md-scroll-view-refresh
slot="refresh"
slot-scope="{ scrollTop, isRefreshActive, isRefreshing }"
:scroll-top="scrollTop"
:is-refreshing="isRefreshing"
:is-refresh-active="isRefreshActive"
></md-scroll-view-refresh>
more
加载更多组件插槽
header
吸顶区域插槽
footer
吸底区域插槽
ScrollView Methods
reflowScroller()
重置滚动区域,一般滚动区域中的内容发生变化之后需调用
scrollTo(left, top, animate = false)
滚动至指定位置
参数 | 说明 | 类型 |
---|---|---|
left | 距左侧距离 | Number |
top | 距顶部距离 | Number |
animate | 使用动画 | Boolean |
triggerRefresh()
触发下拉刷新
finishRefresh()
停止下拉刷新
finishLoadMore()
停止加载更多
ScrollView Events
@scroll({scrollLeft, scrollTop})
滚动事件
属性 | 说明 | 类型 |
---|---|---|
scrollLeft | 距左侧距离 | Number |
scrollTop | 距顶部距离 | Number |
@refreshActive()
释放可刷新事件
@refreshing()
刷新中事件
@endReached()
滚动触底事件