pageing.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // 下拉刷新 mixin
  2. export default {
  3. data() {
  4. return {
  5. // 触摸相关状态
  6. startY: 0,
  7. startTime: 0,
  8. isDragging: false,
  9. lastMoveY: 0,
  10. dragDistance: 0,
  11. velocity: 0,
  12. isTouchStarted: false,
  13. }
  14. },
  15. methods: {
  16. // 触摸开始
  17. touchStartHandler(e) {
  18. if (!this.refresherEnabled) return;
  19. const touch = e.touches[0];
  20. // 重置状态
  21. this.startY = touch.pageY;
  22. this.startTime = Date.now();
  23. this.isDragging = false;
  24. this.dragDistance = 0;
  25. this.velocity = 0;
  26. this.lastMoveY = touch.pageY;
  27. this.isTouchStarted = true;
  28. if (this.curReadyRefresh && this.refreshStatus !== 3) {
  29. this.updateContainerStyle('translateY(0px)', '0s');
  30. }
  31. },
  32. // 触摸移动
  33. touchMoveHandler(e) {
  34. if (!this.isTouchStarted || !this.refresherEnabled ||
  35. !this.curReadyRefresh || this.refreshStatus === 3) return;
  36. const touch = e.touches[0];
  37. const currentY = touch.pageY;
  38. const diffY = currentY - this.startY;
  39. if (diffY <= 0) return;
  40. // 计算拖拽距离和速度
  41. this.dragDistance = diffY;
  42. this.velocity = (currentY - this.lastMoveY) / (Date.now() - this.startTime);
  43. this.lastMoveY = currentY;
  44. this.isDragging = true;
  45. // 应用阻力效果
  46. const resistedDistance = this.calculateResistance(diffY, 150);
  47. const displayDistance = resistedDistance * 0.6;
  48. // 更新状态
  49. if (displayDistance > 10) {
  50. if (!this.readyRefresh) {
  51. this.setReadyRefresh({ readyRefresh: true });
  52. this.readyRefresh = true;
  53. }
  54. if (!this.refreshShow) {
  55. this.setRefreshShow({ refreshShow: true });
  56. this.refreshShow = true;
  57. }
  58. }
  59. // 设置变换
  60. this.updateContainerStyle('translateY(' + displayDistance + 'px)', '0s');
  61. // 更新刷新状态
  62. const newStatus = displayDistance >= this.refresherThreshold ? 2 : 1;
  63. if (this.refreshStatus !== newStatus) {
  64. this.setRefreshStatus(newStatus);
  65. }
  66. },
  67. // 触摸结束
  68. touchEndHandler(e) {
  69. if (!this.refresherEnabled || !this.curReadyRefresh || !this.isDragging) return;
  70. // 重置拖拽状态
  71. this.isDragging = false;
  72. this.setReadyRefresh({ readyRefresh: false });
  73. this.readyRefresh = false;
  74. // 判断是否应该刷新
  75. const shouldRefresh = this.refreshStatus === 2 ||
  76. (Math.abs(this.velocity) > 0.5 && this.dragDistance > 10);
  77. if (shouldRefresh) {
  78. // 触发刷新
  79. this.setRefreshStatus(3);
  80. // 动画到刷新位置
  81. this.updateContainerStyle('translateY(' + this.refresherThreshold + 'px)', '0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94)');
  82. } else {
  83. // 回弹动画
  84. this.updateContainerStyle('translateY(0px)', '0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94)');
  85. // 隐藏刷新指示器
  86. this.setRefreshShow({ refreshShow: false });
  87. this.refreshShow = false;
  88. }
  89. // 重置拖拽相关状态
  90. this.dragDistance = 0;
  91. this.velocity = 0;
  92. this.isTouchStarted = false;
  93. },
  94. // 更新容器样式
  95. updateContainerStyle(transform, transition) {
  96. const container = this.$refs['refresh-container'];
  97. if (container) {
  98. container.style.transform = transform;
  99. container.style.transition = transition;
  100. }
  101. },
  102. // 计算阻力效果
  103. calculateResistance(distance, maxDistance) {
  104. if (distance <= maxDistance) {
  105. return distance;
  106. }
  107. return maxDistance + (distance - maxDistance) * 0.6;
  108. },
  109. // 重置拖拽状态
  110. resetDragState() {
  111. this.refreshShow = false;
  112. this.readyRefresh = false;
  113. this.isDragging = false;
  114. this.dragDistance = 0;
  115. this.velocity = 0;
  116. this.isTouchStarted = false;
  117. },
  118. // 重置容器位置
  119. resetContainerPosition(useEasing = true) {
  120. const transition = useEasing ? '0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94)' : '0.3s ease-out';
  121. this.updateContainerStyle('translateY(0px)', transition);
  122. }
  123. }
  124. };