使用油猴脚本时给 jQuery添加扩展方法
最近用油猴写了个 swagger文档助手的脚本,用于复制api链接,名称,由于页面是异步加载的,需要判断元素有没有加载。
搜了下找到这篇文章 jQuery下实现等待指定元素加载完毕
看着不错,赶紧扒来代码试试
jQuery.fn.extend({
wait: function (selector, func, times, interval) {
var _times = times || -1, //100次
_interval = interval || 20, //20毫秒每次
_self = this,
_selector = selector, //选择器
_iIntervalID //定时器id
if (this.length) {
//如果已经获取到了,就直接执行函数
func && func.call(this)
} else {
_iIntervalID = setInterval(function () {
if (!_times) {
//是0就退出
clearInterval(_iIntervalID)
}
_times <= 0 || _times-- //如果是正数就 --
_self = $(_selector) //再次选择
if (_self.length) {
//判断是否取到
func && func.call(_self)
clearInterval(_iIntervalID)
}
}, _interval)
}
return this
}
})
$('.opblock-summary').wait('.opblock-summary', function () {
// 执行具体逻辑
})
由于对jQuery不太熟悉,看了文档有 jQuery.extend, jQuery.fn.extend
两种方法,自以为jQuery.extend相当于构造函数的方法,就写下了这样的代码:
jQuery.extend({
wait: function (selector, func, times, interval) {
})
$.wait('.opblock-summary', function () {
// 执行具体逻辑
})
然后就是一顿报错排错…
这里的jQuery.extend
其实就相当于一个工具函数了,和Object.assign
,...扩展运算符
非常类似,和原型一点关系没有,自然不能添加原型方法。官方文档这样解释的:
jQuery.extend( target [, object1 ] [, objectN ] )
将两个或更多对象的内容合并到第一个对象。
也就是限定了至少有三个参数
en…个人感觉可能还不如Object.assign
顺手,也就不再去尝试了。
注意项:
扩展方法是添加到原型上的,也就是每个jQuery实例对象都会有wait
方法,而jQuery构造函数本身是没有该方法的。
如果代码这样写将会报错找不到wait
方法了:
$.wait('.opblock-summary', function () {
// 执行具体逻辑
})
不过竟然是每个实例对象都会拥有该方法,这样也是可以的。
$().wait('.opblock-summary', function () {
// 执行具体逻辑
})
在jQuery 1.4中,如果你传递给jQuery()方法一个空参数,一个空的jQuery设置将被返回(.length属性为0)。 在以前的jQuery版本中,一个包含整个文档节点的集合将被返回。
最后贴一下swagger油猴助手的效果图及全部代码
// ==UserScript==
// @name swagger 助手
// @namespace swagger-helper
// @version 0.1
// @description try to take over the world!
// @author You
// @match */apiv2/swagger*
// @icon https://www.google.com/s2/favicons?domain=tampermonkey.net
// @require https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js
// @grant unsafeWindow
// @grant GM.setClipboard
// @grant GM_addStyle
// ==/UserScript==
const css = `
.btn-wrap{
margin-right: 24px;
}
.swagger-ui .btn-copy{
height: 32px;
border-radius: 4px;
margin: 0 12px;
}
.copy-tip{
position: fixed;
min-width: 300px;
top: 100px;
right: 32px;
padding: 0 1rem;
border: 1px solid teal;
color: teal;
background: white;
}
`
;(function () {
'use strict'
// GM_addStyle(GM_getResourceText('css'))
GM_addStyle(css)
jQuery.fn.extend({
wait: function (selector, func, times, interval) {
var _times = times || -1, //100次
_interval = interval || 20, //20毫秒每次
_self = this,
_selector = selector, //选择器
_iIntervalID //定时器id
if (this.length) {
//如果已经获取到了,就直接执行函数
func && func.call(this)
} else {
_iIntervalID = setInterval(function () {
if (!_times) {
//是0就退出
clearInterval(_iIntervalID)
}
_times <= 0 || _times-- //如果是正数就 --
_self = $(_selector) //再次选择
if (_self.length) {
//判断是否取到
func && func.call(_self)
clearInterval(_iIntervalID)
}
}, _interval)
}
return this
}
})
$().wait('.opblock-summary', function () {
const entryEl = ($('.opblock-summary > button').length && $('.opblock-summary > button')) || $('.opblock-summary')
entryEl.each(function () {
const path = $('.opblock-summary-path', this).attr('data-path')
const name = $('.opblock-summary-description', this).text()
const cyNameEl = $('<button class="btn-copy">复制名称</button>')
$(cyNameEl).on('click', e => {
e.stopPropagation()
GM.setClipboard(name)
message()
})
const cyLinkEl = $('<button class="btn-copy"">复制链接</button>')
$(cyLinkEl).on('click', e => {
e.stopPropagation()
GM.setClipboard(path)
console.log('e:', e)
message()
})
const btnWrap = $(`
<div class="btn-wrap">
</div>
`).append(cyNameEl, cyLinkEl)
$('.opblock-summary-description', this).after(btnWrap)
})
})
function message(msg = '复制成功!') {
const info = $(`<div class="copy-tip">
<p>${msg}</p>
</div>`).appendTo($('body'))
setTimeout(() => {
info.remove()
}, 1000)
}
})()
注意
- 使用
@macth
匹配特地的域名才运行脚本