[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中实现), 其他的都是边角的兼容问题
本想把生活活成一首诗, 时而优雅 , 时而豪放 , 结果活成了一首歌 , 时而不靠谱 , 时而不着调