油猴脚本 监听按钮click事件无效

我正在编写一个油猴脚本,是向网页上添加一个button,并且点击button执行一个函数,却发现点击button后触发不了函数。
测试脚本如下:

// ==UserScript==
// @name         爱奇艺测试
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @include       /^https:\/\/www\.iqiyi\.com\/v_(\w+)\.html.*$/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=iqiyi.com
// @grant        none
// @run-at document-end
// ==/UserScript==
window.addEventListener('load',async function() {
    'use strict';
    console.log("load");
    const parentElement = document.querySelector(".qy-player-title");
    const Button= document.createElement("button");
    Button.innerText = "按钮";
    Button.addEventListener("click", () => {
        console.log("Button onclick");
    });
    parentElement.append(Button);
});

步骤:启用脚本,打开任意一个爱奇艺视频播放页面(例如 https://www.iqiyi.com/v_19rrkrqv2w.html ),可以看到播放器下方的标题旁就是脚本添加的button,正常的话,点击它,会在控制台输出"Button onclick",但实际上没有。
控制台中的"load"表明脚本是成功开始运行的。
通过开发者工具也可以看到,这个button上也没有绑定上来自userscript.html的EventListener……

如果等待2000ms(视网络状态而定,主要是等爱奇艺自己的脚本运行完),再添加按钮的话,就一切正常

所以有啥办法能监视页面自己的js运行完毕的吗?或者其他解决方法

run-at document-start
先创建button,load之后再append。也可以试试直接onclick写入标签,把函数暴露在window下

// @run-at document-start
// ==/UserScript==
'use strict';
console.log("load");
const Button= document.createElement("button");
Button.innerText = "按钮";
Button.addEventListener("click", () => {
    console.log("Button onclick");
});

window.addEventListener('load',async function() {
    const parentElement = document.querySelector(".qy-player-title");
    parentElement.append(Button);
});

@Hoothin 不行的,而且我觉得这和load后再创建并没有区别
onclick也试过了,不行 Button.onclick = function(){console.log("Button onclick");}

我感觉还是页面自己的js做了什么事导致的……

那就onclick。
还有一招,把click绑到document上,然后判断target

百度系的前端都挺变态的,好久之前我写vip视频脚本时iqiyi就hook了很多函数,这边我估计也是阻止了click冒泡

document.addEventListener("click", e => { if(e.target == Button) { console.log("Button onclick"); } });类似于这样,我手机码的,可能有错误

我说的onclick是指直接写入html标签。还有啊,如果元素移除再添加,事件是会丢失的。你看下父元素有没有可能被爱奇艺移除后重新添加

直接写入html就不考虑了,因为还要调用脚本里的其他函数,全塞进去也很麻烦,不止一个按键。
要怎么看元素有没有被移除然后添加呢?用Mutation observer吗?

那就加一个id,把click事件绑在document上,判断e.target.id 。
或者直接把按钮加在body下

1 Like

parentElement 的父元素阻止了冒泡,其实就是“委托”做法,在 document 上跟它抢就行了。

console.log("load");
const Button = document.createElement("button");
Button.innerText = "按钮";

window.addEventListener('load',async function() {
    const parentElement = document.querySelector(".qy-player-title");
    parentElement.append(Button);
    document.addEventListener('click',  fucntion(event) {
    if (event.target === Button) {
        event.stopPropagation(); // 阻止继续冒泡
        console.log("Button onclick"); // 你的逻辑。
        return;
    }
}, true);

关键是 document.addEventListener 的第三个参数为 true,思路大概如此,具体自己调。

1 Like

直接判断元素event.target === Button是不行的,还是得按楼上说的比较属性。

ps:你贴出来的代码里fucntion打错了,cn的顺序反了……我半天都没发现哪里语法错了,没想到是这里拼写错了……

脚本完工了,每次写脚本就和复习一样

用于下载爱奇艺的外挂字幕: