Advantages of this component:

1, use small program/UNIApp native page slide, fluency is higher than scroll view component 2, use component directly, 3, including no data spatio-temporal layout display 4, can customize the drop-down refresh, drop-down loading style 5, the two-way binding of components V-Model 6, perfect solution to the custom navigation can not see the drop-down refresh loading problem

Actual renderings



We turned it on in page.jsonCustom navigation barProperties andThe drop-down refreshAfter the attributes

// Enable pull-down refresh
"enablePullDownRefresh": true
// Customize the navigation bar
"navigationStyle": "custom"
Copy the code

At this point, the three dots in the drop-down refresh of the page will be covered by our navigation bar, so that users cannot see the loading effect in the drop-down refresh, as shown in the following figure

So the user experience is not good. Let’s see how to solve this problem:

1. Encapsulate the MScroll component

2. Encapsulate componentsThe drop-down refresh,Pull on loading,When loading is completemethods

3, the use ofmargin-top: -100upx;Hide the loading we wrote before the user pulls down the refresh

Encapsulates the MScroll component

<template>
  <div class="mscroll">
    <! -- Drop down to refresh -->
    <div class="loading pullLoading">
      <i class="dot"></i>
    </div>
    <! -- Content slot -->
    <slot/>
    <! -- Pull load -->
    <div v-if="hasNextPage" class="loading">
      <i class="dot"></i>
    </div>
    <! -- Empty layout -->
    <div class="empty" v-if='isEmpty'>
      <! -- Change the picture yourself -->
      <img mode='widthFix' src=".. /.. /assets/image/logoPng.png" alt="">
      <p>There is nothing here ~</p>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: Object.required: true.default () {
        return {
          // Current page number
          page: 1.// Number of entries per page
          pageSize: 10.// Is there a next page
          hasNextPage: false.// Total number of data
          total: 0
        }
      }
    }
  },
  data () {
    return {
      / / the next page
      hasNextPage: false./ / no data
      isEmpty: false./ / load
      isLoading: false}},computed: {
    // Convert pages
    pages () {
      return this.value
    }
  },
  methods: {
    // Drop refresh
    pullRefresh () {
      / / load
      this.isLoading = true
      this.$emit('input', {... this.pages,page: 1})
      this.$emit('getData')},// Pull up load
    loadMore () {
      // There is no next page or loading is not loaded
      if (!this.hasNextPage || this.isLoading) return
      / / load
      this.isLoading = true
      this.$emit('input', {... this.pages,page: this.pages.page + 1})
      this.$emit('getData')},// Successfully loaded method
    loadSuccess (data) {
      // The first page should go back to the top
      if (data.page == 1) {
        uni.pageScrollTo({
          scrollTop: 0})}// End of the drop-down refresh
      uni.stopPullDownRefresh()
      // Close the load
      this.isLoading = false
      // Whether there is a next page (can be determined by the total number of pages and current page)
      this.hasNextPage = data.hasNextPage
      // Whether there is data
      this.isEmpty = ! data.total } } }</script>

<style lang='scss' scoped>// Load the animation@keyframes dotFlashing {
    0% {
      background-color: #ccc;
    }
    100% {
      background-color: # 999; }}.mscroll{
    // loading
    .loading {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100upx;
      overflow: hidden;
      &.pullLoading{// here is the keymargin-top: -100upx; } // Simulate wechat dot.dot {
        display: inline-block;
        position: relative;
        width: 14upx;
        height: 14upx;
        border-radius: 50%;
        background: # 999;
        animation: dotFlashing 1s infinite linear alternate;
        animation-delay:.5s;
        &::before {
          left: -28upx;
          animation: dotFlashing 1s infinite alternate;
          animation-delay: 0s;
        }
        &::after {
          left: 28upx;
          animation: dotFlashing 1s infinite alternate;
          animation-delay: 1s;
        }
        &::before,
        &::after {
          content: ' ';
          display: inline-block;
          position: absolute;
          top: 0;
          width: 14upx;
          height: 14upx;
          border-radius: 50%;
          background: # 999; }}} // Empty layout.empty{
      margin-top: 280upx;
      text-align: center;
      img{
        width: 180upx;
      }
      p{
        margin-top: 20upx;
        color: # 999;
        font-size: 26upx
      }
    }
  }
</style>
Copy the code

use

Page. Json configuration

"pages": [{"path": "pages/homePage/index"."style": {
      "navigationBarTitleText": "Page title".// Page title
	  "enablePullDownRefresh": true.// Enable drop-down refresh (required)
      "backgroundTextStyle": "light".// Pull down refresh loading small dot color, white background + white small dot can realize "hide" native small dot oh
      "navigationStyle": "custom".// Customize the navigation bar (you can also use this component without customizing the navigation bar, but you can only use the native dot style, you cannot customize the drop-down refresh style)
      "backgroundColor": "#F5F7F9" // Page background color}}]Copy the code

Parent component use

<template> <! Calculate your navigation altitude --><div class='index' :style="{'padding-top': '100px'}">
    <! -- Custom navigation bar -->
    <nav :style="{height: '100px'}"></nav>
    <! Pages = pages -->
    <m-scroll ref='mscroll' v-model="pages" @getData='getData'>
      <! -- List data -->
      <ul>
        <li v-for="i in list" :key="i">Analog data ------------- section {{I + 1}}</li>
      </ul>
    </m-scroll>
  </div>
</template>

<script>
import mScroll from './mscroll'
export default {
  components: {
    mScroll
  },
  data () {
    return {
      list: 20.pages: {
        page: 1.pageSize: 10}}},// Triggers a pull-down refresh
  onPullDownRefresh () {
    this.$refs.mscroll.pullRefresh()
  },
  // Triggers pull-up loading
  onReachBottom () {
    this.$refs.mscroll.loadMore()
  },
  onLoad () {
    this.getData()
  },
  methods: {
    getData () {
      // simulate the request
      setTimeout(() = > {
        this.list += 10
        const total = 50
        consthasNextPage = total ! =this.list
        const data = {
          page: this.pages.page, // Page number must be included
          total, // The total number must be included
          hasNextPage // The next page must be included
        }
        // The current page number, total data, and next page are required
        this.$refs.mscroll.loadSuccess(data)
      }, 1000)}}}</script>

<style lang='scss' scoped>// Customize the navigation barnav{
    background: #446AAD;
    position: fixed;
    z-index: 10;
    left: 0;
    top: 0;
    right: 0;
  }
  ul{
    li{
      padding: 20upx;
      border-bottom: 1px solid #eee; }}</style>
Copy the code

At this point, the code is finished, considering or have a bug place, but also hope a lot of messages to inform me 😁!