如何检测拉动刷新

How to detect Pull to refresh

有很多 "pull to refresh" 插件。我已经测试了其中的 5 个。但是 none 其中 运行 速度很快(尤其是在旧智能手机上)。

检查拉动刷新的最佳(糟糕的用户体验性能和响应能力)方法是什么?

PS: 我不需要任何动画。我只想知道用户是否 "pull to refresh"

性能需要最少的代码

插件和库必须写得尽可能灵活和通用,以解决许多相关问题。这意味着它们总是比您需要的体积大,从而影响性能。这也意味着您永远不必维护该代码。这就是权衡。

如果性能是您的目标,请自行构建。

由于您只需要下拉检测,因此构建一个简单的滑动检测器。 当然,您必须根据自己的需要、OS 的事件属性、事件触发器和您所定位的浏览器进行调整。

从我的旧 js-minimal-swipe-detect

简化而来
var pStart = { x: 0, y: 0 };
var pStop = { x: 0, y: 0 };

function swipeStart(e) {
  if (typeof e["targetTouches"] !== "undefined") {
    var touch = e.targetTouches[0];
    pStart.x = touch.screenX;
    pStart.y = touch.screenY;
  } else {
    pStart.x = e.screenX;
    pStart.y = e.screenY;
  }
}

function swipeEnd(e) {
  if (typeof e["changedTouches"] !== "undefined") {
    var touch = e.changedTouches[0];
    pStop.x = touch.screenX;
    pStop.y = touch.screenY;
  } else {
    pStop.x = e.screenX;
    pStop.y = e.screenY;
  }

  swipeCheck();
}

function swipeCheck() {
  var changeY = pStart.y - pStop.y;
  var changeX = pStart.x - pStop.x;
  if (isPullDown(changeY, changeX)) {
    alert("Swipe Down!");
  }
}

function isPullDown(dY, dX) {
  // methods of checking slope, length, direction of line created by swipe action
  return (
    dY < 0 &&
    ((Math.abs(dX) <= 100 && Math.abs(dY) >= 300) ||
      (Math.abs(dX) / Math.abs(dY) <= 0.3 && dY >= 60))
  );
}

document.addEventListener(
  "touchstart",
  function (e) {
    swipeStart(e);
  },
  false
);
document.addEventListener(
  "touchend",
  function (e) {
    swipeEnd(e);
  },
  false
);

你厌倦了这些解决方案吗?

你需要检查这个fiddle

var mouseY = 0
var startMouseY = 0

$("body").on("mousedown", function (ev) {
  mouseY = ev.pageY
  startMouseY = mouseY

  $(document).mousemove(function (e) {
    if (e.pageY > mouseY) {
      var d = e.pageY - startMouseY
      console.log("d: " + d)
      if (d >= 200) location.reload()
      $("body").css("margin-top", d / 4 + "px")
    } else $(document).unbind("mousemove")
  })
})

$("body").on("mouseup", function () {
  $("body").css("margin-top", "0px")
  $(document).unbind("mousemove")
})

$("body").on("mouseleave", function () {
  $("body").css("margin-top", "0px")
  $(document).unbind("mousemove")
})

如果您正在寻找一些插件 this plugin 可能会对您有所帮助

一个简单的方法:

$(document.body).pullToRefresh(function() {
         setTimeout(function() {
            $(document.body).pullToRefreshDone();
         }, 2000);
      });

这个呢?

var lastScrollPosition = 0;
window.onscroll = function(event)
{
  if((document.body.scrollTop >= 0) && (lastScrollPosition < 0))
  {
    alert("refresh");
  }
  lastScrollPosition = document.body.scrollTop;
}

如果您的浏览器没有负向滚动,那么您可以将第 4 行替换为如下内容: if((document.body.scrollTop == 0) && (lastScrollPosition > 0))

或者,对于 android 设备,您可以将 lastScrollPosition 换成 "ontouchmove" 或其他手势事件。

我知道很多人已经回答了这个答案,但它可能会对某些人有所帮助。

它基于 Mr. Pryamid's 答案。但他的回答不工作触摸屏。仅适用于鼠标。

此答案适用于触摸屏和桌面。我在桌面 chrome 和 android

