uni-app 实现 fullpage 组件(适用于微信小程序,h5 等)

纯业务需求

本文github 源码地址

1.组件 src/components/FullPage/index.vue

1
<template>
2
  <view class="full-page-container">
3
    <view
4
      class="full-page-main"
5
      @touchstart="handleTouchStart"
6
      @touchmove="handleTouchMove"
7
      @touchend="handleTouchEnd"
8
      :style="style"
9
    >
10
      <slot />
11
    </view>
12
  </view>
13
</template>
14
15
<script>
16
  export default {
17
    name: 'FullPage',
18
    props: {
19
      // 触发翻页的临界值
20
      critical: {
21
        type: Number,
22
        default: 50,
23
      },
24
      // 总共页面数
25
      totalPage: {
26
        type: Number,
27
        required: true,
28
        default: 0,
29
      },
30
      // 当前页面的索引值
31
      activeIndex: {
32
        type: Number,
33
        required: true,
34
        default: 0,
35
      },
36
    },
37
    data() {
38
      return {
39
        pageIndex: 0, // 当前页面的索引值
40
        startPageY: 0, // 开始的位置
41
        endPageY: 0, // 结束的位置
42
        marginTop: 0, // 滑动下拉(上拉)距离
43
      }
44
    },
45
    mounted() {
46
      this.pageIndex = this.activeIndex
47
    },
48
    computed: {
49
      style() {
50
        return `transform:translateY(-${this.pageIndex * 100}%);margin-top:${
51
          this.marginTop
52
        }px`
53
      },
54
    },
55
    watch: {
56
      activeIndex(value) {
57
        this.pageIndex = value
58
      },
59
    },
60
    methods: {
61
      // 开始滑动
62
      handleTouchStart(e) {
63
        const { pageY } = e.touches[0]
64
        this.startPageY = pageY
65
      },
66
      // 滑动中
67
      handleTouchMove(e) {
68
        const { pageY } = e.touches[0]
69
        if (
70
          pageY - this.startPageY < this.critical &&
71
          pageY - this.startPageY > -this.critical
72
        ) {
73
          this.marginTop = pageY - this.startPageY
74
        }
75
        this.endPageY = pageY
76
      },
77
      // 滑动结束
78
      handleTouchEnd() {
79
        if (!this.endPageY) {
80
          return
81
        }
82
        if (
83
          this.endPageY - this.startPageY > this.critical &&
84
          this.pageIndex > 0
85
        ) {
86
          this.pageIndex -= 1
87
        } else if (
88
          this.endPageY - this.startPageY < -this.critical &&
89
          this.pageIndex < this.totalPage - 1
90
        ) {
91
          this.pageIndex += 1
92
        }
93
        this.$emit('update:activeIndex', this.pageIndex)
94
        this.startPageY = 0
95
        this.endPageY = 0
96
        this.marginTop = 0
97
      },
98
    },
99
  }
100
</script>
101
102
<style lang="scss" scoped>
103
  .full-page-container {
104
    height: 100%;
105
    overflow: hidden;
106
    .full-page-main {
107
      height: 100%;
108
      transition: all 0.3s;
109
    }
110
  }
111
</style>

2.使用 /src/pages/index/index.vue

1
<template>
2
  <full-page :active-index.sync="activeIndex" :total-page="totalPage">
3
    <view
4
      class="section"
5
      v-for="(item, index) in totalPage"
6
      :key="index"
7
      :style="getRandomStyle()"
8
    >
9
      <div :class="'page page-' + index">
10
        {{ index + 1 }}
11
        <button type="primary" @click="toPage(1)">
12
          跳转到第1页
13
        </button>
14
        <button type="primary" @click="toPage(10)">
15
          跳转到第10页
16
        </button>
17
      </div>
18
    </view>
19
  </full-page>
20
</template>
21
22
<script>
23
  import FullPage from '@/components/FullPage'
24
  export default {
25
    components: {
26
      FullPage,
27
    },
28
    data() {
29
      return {
30
        totalPage: 10,
31
        activeIndex: 0,
32
      }
33
    },
34
    methods: {
35
      getRandomStyle() {
36
        const r = Math.floor(Math.random() * 256)
37
        const g = Math.floor(Math.random() * 256)
38
        const b = Math.floor(Math.random() * 256)
39
        const color = '#' + r.toString(16) + g.toString(16) + b.toString(16)
40
        return `background-color:${color}`
41
      },
42
      toPage(index) {
43
        this.activeIndex = index - 1
44
      },
45
    },
46
  }
47
</script>
48
<style lang="scss" scoped>
49
  page {
50
    height: 100%;
51
  }
52
  .section {
53
    height: 100%;
54
    width: 100%;
55
    position: relative;
56
  }
57
  .page {
58
    height: 100%;
59
    width: 100%;
60
    text-align: center;
61
    font-size: 50rpx;
62
    padding-top: 150rpx;
63
    box-sizing: border-box;
64
  }
65
  button {
66
    font-size: 30rpx;
67
    width: 400rpx;
68
    margin: 50rpx;
69
  }
70
</style>

3.实现效果
在这里插入图片描述

参考链接

1.https://github.com/rongj/wechatapp-fullpage-scroll