# Tampermonkey 开发基本知识
# 什么是油猴脚本
油猴脚本(Tampermonkey script)是一种浏览器扩展中的一种,它允许用户通过 JavaScript 自定义网站的行为。通过编写脚本,你可以修改网站的外观、行为、交互效果等等方面。使用油猴脚本,你可以自定义自己的浏览器体验,定制功能和样式,满足您的个性化使用需求。油猴脚本可应用于各种浏览器,例如,Chrome、Firefox、Safari、Opera 等等都有提供对油猴脚本的支持。
# 第一个程序 Hello World
// ==UserScript==
// @name Hello World Example
// @namespace http://tampermonkey.net/
// @version 1
// @description Simple example for Tampermonkey
// @author You
// @match https://*/*
// @match http://*/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
window.alert("Hello World!");
})();
以上代码实现了在打开任何网页时,会弹出一个提示框,内容为“Hello World!”。
在油猴脚本中,必须添加几行注释,指示油猴如何处理脚本,例如@name、@namespace、@match等。
由于我们没有使用特权,因此“@grant none”是不需要的。
# Match 规则
油猴脚本可以通过 match 规则来指定应该应用到哪些网站或页面。match 规则是位于注释块中的一组元数据,它通常包括一些 @match 或 @include 等字段。这些字段可以接受一个或多个 URL 模式,从而匹配到你所想应用的所有网站或页面。
以下是一些常见的 match 规则:
- 包含某个特定协议的所有 URL:
http://*/*
或https://*/*
- 包含某个域名的所有 URL:
*://*.example.com/*
- 匹配某个具体的 URL:
https://example.com/index.html
- 包含某个子路径的所有 URL:
https://example.com/path/*
- 只应用到某个子域名下:
https://sub.example.com/*
你可以使用逗号分隔不同的 URL 模式,来同时匹配多个 URL。比如: https://example.com,http://example.org
,指匹配两个不同域名的URL。
match 规则的目的是使油猴脚本能够准确匹配特定的网站或页面,从而在你需要的时候自动运行。
# 获取 DOM 元素
通过获取DOM元素,实现修改元素样式、添加新元素、修改页面布局和动态添加内容等。以下是一些获取DOM元素的方法:
- 使用 document.querySelector() 这是获取单个DOM元素最简单的方式,类似于jQuery的选择器。以下是获取 id="example" 的元素:
document.querySelector("#example");
- 使用 document.querySelectorAll() 这是获得所有匹配的元素的方法。以下是获取 class="example" 的所有元素的示例:
document.querySelectorAll(".example");
- 通过元素的属性获取 如果元素具有独特的属性(例如具有唯一id),则可以使用该属性获取元素。以下是获取 id="example" 的元素:
document.getElementById("example");
- 使用jQuery 如果网站使用了jQuery,则可以使用该库的选择器和方法来获取元素。必须首先确保jQuery库已加载。以下是获取 class="example" 的第一个元素的示例:
$(".example").eq(0);
- 监听DOM元素的变化 可以使用 MutationObserver 监听DOM树中的更改,以便在元素添加或删除时自动触发脚本。以下是一个简单的示例:
//选择目标节点
var targetNode = document.querySelector('#target');
//观察器的配置(需要观察什么变动)
var config = { attributes: true, childList: true, subtree: true };
//当观察到变动时执行的回调函数
var callback = function(mutationsList, observer) {
for(var mutation of mutationsList) {
if (mutation.type == 'childList') {
console.log('A child node has been added or removed.');
}
else if (mutation.type == 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
};
//创建一个观察器实例并传入回调函数
var observer = new MutationObserver(callback);
// 以上述配置开始观察目标节点
observer.observe(targetNode, config);
// 停止观察
observer.disconnect();
上述示例中,使用了MutationObserver来监听目标节点的子节点变化和属性变化。要开始观察,将目标节点和配置传递给 observer 实例的observe()方法。调用 disconnect() 方法来停止观察。
# 在页面添加一个按钮
- 创建一个新按钮元素并设置其属性
var myButton = document.createElement("button");
myButton.innerHTML = "Click me";
myButton.setAttribute("id", "myButton");
myButton.setAttribute("style", "color: blue; background-color: white;");
- 将按钮添加到页面上到位置
document.body.appendChild(myButton);
- 添加事件监听器 使用 addEventListener() 方法添加事件监听器。在下面的示例中,我们使用该方法将 click 事件与按钮相关联:
myButton.addEventListener("click", myFunction);
- 在事件处理函数 myFunction() 中添加要执行的操作。 在下面的示例中,单击按钮将显示一个提示框:
function myFunction() {
alert("Button Clicked!");
}
完整代码如下:
var myButton = document.createElement("button");
myButton.innerHTML = "Click me";
myButton.setAttribute("id", "myButton");
myButton.setAttribute("style", "color: blue; background-color: white;");
document.body.appendChild(myButton);
myButton.addEventListener("click", myFunction);
function myFunction() {
alert("Button Clicked!");
}
这将在页面中创建一个文本为 "Click me" 的蓝色按钮,并在单击按钮时显示一个消息框。在myFunction()函数中,你可以添加任何你想运行的自定义代码。
# 监听页面事件
油猴脚本可以通过不同的方式监视页面事件,从而在特定事件发生时执行指定的功能。
# 使用 MutationObserver 监听 DOM 变化
MutationObserver 可以用于监听 DOM 中元素的添加、删除、属性变化等。以下是使用 MutationObserver 监听特定元素添加和属性变化的示例:
var targetNode = document.querySelector('body');
var attributeToWatch = 'class';
var elementToAdd = document.createElement('div');
elementToAdd.innerText = 'Hello World';
var callback = function(mutationsList, observer) {
for (var mutation of mutationsList) {
if (mutation.type === 'childList') {
for (var i = 0; i < mutation.addedNodes.length; i++) {
if (mutation.addedNodes[i].tagName === 'DIV') {
console.log('Element added: ', mutation.addedNodes[i]);
}
}
} else if (mutation.type === 'attributes' && mutation.attributeName === attributeToWatch) {
console.log(`Attribute "${attributeToWatch}" of ${mutation.target.tagName} changed to "${mutation.target.getAttribute(attributeToWatch)}"`);
}
}
};
var observer = new MutationObserver(callback);
observer.observe(targetNode, {
childList: true,
subtree: true,
attributes: true,
attributeOldValue: true,
attributeFilter: [attributeToWatch]
});
在上面的示例中,我们创建了一个 MutationObserver 对象,并传递了一个回调函数和配置。我们监控了body元素的子DOM元素的添加,以及body元素的class属性的变化。
# 使用 window.addEventListener() 监听页面事件
window.addEventListener() 可以用于监听浏览器窗口和页面加载的各种事件,如 load 和 unload 事件。以下是一个使用 window.addEventListener() 监听页面滚动事件的示例:
window.addEventListener('scroll', function() {
console.log(window.pageYOffset);
});
在上面的示例中,使用 window.addEventListener() 监听了页面滚动事件并在控制台输出当前页面的滚动位置。
window.addEventListener('load', function() {
console.log('Page is fully loaded');
// 在这里编写你需要的代码
});
在上面的示例中,使用 window.addEventListener() 监听了 load 事件,当页面完全加载时会触发该事件,在回调函数中我们可以编写我们需要的功能和操作。
# 使用 XMLHttpRequest 和 fetch 监听 Ajax 请求
如果页面使用 Ajax 发送 HTTP 请求,则可以使用 XMLHttpRequest 和 fetch 两个 API 监听请求并捕获响应。以下是一个使用 XMLHttpRequest 监听请求的示例:
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://example.com/api/data", true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
console.log(xhr.responseText);
}
};
xhr.send();
在上面的示例中,我们使用 XMLHttpRequest 发送了一个 GET 请求并通过 readyState==4 判断请求是否完成,如果请求已完成则在控制台输出响应字符串。
总之,油猴脚本可以通过多种方法监视页面事件。根据您的具体需求选择合适的方法并使用它们。
# 定时器
可以以使用 JavaScript 的 setTimeout() 或 setInterval() 函数来实现定时器功能。以下是使用 setTimeout() 函数实现定时器的示例
示例代码:
// 定义一个定时器函数,每隔10秒钟输出一次当前时间
function timerFunc() {
const now = new Date();
console.log(`当前时间:${now.toLocaleTimeString()}`);
}
// 设置一个定时器,每隔10秒钟调用一次timerFunc函数
const timerId = setInterval(timerFunc, 10000);
// 取消定时器,停止调用timerFunc函数
clearInterval(timerId);
在油猴脚本中,可以将需要定时执行的任务放在一个函数内,然后使用setInterval()方法定时调用该函数。同时需要注意,在油猴脚本中通常需要在脚本结束前清除定时器,避免脚本执行结束后仍有定时器在运行。
# 发送一个 HTTP 请求
在油猴脚本中发送http请求可以使用XMLHttpRequest对象或fetch函数。下面为你提供两种方式的示例代码。
使用XMLHttpRequest对象发送http请求:
// 创建一个XMLHttpRequest对象
const xhr = new XMLHttpRequest();
// 设置请求参数
const method = 'GET';
const url = 'https://jsonplaceholder.typicode.com/todos/1';
xhr.open(method, url);
// 发送请求
xhr.send();
// 监听请求状态变化
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
// 请求成功,获取响应数据
console.log(xhr.responseText);
} else {
// 请求失败,输出错误信息
console.error(xhr.statusText);
}
}
};
使用fetch函数发送http请求:
// 发送GET请求
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
// 发送POST请求
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1,
}),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
请注意,在发送http请求时需要注意跨域问题,需要通过设置请求头或使用代理等方式来解决。同时,还需要注意请求的安全性,避免泄漏敏感信息。