中测试过 chrome
<!DOCTYPE html>
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }

      html,
      body {
        width: 100%;
        height: 100%;
      }

      .pull-to-refresh-container {
        width: 100%;
        height: 100%;
        background-color: yellow;
        position: relative;
      }

      .pull-to-refresh-content-container {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: white;
        margin: 0px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div class="pull-to-refresh-container">
      <div class="pull-to-refresh-loader-container">
        loading ...
      </div>
      <div class="pull-to-refresh-content-container">
        here lies the content
      </div>
    </div>

    <script>
      var mouseY = 0
      var startMouseY = 0
      var container = document.querySelector(
        ".pull-to-refresh-content-container"
      )

      container.onmousedown = (ev) => {
        mouseY = ev.pageY
        startMouseY = mouseY

        container.onmousemove = (e) => {
          if (e.pageY > mouseY) {
            var d = e.pageY - startMouseY

            console.log("d: " + d)
            container.style.marginTop = d / 4 + "px"
            if (d >= 300) {
              // alert("load more content");
            }
          } else {
            container.onmousemove = null
          }
        }
      }

      container.onmouseup = (ev) => {
        container.style.marginTop = "0px"
        container.onmousemove = null
      }

      container.onmouseleave = (ev) => {
        container.style.marginTop = "0px"
        container.onmousemove = null
      }
      container.ontouchstart = (ev) => {
        mouseY = ev.touches[0].pageY
        startMouseY = mouseY

        container.ontouchmove = (e) => {
          if (e.touches[0].pageY > mouseY) {
            var d = e.touches[0].pageY - startMouseY

            console.log("d: " + d)
            container.style.marginTop = d / 4 + "px"
            if (d >= 300) {
              // alert("load more content");
            }
          } else {
            container.onmousemove = null
          }
        }
      }

      container.ontouchcancel = (ev) => {
        container.style.marginTop = "0px"
        container.onmousemove = null
      }

      container.ontouchend = (ev) => {
        container.style.marginTop = "0px"
        container.onmousemove = null
      }
    </script>
  </body>
</html>

以下是我使用 Stimulus 和 Turbolinks 的方法:

观看视频:https://imgur.com/a/qkzbhZS

import { Controller } from "stimulus"
import Turbolinks from "turbolinks"

export default class extends Controller {
  static targets = ["logo", "refresh"]

  touchstart(event) {
    this.startPageY = event.changedTouches[0].pageY
  }

  touchmove(event) {
    if (this.willRefresh) {
      return
    }

    const scrollTop = document.documentElement.scrollTop
    const dy = event.changedTouches[0].pageY - this.startPageY

    if (scrollTop === 0 && dy > 0) {
      this.logoTarget.classList.add("hidden")
      this.refreshTarget.classList.remove("hidden")

      if (dy > 360) {
        this.willRefresh = true
        this.refreshTarget.classList.add("animate-spin")
        this.refreshTarget.style.transform = ""
      } else {
        this.refreshTarget.classList.remove("animate-spin")
        this.refreshTarget.style.transform = `rotate(${dy}deg)`
      }
    } else {
      this.logoTarget.classList.remove("hidden")
      this.refreshTarget.classList.add("hidden")
      this.refreshTarget.classList.remove("animate-spin")
      this.refreshTarget.style.transform = ""
    }
  }

  touchend(event) {
    if (this.willRefresh) {
      Turbolinks.visit(window.location.toString(), { action: 'replace' })
    } else {
      this.logoTarget.classList.remove("hidden")
      this.refreshTarget.classList.add("hidden")
      this.refreshTarget.classList.remove("animate-spin")
      this.refreshTarget.style.transform = ""
    }
  }
}
  body(class="max-w-md mx-auto" data-controller="pull-to-refresh" data-action="touchstart@window->pull-to-refresh#touchstart touchmove@window->pull-to-refresh#touchmove touchend@window->pull-to-refresh#touchend")
        = image_tag "logo.png", class: "w-8 h-8 mr-2", "data-pull-to-refresh-target": "logo"
        = image_tag "refresh.png", class: "w-8 h-8 mr-2 hidden", "data-pull-to-refresh-target": "refresh"