123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- <template>
- <div ref="wrapper" class="list-wrapper">
- <div class="scroll-content">
- <div ref="listWrapper">
- <slot></slot>
- </div>
- <slot name="pullup" v-if="isloading" :pullUpLoad="pullUpLoad" :isPullUpLoad="isPullUpLoad">
- <div class="pullup-wrapper" v-if="pullUpLoad">
- <div class="before-trigger" v-if="!isPullUpLoad">
- <span>{{pullUpTxt}}</span>
- </div>
- <div class="after-trigger" v-else>
- <loading></loading>
- </div>
- </div>
- </slot>
- </div>
- <slot name="pulldown" :pullDownRefresh="pullDownRefresh" :pullDownStyle="pullDownStyle" :beforePullDown="beforePullDown" :isPullingDown="isPullingDown" :bubbleY="bubbleY" >
- <div ref="pulldown" class="pulldown-wrapper" :style="pullDownStyle" v-if="pullDownRefresh">
- <div class="before-trigger" v-if="beforePullDown">
- <bubble :y="bubbleY"></bubble>
- </div>
- <div class="after-trigger" v-else>
- <div v-if="isPullingDown" class="loading">
- <loading></loading>
- </div>
- <div v-else>
- <span>{{refreshTxt}}</span>
- </div>
- </div>
- </div>
- </slot>
- </div>
- </template>
- <script type="text/ecmascript-6">
- import BScroll from 'better-scroll'
- import Loading from '../loading/loading.vue'
- import Bubble from '../bubble/bubble.vue'
- import Dom from '../../util/dom'
- const COMPONENT_NAME = 'scroll'
- const DIRECTION_H = 'horizontal'
- const DIRECTION_V = 'vertical'
-
- export default {
- name: COMPONENT_NAME,
- props: {
- data: {
- type: Array,
- default: function () {
- return []
- }
- },
- probeType: {
- type: Number,
- default: 1
- },
- click: {
- type: Boolean,
- default: true
- },
- listenScroll: {
- type: Boolean,
- default: false
- },
- listenBeforeScroll: {
- type: Boolean,
- default: false
- },
- direction: {
- type: String,
- default: DIRECTION_V
- },
- scrollbar: {
- type: null,
- default: false
- },
- pullDownRefresh: {
- type: null,
- default: false
- },
- pullUpLoad: {
- type: null,
- default: false
- },
- startY: {
- type: Number,
- default: 0
- },
- refreshDelay: {
- type: Number,
- default: 20
- },
- freeScroll: {
- type: Boolean,
- default: false
- },
- mouseWheel: {
- type: Boolean,
- default: false
- },
- bounce: {
- default: false
- },
- isloading: {
- type: Boolean,
- default: false
- }
- },
- data () {
- return {
- beforePullDown: true,
- isRebounding: false,
- isPullingDown: false,
- isPullUpLoad: false,
- pullUpDirty: true,
- pullDownStyle: '',
- bubbleY: 0
- }
- },
- computed: {
- pullUpTxt () {
- const moreTxt = '--- 上拉更多 ---'
-
- const noMoreTxt = '--- 我也是有底线的 ---'
-
- return this.pullUpDirty ? moreTxt : noMoreTxt
- },
- refreshTxt () {
- return this.pullDownRefresh && (this.pullDownRefresh.txt || '已刷新')
- }
- },
- created () {
- this.pullDownInitTop = -50
- },
- mounted () {
- this.$nextTick(() => {
- this.initScroll()
- })
- },
- methods: {
- initScroll () {
- if (!this.$refs.wrapper) {
- return
- }
- if (this.$refs.listWrapper && (this.pullDownRefresh || this.pullUpLoad)) {
- this.$refs.listWrapper.style.minHeight = `${Dom.getRect(this.$refs.wrapper).height + 1}px`
- }
-
- let options = {
- probeType: this.probeType,
- click: this.click,
- scrollY: this.freeScroll || this.direction === DIRECTION_V,
- scrollX: this.freeScroll || this.direction === DIRECTION_H,
- scrollbar: this.scrollbar,
- pullDownRefresh: this.pullDownRefresh,
- pullUpLoad: this.pullUpLoad,
- startY: this.startY,
- freeScroll: this.freeScroll,
- mouseWheel: this.mouseWheel,
- bounce: this.bounce
- }
-
- this.scroll = new BScroll(this.$refs.wrapper, options)
-
- if (this.listenScroll) {
- this.scroll.on('scroll', (pos) => {
- this.$emit('scroll', pos)
- })
- }
-
- if (this.listenBeforeScroll) {
- this.scroll.on('beforeScrollStart', () => {
- this.$emit('beforeScrollStart')
- })
- }
-
- if (this.pullDownRefresh) {
- this._initPullDownRefresh()
- }
-
- if (this.pullUpLoad) {
- this._initPullUpLoad()
- }
- },
- disable () {
- this.scroll && this.scroll.disable()
- },
- enable () {
- this.scroll && this.scroll.enable()
- },
- refresh () {
- this.scroll && this.scroll.refresh()
- },
- scrollTo () {
- this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments)
- },
- scrollToElement () {
- this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments)
- },
- clickItem (e, item) {
- this.$emit('click', item)
- },
- destroy () {
- this.scroll.destroy()
- },
- forceUpdate (dirty) {
- if (this.pullDownRefresh && this.isPullingDown) {
- this.isPullingDown = false
- this._reboundPullDown().then(() => {
- this._afterPullDown()
- })
- } else if (this.pullUpLoad && this.isPullUpLoad) {
- this.isPullUpLoad = false
- this.scroll.finishPullUp()
- this.pullUpDirty = dirty
- this.refresh()
- } else {
- this.refresh()
- }
- },
- _initPullDownRefresh () {
- this.scroll.on('pullingDown', () => {
- this.beforePullDown = false
- this.isPullingDown = true
- this.$emit('pullingDown')
- })
-
- this.scroll.on('scroll', (pos) => {
- if (!this.pullDownRefresh) {
- return
- }
- if (this.beforePullDown) {
- this.bubbleY = Math.max(0, pos.y + this.pullDownInitTop)
- this.pullDownStyle = `top:${Math.min(pos.y + this.pullDownInitTop, 10)}px`
- } else {
- this.bubbleY = 0
- }
-
- if (this.isRebounding) {
- this.pullDownStyle = `top:${10 - (this.pullDownRefresh.stop - pos.y)}px`
- }
- })
- },
- _initPullUpLoad () {
- this.scroll.on('pullingUp', () => {
- this.isPullUpLoad = true
- this.$emit('pullingUp')
- })
- },
- _reboundPullDown () {
- const { stopTime = 600 } = this.pullDownRefresh
- return new Promise((resolve) => {
- setTimeout(() => {
- this.isRebounding = true
- this.scroll.finishPullDown()
- resolve()
- }, stopTime)
- })
- },
- _afterPullDown () {
- setTimeout(() => {
- this.pullDownStyle = `top:${this.pullDownInitTop}px`
- this.beforePullDown = true
- this.isRebounding = false
- this.refresh()
- }, this.scroll.options.bounceTime)
- }
- },
- watch: {
- data () {
- setTimeout(() => {
- this.forceUpdate(true)
- }, this.refreshDelay)
- }
- },
- components: {
- Loading,
- Bubble
- }
- }
-
- </script>
-
- <style lang="scss" scoped>
- .list-wrapper {
- position: relative;
- height: 100%;
- overflow: hidden;
- background: #fff;
- }
-
- .scroll-content {
- position: relative;
- z-index: 1;
- }
-
- .list-content {
- position: relative;
- z-index: 10;
- background: #fff;
- }
-
- .pulldown-wrapper {
- position: absolute;
- width: 100%;
- left: 0;
- display: flex;
- justify-content: center;
- align-items: center;
- transition: all;
- }
-
- .after-trigger {
- margin-top: 10px;
- }
-
- .pullup-wrapper {
- width: 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- padding-bottom: 10px;
- }
- </style>
|