SPA页面操作库(类jQuery)

支持Vue。提供元素加载后点击、监听url变化等方法

当前为 2022-02-20 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/440334/1020488/jQuery-like%20SPA%20operation%20library.js

  1. // ==UserScript==
  2. // @name jQuery-like SPA operation library
  3. // @name:zh-CN SPA页面操作库(类jQuery)
  4. // @description SPA like vue is supported。offers functions like click element after loaded, call function after url change。
  5. // @description:zh-CN 支持Vue。提供元素加载后点击、监听url变化等方法
  6. // @author yechenyin
  7. // @licence MIT
  8. // @version 1.0
  9. // ==/UserScript==
  10.  
  11. //闭包里的方法的用法和jquery同命名方法一致
  12. (function () {
  13. let jQuery = function (selector) {
  14. return new jQuery.fn.init(selector)
  15. }
  16. jQuery.fn = jQuery.prototype = {
  17. length: 0,
  18. selector: '',
  19. init: function (elementOrSelector) {
  20. let nodes = []
  21. if (typeof (elementOrSelector) == 'string') {
  22. this.selector = elementOrSelector
  23. nodes = document.querySelectorAll(this.selector)
  24. } else if (elementOrSelector instanceof NodeList) {
  25. nodes = elementOrSelector
  26. } else if (elementOrSelector instanceof Element) {
  27. nodes = [elementOrSelector]
  28. }
  29. this.length = nodes.length
  30. for (let i = 0; i < nodes.length; i++) {
  31. this[i] = nodes[i]
  32. }
  33. },
  34. each: function (callback) {
  35. for (let i = 0; i < this.length; i++) {
  36. callback.call(this[i])
  37. }
  38. },
  39. on: function (event, callback) {
  40. this.each(function () {
  41. this.addEventListener(event, callback)
  42. })
  43. },
  44. text: function (string) {
  45. let i = 0
  46. if (string !== undefined) {
  47. for (i = 0; i < this.length; i++) {
  48. this[i].innerText = string
  49. }
  50. } else {
  51. return this[0].innerText
  52. }
  53. },
  54. val: function (value) {
  55. if (value === undefined) {
  56. let ret
  57. if (this[0].type == 'checkbox')
  58. ret = this[0].checked
  59. else if (this[0].type == 'radio' || this[0].type == 'text' || this[0].tagName == 'select')
  60. ret = this[0].value
  61. return ret
  62. } else {
  63. for (let i = 0; i < this.length; i++) {
  64. if (this[i].type == 'checkbox' && Boolean(value))
  65. this[i].click()
  66. else if (this[i].type == 'radio')
  67. this[i].checked = this[i].value == value
  68. else if (this[i].type == 'text')
  69. this[i].value = value
  70. else if (this[i].tagName == 'select')
  71. this[i].value = value
  72. this[i].dispatchEvent(new Event('input', { bubbles: true }))
  73. }
  74. }
  75. },
  76. attr: function (attribute, value) {
  77. if (value === undefined) {
  78. return this[0].getAttribute(attribute)
  79. } else {
  80. this.each(function () {
  81. this.setAttribute(attribute, value)
  82. })
  83. }
  84. },
  85. click: function () {
  86. this[0].click()
  87. },
  88. find: function (selector) {
  89. let j = 0
  90. let result = []
  91. for (let i = 0; i < this.length; i++) {
  92. if (this[i].querySelectorAll(selector).length) {
  93. }
  94. }
  95. },
  96. append: function (html) {
  97. for (let i = 0; i < this.length; i++) {
  98. this[i].innerHTML += html
  99. }
  100. },
  101. }
  102.  
  103. jQuery.fn.init.prototype = jQuery.fn
  104. if (!window.jQuery) window.jQuery = window.$ = jQuery
  105. })()
  106.  
  107. //每当符合选择器规则的元素插入到页面中时,唤起callback方法。如果trigger_once为true,只唤起一次
  108. jQuery.fn.inserted = function (callback, trigger_once = false) {
  109. let selector = this.selector;
  110. if ($(selector).length > 0) {
  111. console.log($(selector).length + ' ' + selector + " is loaded at begin");
  112. callback.call($(selector));
  113. }
  114. let finished = false
  115. let recallback = function (mutationsList, observer) {
  116. for (let i = 0; i < mutationsList.length; i++) {
  117. //console.log(mutationsList[i].target)
  118. if (mutationsList[i].addedNodes) {
  119. for (let j = 0; j < mutationsList[i].addedNodes.length; j++) {
  120. let element = mutationsList[i].addedNodes[j]
  121. if (!(trigger_once && finished) && element instanceof Element && element.querySelectorAll(selector).length) {
  122. if (element.id)
  123. console.log('#' + element.id + ' which contains ' + selector + ' is loaded')
  124. else if (element.className)
  125. console.log('.' + element.className + ' which contains ' + selector + ' is loaded')
  126. else
  127. console.log(element.outerHtml + ' which contains ' + selector + ' is loaded')
  128. if (trigger_once) {
  129. observer.disconnect()
  130. finished = true
  131. }
  132. callback.call($(element.querySelectorAll(selector)))
  133. }
  134. }
  135. }
  136. }
  137. };
  138. let MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
  139. if (MutationObserver) {
  140. let observer = new MutationObserver(recallback)
  141. observer.observe(document.body, {
  142. childList: true,
  143. subtree: true
  144. })
  145. }
  146. }
  147.  
  148. //当符合选择器规则的元素插入到页面中时,调用一次callback方法,之后不会在唤起
  149. jQuery.fn.loaded = function (callback) {
  150. if (callback)
  151. this.inserted(callback, true);
  152. }
  153.  
  154. //在元素加载完成后经过delay(单位毫秒)延迟后点击元素
  155. jQuery.fn.clickAfterLoaded = function (delay = 0) {
  156. this.loaded(function () {
  157. setTimeout(function () {
  158. this[0].click()
  159. }.bind(this), delay)
  160. })
  161. }
  162. //在元素加载完成后经过delay(单位毫秒)延迟后设置输入值
  163. jQuery.fn.setAfterLoaded = function (value, delay = 0) {
  164. this.loaded(function () {
  165. setTimeout(function () {
  166. this.val(value)
  167. }.bind(this), delay)
  168. })
  169. }
  170.  
  171. //替代得到http成功回应后的回调
  172. $.replaceResponseCallback = function (callback, continueOriginalCallback = false) {
  173. let open = XMLHttpRequest.prototype.open
  174. XMLHttpRequest.prototype.open = function () {
  175. this.addEventListener(
  176. 'readystatechange',
  177. function () {
  178. if (
  179. this.readyState == 4 &&
  180. this.response
  181. ) {
  182. callback.call(this)
  183. }
  184. },
  185. false
  186. )
  187. if (continueOriginalCallback)
  188. open.apply(this, arguments)
  189. XMLHttpRequest.prototype.open = open
  190. }
  191. }
  192. //url改变后唤起callback,支持监测SPA的#后面的字符串变化
  193. $.onurlchange = function (callback) {
  194. history.pushState = ((f) =>
  195. function pushState() {
  196. let ret = f.apply(this, arguments)
  197. window.dispatchEvent(new Event('pushstate'))
  198. window.dispatchEvent(new Event('urlchange'))
  199. return ret
  200. })(history.pushState)
  201.  
  202. history.replaceState = ((f) =>
  203. function replaceState() {
  204. let ret = f.apply(this, arguments)
  205. window.dispatchEvent(new Event('replacestate'))
  206. window.dispatchEvent(new Event('urlchange'))
  207. return ret
  208. })(history.replaceState)
  209.  
  210. window.addEventListener('popstate', () => {
  211. window.dispatchEvent(new Event('urlchange'))
  212. })
  213. window.addEventListener('urlchange', function () {
  214. callback()
  215. })
  216. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址