1.0.0 • Published 3 years ago

pdrjs v1.0.0

Weekly downloads
2
License
ISC
Repository
github
Last release
3 years ago

pdr —— 防止用户多次点击发送重复请求的工具

pdr - a tool for preventing duplicated requests by user click

demo:https://heruns.github.io/pdr/demos/

功能

  • 不依赖 axios,自动监听 ajax 请求的发送和响应,防止重复请求
  • 提供请求开始和结束的钩子,可自定义请求目标样式,或搭配 element ui 等组件库/样式库使用
  • 内置为请求元素添加 loading 或降低不透明度的功能,提高交互体验
  • 提供 vue 指令,可以指定特定目标,及手动控制请求开始和结束的时机

使用

方式 1:全局监听请求

这种方式只需直接在页面中加载 pdr.js 即可,加载后会在 window 对象上挂载一个 pdr 对象,可通过 pdr.setOptions 修改默认参数

pdr.setOptions({
  loading: true, // 是否添加 loading
  loadingText: "", // 请求时的文字提示
  // opacity: 1, // 设置元素请求时的不透明度
  selectors: ["button"], // 需要全局统一处理请求的选择器列表
  eventTypes: ["click"], // 需要全局统一处理请求的事件列表
  onRequest(target, options) {}, // 请求发起的钩子
  onResponse(target, options) {}, // 请求结束的钩子
});

方式 2:vue 指令指定请求元素和时机

首先通过 Vue.use(pdr) 注册 v-pdr 指令,注册后使用方式如下:

<!-- 手动设置请求开始和结束时机,可用于处理多个请求的情况 -->
<button v-pdr="fetching" @click="request">按钮</button>

<!-- 手动指定目标,可用于 selectors 不匹配的情况 -->
<div v-pdr="{'loading': true, 'loadingText': '正在下载...'}" @click="download">
  <div class="content">点击下载文件</div>
</div>

方式 3:通过钩子函数自定义请求元素的样式,可搭配 element ui 等组件库使用

JS:

pdr.setOptions({
  loading: false,
  onRequest(target, options) {
    // 请求开始,添加 loading
    if (target.classList.contains("el-button")) {
      target.classList.add("is-loading");
      const loading = document.createElement("i");
      loading.className = "el-icon-loading";
      target.insertBefore(
        loading,
        target.children.length > 0 ? target.children[0] : null
      );
    }
  },
  onResponse(target, options) {
    // 请求结束,移除 loading
    if (target.classList.contains("el-button")) {
      target.classList.remove("is-loading");
      const loading = document.querySelector(".el-icon-loading");
      loading && target.removeChild(loading);
    }
  },
});

在模板中正常使用即可,请求时会自动为按钮加上 loading 样式

<el-button type="primary" @click="request">click me</el-button>

原理

  • 通过重写 XMLHttpRequest.prototype.send 方法和监听 xhr 对象的 loadend 事件实现请求监听
  • 通过 window.event 对象获取触发请求的元素
  • 通过给请求元素设置 pointer-events:none,防止用户多次点击导致的重复请求
  • 设置不透明度时涉及到修改行内样式,即使是行内样式也要使用 el.style.setProperty("opacity", opacity, "important") 保证样式优先级是最高的,同时通过 el.style.getPropertyPriority 获取原样式的优先级,以便后面恢复

限制

  • 当元素会触发连续请求时,比如点击按钮发起一个请求,请求完成后再通过拿到的数据去调另一个接口这种情况,可以通过 pdr.start + pdr.stop 方法或通过 vue 指令来处理

TODO

  • 完善 API 文档
  • 发布到 npm
  • 单元测试
  • 支持配置 loading 图标