上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
123下一页
返回列表 发新帖

[油猴脚本开发指南]脚本往页面上添加新元素

[复制链接]
  • TA的每日心情
    开心
    5 天前
  • 签到天数: 49 天

    [LV.5]常住居民I

    138

    主题

    1814

    帖子

    1988

    积分

    管理员

    Rank: 10Rank: 10Rank: 10

    积分
    1988

    猫咪币纪念章热心会员活跃会员突出贡献三好学生中秋纪念章国庆纪念章

    发表于 2021-1-23 15:30:44 | 显示全部楼层 | 阅读模式

    本节主要内容

    介绍使用脚本往前端页面插入按钮或者一个小框框之类的元素.最后弄一个给b站真·一键三连的按钮.(有兴趣也可以写二连,太耗硬币了T T)
    感兴趣的朋友可以弄一个评论列表来实战,本来是想在本节中弄的,但是篇幅有限,暂时放弃吧.想的话可以反馈一下,我安排到下一节.
    (本来是想再弄一个弹幕列表的页面的,但是感觉难度太高了,不太合适做教程.)

    脚本往页面添加新元素

    脚本往页面增加新元素这种需求经常可见,例如百度云的脚本,就会往页面上添加一些解析链接之类的按钮,一些助手类型的会往页面上添加一些小窗口,显示脚本的运行状态等等.

    如果要让脚本往页面上添加新元素,原理很简单.

    首先使用 document.createElement创建好你想插入的元素,例如按钮就 document.createElement("button"),如果你有很多组件想放进去的话可以用 document.createElement("div"),然后往element里的innerHTML直接写html代码.

    然后找到你想插入的位置,使用 append/insertBefore之类的方法插入你的element.之后就可以在 F12 开发者工具中的 element中看到我们插入的内容了.

    append,appendChild,prepend,insertBefore,具体方法和区别可以自行百度搜索和查看文档(其实是我嫌麻烦,整理一下又可以水一篇了)

    像下面的代码,插入到了最后面

    image-20210123121141630.png

    当然上述是的原生的方法,例如有些网页自带jQuery,那么可以用 `$("

    html代码
    ")之类的方式去创建元素,再用jQuery的append`之类的方法插入到页面中去.本系列内容还是使用原生的来进行讲解和使用.

    新元素的事件监听

    > 元素是添加进去了,但是只能看又不能用那有啥用.所以我们需要监听我们的元素事件,最常用的就是 click点击事件,点了我们的按钮,让我们的脚本做出一些反应.

    如果是类似按钮的方式,我们可以这样写.直接的使用onclick的方法.

    let btn=document.createElement("button");
    btn.innerHTML="按钮文字,其实也可以写html,变成下面的样子(不过谁用按钮来包那么多html标签呢)";//innerText也可以,区别是innerText不会解析html
    btn.onclick=function(){
        //code
        alert("点击了按钮");
    }
    document.body.append(btn);

    如果是一个div,在里面写html自由发挥,可以使用下面的方式.event详细说明:Event

    let div=document.createElement("div");
    div.innerHTML='<span id="span-1">span1</span><span class="sp">span class</span>';
    div.onclick=function(event){
        if(event.target.id=="span-1"){
            alert("span-1被点击了");
        }else if(event.target.className=="sp"){
            alert("sp这一类被点了");
        }
    };
    document.body.append(div);

    至于为什么会有这样的区别,简单来说就是前一种方法我们监听的只有一个元素,那我们肯定就知道就只可能是这一个执行的操作.

    后面的因为里面包含了多个元素,我们就可以从event里面找到实际被点击的元素,通过id或者class去判断,来走我们的脚本执行流程.

    另外再补充一下,上面的onclick可以改写成addEventListener("click"),类似下面这样.

    div.addEventListener("click",function(ev){
        console.log(ev);
    });

    主要区别onclick只能绑定一个function,addEventListener可以绑定多个,这又涉及了前端的内容,大家可以课后补习一下,可以看一下addEventListener的说明.也还有其它的绑定事件的方法,这里就不一一列举了.

    对于监听页面上已经有的按钮,推荐用addEventListener,以防onclick将原来的按钮事件覆盖掉(如果按钮也是用onclick的话),看情况而定.

    而且也可以在事件中 return false;使事件不再向上传递.(有点扯远了,就随口提一句😂,补充一些脚本的开发小技巧,就像是补充内力一样,以防踩坑,万一遇到了呢,不可能所有的东西都是完全按照教程来的.有兴趣的可以课外去细究,也可以略过有个印象就好.)

    新元素的style

    为了好看或者放在网页中不突兀,我们可以加上网页自带的class或者自己写一些样式,类似下面这样:

    btn.className="default-btn";//添加class
    btn.id="submit-btn";//添加id
    btn.style.color="#ff0000";//给按钮写style样式,查看这个文档,看css与JavaScript的对应:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference
    div.innerHTML='<span id="span-1" class="span-class" style="font-size:12px">span1</span><span class="sp" style="color:red">span class</span>';//在html里写style

    bilibili真·一键三连

    > 上面的内容说完后,来做点实际的东西,期望在页面上的收藏按钮和分享按钮中间增加一个三连按钮

    image-20210123130836474.png

    我们可以先通过 F12开发者工具找到这一块的元素,发现是用的span,为了样子一样我们可以用span来创建.不过!为了方便,我们还是使用button,大家也可以当作课后作业去完善.(实际上也没什么图标,直接用按钮得了)

    image-20210123131021747.png

    创建代码如下:

    let triple=document.createElement("button");
    triple.innerText="三连";
    triple.style.background="#757575";//颜色弄得差不多吧
    triple.style.color="#fff";
    triple.onclick=function(){
        //三连代码
    };

    插入我们可以找到share的父节点,然后使用insertBefore,在share之前插入我们的三连按钮,代码如下:

    let share=document.querySelector('.share');
    share.parentElement.insertBefore(triple,share);

    emmmm好丑,先这样吧,功能是可以的就行😂

    image-20210123140056733.png

    不过直接的这样插入是不行的,最终代码类似这样,比较复杂需要有点DOM之类的知识才好理解,暂时不展开吧,也暴力一点也可以直接用 setTimeout等一段时间再插入,且run-at设置为document-end.

    let ops=document.querySelector('#arc_toolbar_report .ops');
    //插入三连之后好像会重新生成,不添加就不会重新生成,暂时没弄清什么情况,先这样处理了.
    //主要作用是监听ops的DOMNodeInserted事件,等它修改完成之后再插入我们的三连按钮,另外注意run-at是document-end,要等待ops生成之后再监听,不然query返回null会报错
    //这个事件会多次调用,但是我们insertBefore插入如果元素存在,只是修改而不会新增
    ops.addEventListener("DOMNodeInserted", function(event) {
        let share=document.querySelector('.share');
        share.parentElement.insertBefore(triple,share);
    });
    

    然后我们可以长按大拇指,抓一下三连的http请求,就像上一节的ajax自动关注up主一样

    image-20210123140304599.png

    aid是我们的视频id,csrf的在cookie里面,这里就暂时不细说了,因为我们就是在bilibili的页面上,所以我们不需要使用GM跨域(所以我的grant是none,不需要沙盒环境,另外用unsafeWindow也挺麻烦的),而且也可以直接通过cookie取到csrf,直接用xhr请求接口就行了.代码如下:

    let httpRequest = new XMLHttpRequest();
    httpRequest.open('POST', 'https://api.bilibili.com/x/web-interface/archive/like/triple');
    httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    httpRequest.withCredentials = true;//设置跨域发送带上cookie
    let aid=window.__INITIAL_STATE__.aid;
    let sKey="bili_jct";
    let csrf=decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&amp;") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
    //上面这一段就是取出csrf,在cookie里面是bili_jct,这一段我是直接copy的,总之获取到就好了啦
    httpRequest.send('aid='+aid+'&amp;csrf='+csrf);
    httpRequest.onreadystatechange = function () {
        if (httpRequest.readyState == 4 &amp;&amp; httpRequest.status == 200) {
            var json = JSON.parse(httpRequest.responseText);
            console.log(json);
            if(json.code==0){
               alert("三连成功!刷新页面可见");
            }else{
                alert("三连失败/(ㄒoㄒ)/~~");
            }
        }
    };

    上述取csrf代码来自:Document.cookie

    end

    我们脚本本次用了 run-at,grant none,这是之前学习过的,大家可以多多注意一下,最后脚本代码会发到脚本发布区,大家可以去试试看看完整代码.

    bilibili三连按钮demo
    https://bbs.tampermonkey.net.cn/thread-238-1-1.html
    (出处: 油猴中文网)

    上不慕古,下不肖俗。为疏为懒,不敢为狂。为拙为愚,不敢为恶。/ 微信公众号:一之哥哥
  • TA的每日心情
    开心
    2022-6-2 15:24
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    8

    主题

    43

    帖子

    46

    积分

    初级工程师

    Rank: 4

    积分
    46

    国庆纪念章

    发表于 2021-4-19 23:05:45 | 显示全部楼层
    感谢大佬小白学习中
    回复

    使用道具 举报

    该用户从未签到

    2

    主题

    17

    帖子

    6

    积分

    助理工程师

    Rank: 1

    积分
    6
    发表于 2021-7-14 18:08:40 | 显示全部楼层
    不错不错,第一天看视频,看到了页面添加元素
    回复

    使用道具 举报

    该用户从未签到

    2

    主题

    17

    帖子

    6

    积分

    助理工程师

    Rank: 1

    积分
    6
    发表于 2021-7-14 19:00:06 | 显示全部楼层
    谢谢作者大大,我马上抓紧时间学习!
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    4

    帖子

    3

    积分

    助理工程师

    Rank: 1

    积分
    3
    发表于 2021-9-13 16:53:42 | 显示全部楼层
    例子中的bilibili大概是通过什么方法来监视脚本向网页中添加代码的呢?
    是不是也是用类似addEventListener("DOMNodeInserted", function(event){} )这种方式?
    那我用unsafeWindow.onload=function(){}等加载完再添加按钮可不可行
    回复

    使用道具 举报

  • TA的每日心情

    2022-6-4 20:51
  • 签到天数: 32 天

    [LV.5]常住居民I

    328

    主题

    2880

    帖子

    2890

    积分

    荣誉开发者

    非物质文化遗产社会摇传承人

    Rank: 10Rank: 10Rank: 10

    积分
    2890

    猫咪币纪念章

    发表于 2021-9-13 17:11:39 | 显示全部楼层
    主治医生赵大宝 发表于 2021-9-13 16:53
    例子中的bilibili大概是通过什么方法来监视脚本向网页中添加代码的呢?
    是不是也是用类似addEventListener(" ...

    理论来说能添加上方式不重要
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 49 天

    [LV.5]常住居民I

    138

    主题

    1814

    帖子

    1988

    积分

    管理员

    Rank: 10Rank: 10Rank: 10

    积分
    1988

    猫咪币纪念章热心会员活跃会员突出贡献三好学生中秋纪念章国庆纪念章

    发表于 2021-9-13 17:13:41 | 显示全部楼层
    主治医生赵大宝 发表于 2021-9-13 16:53
    例子中的bilibili大概是通过什么方法来监视脚本向网页中添加代码的呢?
    是不是也是用类似addEventListener(" ...

    unsafeWindow.onload=function(){}

    在本例上不行,插入后,因为b站的逻辑,会重写这一块dom,将插入的进行覆盖
    上不慕古,下不肖俗。为疏为懒,不敢为狂。为拙为愚,不敢为恶。/ 微信公众号:一之哥哥
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    4

    帖子

    3

    积分

    助理工程师

    Rank: 1

    积分
    3
    发表于 2021-9-13 17:22:56 | 显示全部楼层
    王一之 发表于 2021-9-13 17:13
    unsafeWindow.onload=function(){}

    在本例上不行,插入后,因为b站的逻辑,会重写这一块dom,将插入的进 ...

    那我问一下b站是怎么监控的我修改了这一块的dom呢
    回复

    使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 49 天

    [LV.5]常住居民I

    138

    主题

    1814

    帖子

    1988

    积分

    管理员

    Rank: 10Rank: 10Rank: 10

    积分
    1988

    猫咪币纪念章热心会员活跃会员突出贡献三好学生中秋纪念章国庆纪念章

    发表于 2021-9-13 17:33:52 | 显示全部楼层
    主治医生赵大宝 发表于 2021-9-13 17:22
    那我问一下b站是怎么监控的我修改了这一块的dom呢

    这个不清楚,可能和b站用的前端框架有关系了
    上不慕古,下不肖俗。为疏为懒,不敢为狂。为拙为愚,不敢为恶。/ 微信公众号:一之哥哥
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    4

    帖子

    3

    积分

    助理工程师

    Rank: 1

    积分
    3
    发表于 2021-9-13 18:10:55 | 显示全部楼层
    王一之 发表于 2021-9-13 17:33
    这个不清楚,可能和b站用的前端框架有关系了

    谢谢~~~~~~~
    回复

    使用道具 举报

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表