[vue] 在vue中手动实现下拉刷新功能

1. 下拉刷新组件

<template>
  <div
    class="box"
    ref="boxRef"
    @touchstart="touchstart"
    @touchmove="touchmove"
    @touchend="touchend"
    :style="style"
  >
    <slot />
  </div>
</template>

<script setup>
const state = reactive({
  isPulldown: false,
  startY: 0,
  move: 0,
  style: {
    transform: "translateY(0px)",
    transition: "none",
  },
});
const { style } = toRefs(state);

const boxRef = ref();
function touchstart(ev) {
  state.style.transition = "none";
  const isPulldown = boxRef.value.parentElement.scrollTop === 0;
  state.isPulldown = isPulldown;
  if (isPulldown) {
    state.startY = ev.targetTouches[0].screenY;
  }
}

function touchmove(ev) {
  if (!state.isPulldown) return;
  const y = ev.targetTouches[0].screenY;
  let move = y - state.startY;
  move = move > 80 ? 80 : move;
  if (move > 0) {
    state.move = move;
    state.style = {
      transform: `translateY(${move}px)`,
    };
  }
}

function touchend(ev) {
  if (!state.isPulldown) return;
  if (state.move > 60) {
    console.log("刷新数据");
  }
  if (state.move > 0) {
    state.style.transition = "0.3s";
    state.style.transform = "translateY(0px)";
    state.move = 0;
  }
}
</script>

<style lang="scss" scoped>
.box {
  &::before {
    content: "松开刷新";
    position: absolute;
    top: -80px;
    left: 0;
    height: 80px;
    width: 100%;
    z-index: 1;
    background: gray;
    color: red;
    font-size: 16px;
    text-align: center;
    line-height: 80px;
  }
}
</style>

2. 调用组件的login页面, 测试随便命名的

<template>
  <div class="container">
    <pulldown_refresh>
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
      <div class="item">4</div>
      <div class="item">5</div>
      <div class="item">6</div>
      <div class="item">7</div>
      <div class="item">8</div>
      <div class="item">9</div>
      <div class="item">10</div>
      <div class="item">11</div>
      <div class="item">12</div>
      <div class="item">13</div>
      <div class="item">14</div>
      <div class="item">15</div>
      <div class="item">16</div>
      <div class="item">17</div>
      <div class="item">18</div>
      <div class="item">19</div>
      <div class="item">20</div>
    </pulldown_refresh>
  </div>
</template>

<script setup>
import pulldown_refresh from "@/components/pulldown_refresh.vue";
</script>

<style lang="scss" scoped>
.container {
  // height: 100vh;
  // overflow-y: scroll;
}

@for $i from 1 through 20 {
  .item:nth-child(#{$i}) {
    height: 100px;
    background-color: rgb(random(255), random(255), random(255));
  }
}
</style>

 

原理就是监听移动端的滑动事件,关闭过渡效果,  判断用户滑动的距离, 然后通过transform Y轴移动

用户松开手指的时候, 开启过渡效果, 让transform的值归零, 如果滑动距离足够, 就触发 父组件 的刷新事件(打印,未在demo中实现), 其他的都是边角的兼容问题

 

posted @ 2024-10-16 17:09  深海里的星星i  阅读(54)  评论(0编辑  收藏  举报