ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

兼职答题第一道被采纳的题

2021-10-24 11:02:06  阅读:171  来源: 互联网

标签:requestKey const 答题 第一道 绑定 事件 addEventListener 兼职 config


这道题来自CSDN,最近接了一个兼职在CSND做答题服务。

这道题是网友提出来了的,题干如下:

请问有没有办法用vue或者原生JS将多个页面统一进行防止重复执行点击事件(在不侵入源事件方法的前提下,因为页面太多是在改不过来),或者进行统一节流处理

我给出的第一个答案:

如果点击事件都有axios请求,你防止的是重复的后端请求,如果是vue单页面项目可以考虑如下的方案: 取消重复请求,具体方法如下,基本思路是缓存,请求结束之后清空缓存

/**
 * 全部请求拦截器处理
 */
const pendingRequests = new Map()
myAjax.interceptors.request.use(function (config) {
  const params = config.params || config.data
  const requestKey = `${config.url}/${JSON.stringify(params)}&request_type=${config.method}`
  if (pendingRequests.has(requestKey)) {
    config.cancelToken = new axios.CancelToken((cancel) => {
      // cancel 函数的参数会作为 promise 的 error 被捕获
      cancel(`重复的请求被主动拦截: ${requestKey}`)
    })
  } else {
    pendingRequests.set(requestKey, config)
    config.requestKey = requestKey
  }
  return config
},
function (error) {
  pendingRequests.clear()
  return Promise.reject(error)
}
)
/**
 * 响应拦截器
 */
myAjax.interceptors.response.use(response => {
  const requestKey = response.config.requestKey
  pendingRequests.delete(requestKey)
  return response
}, error => {
  pendingRequests.clear()
  return Promise.reject(error)
})

或者将问题阐述具体一些。

之所以这样是他的题干信息不具体,而且当是我正在优化全局响应拦截器这部分。我很自然的想到是不是他也做一层拦截就可以了。然后我给出全局拦截的前提还有解决方案。

后来,他回复了,回复内容:

不是单页面项目,后台请求基本都是普通的ajax(应该是不像axios有拦截器的..)。主要是对每个页面的nav标签里的请求按钮进行统一的防重复点击、请求。

然后我就知道他要做什么了,是想对所有类似的按钮做一层防抖。于是我给出了我的第二个答案:

可以利用css的选择器拿到按钮, 然后拿到按钮绑定事件的引用, 然后重新给按钮绑定事件, 重写事件的方法,加上防抖。

<body>
    <button id="btn" onclick="alert('hi~')">我是按钮</button>
    <script>
        const btn = document.getElementById('btn')
        const clickfn = btn.onclick // 获取onclik的方法
        btn.onclick = null //解除事件
        console.log(clickfn, 'click')
        let timer = null
        // 利用addEventListener重新绑定事件 顺便加上防抖
        btn.addEventListener('click', ()=>{
            timer && clearTimeout(timer)
            timer = setTimeout(() => {
                clickfn()
            }, 300);
        })
    </script>
</body>

将上面写成一个单独的JavaScript文件,引入到各个html文件中。 当然前提是你是利用onclick绑定的事件,如果是利用addEventListener绑定的事件:也可以参照这个思路,但前提是能够拿到addEventListener绑定的事件。目前我没找到合适的方法拿到。

给出这个方案也是基于《设计模式》里面有提到的装饰者模式,尽可能少的减少原来代码的情况下,解决问题。

但是题主随后表示和我一样不能拿到addEventListener绑定事件的引用。

最后我又想到了一个方案,于是再度回复:

(function() { 
    Element.prototype._addEventListener = Element.prototype.addEventListener; 
    Element.prototype.addEventListener = function(a, b, c) { 
     this._addEventListener(a, b, c); 
     if (a == "click") { 
      this._addEventListener("touchstart", b, c); 
     } 
    }; 
})();

试试复写addEventListener这个思路。

我相信这个思路一定是可以解决的。然后我耐心等待题主的回复。可题主就像不在线了一样,一直到我快下班了都没回复。我因为着急别的事情就不在关注。

第二天没想到的是题主回复通过借鉴第一个回复解决了问题。并且表示多谢我,我于是在他的回复下面麻烦他采纳我的答案,没想到他真的采纳了。

我心里一阵高兴。

总结:就解决题主的问题而言,防止重复请求的可以用全局拦截器,也可以用防抖。就题主的场景而言,我最后的答案是可以解决他的问题的。实质是对事件绑定过程进行拦截。而利用拿到onclick的方法,虽然没有解决题主的问题,但涉及到一种设计模式:装饰者模式,以不浸入源代码的方式实现开发目的。

标签:requestKey,const,答题,第一道,绑定,事件,addEventListener,兼职,config
来源: https://www.cnblogs.com/zhensg123/p/15450451.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有