zoukankan      html  css  js  c++  java
  • vue 组件系列-dataloading

    //  referenced: https://github.com/bedlate/vue-data-loading
    
    <template>
        <div class="vue-data-loading">
            <div class="loading-header" :style="{height: pullHeight + 'px'}" v-show="PULL_DOWN === pull.type">
                <div class="header-text" v-show="!pull.available">
                    <slot :name="PULL_DOWN + '-before'">下拉刷新数据</slot>
                </div>
                <div class="header-text" v-show="pull.available && PULL_DOWN !== loadingType">
                    <slot :name="PULL_DOWN + '-ready'">松开刷新数据</slot>
                </div>
                <div class="header-text" v-show="PULL_DOWN === loadingType">
                    <slot :name="PULL_DOWN + '-loading'">刷新中...</slot>
                </div>
            </div>
    
            <div class="loading-content">
                <slot></slot>
            </div>
    
            <div class="loading-footer" :style="{height: pullHeight + 'px'}" v-show="PULL_UP === pull.type">
                <div class="footer-text" v-show="!pull.available">
                    <slot :name="PULL_UP + '-before'">上拉加载数据</slot>
                </div>
                <div class="footer-text" v-show="pull.available && PULL_UP !== loadingType">
                    <slot :name="PULL_UP + '-ready'">松开加载数据</slot>
                </div>
                <div class="footer-text" v-show="PULL_UP === loadingType">
                    <slot :name="PULL_UP + '-loading'">加载中...</slot>
                </div>
            </div>
    
            <transition name="fade">
              <div class="loading-footer" v-show="loading && INFINITE_SCROLL === loadingType">
                  <div class="footer-text">
                      <slot :name="INFINITE_SCROLL + '-loading'">加载中...</slot>
                  </div>
              </div>
            </transition>
    
            <div class="loading-footer" v-show="!loading && completed">
                <div class="footer-text">
                    <slot name="completed">加载完毕</slot>
                </div>
            </div>
    
        </div>
    </template>
    
    <script>
        export default {
            props: {
                loading: {
                    type: Boolean,
                    default: false
                },
                completed: {
                    type: Boolean,
                    default: false
                },
                distance: {
                    type: Number,
                    default: 60
                },
                offset: {
                    type: Number,
                    default: 0
                },
                listens: {
                    type: Array,
                    default() {
                        return ['infinite-scroll', 'pull-down', 'pull-up']
                    }
                },
                container: {
                    type: String,
                },
                initScroll: {
                    type: Boolean,
                    default: false,
                },
            },
            data() {
                return {
                    margin: {
                        top: 0,
                        bottom: 0,
                    },
                    pull: {
                        from: -1,
                        to: -1,
                        distance: 0,
                        type: null,
                        available: false,
                    },
                    loadingType: null,
    
                    PULL_UP: 'pull-up',
                    PULL_DOWN: 'pull-down',
                    INFINITE_SCROLL: 'infinite-scroll',
                }
            },
            computed: {
                _container() {
                    return this.container ? this.$parent.$refs[this.container] : window.window
                },
                pullHeight() {
                    return this.pull.distance > this.distance ? this.distance : this.pull.distance
                },
            },
            watch: {
                loading(val, oldVal) {
                    if (oldVal && !val) {
                        this.resetPull()
                        this.setLoadingType()
                    }
                }
            },
            methods: {
                updateView() {
                    let {top, height} = this.$el.getBoundingClientRect()
                    this.margin = {
                        top,
                        bottom: window.innerHeight - (height + top + this.offset)
                    }
                },
                setLoadingType(type = null) {
                    this.loadingType = type
                },
                handleScroll() {
                    this.updateView()
                    if (this.loading || this.completed) {
                        return
                    }
                    if (this.margin.bottom >= 0) {
                        this.$emit(this.INFINITE_SCROLL)
                        this.setLoadingType(this.INFINITE_SCROLL)
                    }
                },
                handleTouchStart(e) {
                    if (this.loading || !(this.hasListen(this.PULL_UP) || this.hasListen(this.PULL_DOWN)) || (this.margin.top < 0 && this.margin.bottom < 0)) {
                        return
                    }
    
                    this.pull.from = e.touches.item(0).pageY
                },
                handleTouchMove(e) {
                    if (this.loading || this.pull.from < 0) {
                        return
                    }
                    this.pull.to = e.touches.item(0).pageY
                    let distance = this.pull.to - this.pull.from
    
                    if (distance > 0 && this.margin.top >0 && this.hasListen(this.PULL_DOWN)) {   // pull down
                        this.pull.type = this.PULL_DOWN
                    } else if (distance < 0 && this.margin.bottom > 0 && this.hasListen(this.PULL_UP)) {    // pull up
                        this.pull.type = this.PULL_UP
                    } else {
                        this.pull.type = null
                    }
    
                    this.pull.distance = Math.abs(distance)
                    this.pull.available = this.pull.distance >= this.distance
                },
                handleTouchEnd() {
                    if (this.pull.distance >= this.distance) {
                        if (this.PULL_UP === this.pull.type || this.PULL_DOWN === this.pull.type) {
                            this.$emit(this.pull.type)
                            this.setLoadingType(this.pull.type)
                        }
                    } else {
                        this.resetPull()
                    }
                },
                resetPull() {
                    this.pull = {
                        from: -1,
                        to: -1,
                        distance: 0,
                        type: null,
                        available: false,
                    }
                },
                bindEvents() {
                    // scroll
                    if (this.hasListen(this.INFINITE_SCROLL)) {
                        ['scroll', 'resize'].forEach(e => {
                            this._container.addEventListener(e, this.handleScroll)
                        })
                    }
    
                    // touch
                    if (this.hasListen(this.PULL_UP) || this.hasListen(this.PULL_DOWN)) {
                        this._container.addEventListener('touchstart', this.handleTouchStart)
                        this._container.addEventListener('touchmove', this.handleTouchMove)
                        this._container.addEventListener('touchend', this.handleTouchEnd)
                    }
                },
                hasListen(event) {
                    return this.listens.indexOf(event) >= 0
                },
                init() {
                    this.bindEvents()
                    this.updateView()
                    if (this.initScroll) {
                        this.handleScroll()
                    }
                },
            },
            mounted() {
                this.$nextTick(() => {
                    this.init()
                })
            },
        }
    </script>
  • 相关阅读:
    leetcode -- Word Break
    [笔试题]MS 2014
    网络编程之TCP/IP各层详解
    深浅copy
    字符编码的转换
    Bytes类型
    Django之模型层(1)
    Django之模板层
    用Python操作文件
    hash(哈希)是什么
  • 原文地址:https://www.cnblogs.com/sybboy/p/12259907.html
Copyright © 2011-2022 走看看