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

【油猴脚本开发指南】魔改sweetalert2支持shadowRoot

[复制链接]
  • TA的每日心情
    慵懒
    18 小时前
  • 签到天数: 811 天

    [LV.10]以坛为家III

    31

    主题

    552

    回帖

    1555

    积分

    荣誉开发者

    积分
    1555

    荣誉开发者新人进步奖油中2周年生态建设者新人报道挑战者 lv2油中3周年喜迎中秋

    发表于 2023-7-24 15:58:16 | 显示全部楼层 | 阅读模式

    前言

    阅读本文前需要有一定原生JS基础

    建议阅读

    基本原理

    [ShadowRoot基本原理]
    https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components/Using_shadow_DOM

    [油猴脚本引用库基本原理]
    https://learn.scriptcat.org/docs/category/%E5%BC%95%E7%94%A8%E5%BA%93%E4%BD%BF%E7%94%A8/

    基本用法

    [油猴脚本开发指南]SweetAlert2的漂亮对话框
    https://bbs.tampermonkey.net.cn/thread-1203-1-1.html

    [油猴脚本开发指南]SweetAlert2进阶
    https://bbs.tampermonkey.net.cn/thread-1303-1-1.html

    为什么要魔改

    油猴脚本属于逆向开发,在原有网站基础上使用脚本管理器及脚本代码对网站原有内容进行修改。
    一般JS库都是为网站正向开发准备的,脚本逆向开发过程中许多需要考虑的要点可能是脚本专属要点,正向开发不会涉及,自然正向开发的JS库也不会考虑。
    因此脚本逆向开发不可避免的会和网站产生冲突,例如JS冲突、CSS冲突,为了消除这种冲突我们就需要对库代码进行修改优化,本文称之为魔改。
    JS冲突由于有脚本沙盒环境,因此我们不必过多考虑。
    而CSS冲突就需要我们自己解决。常见的CSS冲突有脚本CSS主动污染网页CSS以及脚本CSS被动被网页全局CSS污染。为了解决这一冲突,我们可以使用ShadowRoot去隔离脚本CSS以及网页CSS。
    而sweetalert2并未考虑ShadowRoot,所以我们需要帮助他去考虑。

    魔改过程


    (建议分析sweetalert2源码 不详细展开 有空再说)


    sweetalert2中提供了一个选项target="body" //The container element for adding popup into.
    但这并不能支持ShadowRoot,因为在源码中很粗暴的静态定义了多个获取函数均以document.body为基点没有回旋余地。
    但好消息是因为有这个自定义挂载容器选项,意味着我们需要修改的代码不会很多,至少兼容了一半,我们只需要魔改另一半即可。
    既然document.body是静态定义的,那么我们只需要将其修改成动态函数即可
    例如

    // 定义挂载容器
    let target = document.body;
    // 修改挂载容器函数
    const SetTarget = (newTarget) => (target = newTarget);
    // 挂载容器函数
    const GetTarget = () => target;

    创建一个局部变量,默认值为document.body,并为这个局部变量创建2个函数Getter/Setter,并将原始JS中静态定义的document.body替换成GetTarget()
    ,当需要修改挂载容器时调用SetTarget()即可。


    又由于sweetalert2的默认设置target="body",因此为了减少代码量,我们可以使用.mixin()方法,来永久修改默认target,这样就不必要每次都单独设置target

    Swal = Swal.mixin({ target: container })

    ** container为ShadowRoot内挂载节点变量,由于Swal2代码原因必须为ShadowRoot创建一个子元素并将target挂载在子元素上,不能直接为ShadowRoot,否则会产生冲突

    魔改代码

    // ==UserScript==
    // @name        魔改sweetalert2支持shadowRoot
    // @namespace   https://scriptcat.org/
    // @description 有一说一Swal2的动画还是好看的,其他的就算了
    // @version     0.1.0
    // @author      DreamNya
    // @match       https://bbs.tampermonkey.net.cn/
    // @resource    SwalJS   https://cdn.jsdelivr.net/npm/sweetalert2@11.7.20/dist/sweetalert2.js
    // @resource    SwalCSS  https://cdn.jsdelivr.net/npm/sweetalert2@11.7.20/dist/sweetalert2.min.css
    // @grant       unsafeWindow
    // @grant       GM_getResourceText
    // @run-at      document-start
    // ==/UserScript==
    
    // 定义挂载容器
    let target = document.body;
    // 修改挂载容器函数
    const SetTarget = (newTarget) => (target = newTarget);
    // 挂载容器函数
    const GetTarget = () => target;
    
    // 读取 @resource SwalJS 并魔改
    const SwalJS = GM_getResourceText("SwalJS")
        .replace(
            '"undefined"!=typeof window&&/^ru\\b/.test(navigator.language)&&location.host.match(/\\.(ru|su|by|xn--p1ai)$/)',
            "false"
        ) //去除私货
        .replace(/document\.body/g, "GetTarget()"); //重定义容器
    
    // 通过eval引入魔改后的sweetalert js
    eval(SwalJS);
    
    // 读取 @resource SwalCSS 并魔改
    const SwalCSS = GM_getResourceText("SwalCSS").replace(/body/g, "");
    
    // 创建shadowRoot节点
    const div = document.createElement("div");
    const shadowRoot = div.attachShadow({ mode: "open" });
    (document.body || document.firstElementChild).append(div);
    // shadowRoot添加样式
    const style = document.createElement("style");
    style.innerText = SwalCSS;
    shadowRoot.append(style);
    // shadowRoot添加容器
    const container = document.createElement("div");
    container.classList.add(".container");
    shadowRoot.append(container);
    
    // 重定义Swal节点
    SetTarget(container);
    // 配置默认弹出节点为container
    Swal = Swal.mixin({ target: container });
    
    // 暴露变量至网页环境
    unsafeWindow.Swal = Swal;
    
    unsafeWindow.onload = () => Swal.fire("完结撒花", "魔改大成功", "success");
    

    完结撒花

    image.png
    有一说一Swal2的动画还是好看的,其他的就算了,可惜没找到代替库,将就用了。

    已有1人评分油猫币 理由
    朱焱伟 + 7

    查看全部评分 总评分:油猫币 +7 

  • TA的每日心情
    开心
    10 小时前
  • 签到天数: 213 天

    [LV.7]常住居民III

    305

    主题

    4189

    回帖

    4056

    积分

    管理员

    积分
    4056

    管理员荣誉开发者油中2周年生态建设者喜迎中秋油中3周年挑战者 lv2

    发表于 2023-7-25 09:43:20 | 显示全部楼层
    CAT_UI也有呀,我觉得挺好看,也可以自己调整
    上不慕古,下不肖俗。为疏为懒,不敢为狂。为拙为愚,不敢为恶。
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    18 小时前
  • 签到天数: 811 天

    [LV.10]以坛为家III

    31

    主题

    552

    回帖

    1555

    积分

    荣誉开发者

    积分
    1555

    荣誉开发者新人进步奖油中2周年生态建设者新人报道挑战者 lv2油中3周年喜迎中秋

    发表于 2023-7-25 09:48:43 | 显示全部楼层
    王一之 发表于 2023-7-25 09:43
    CAT_UI也有呀,我觉得挺好看,也可以自己调整

    Arco没有动画……不好看【
    Arco没有预设,全要手动弄,实在太麻烦了
    Swal2有弹出动画、关闭动画、图标动画……而且也不大只有60KB,可以作为插件给CAT_UI用,适合我这种懒鬼=-=
    回复

    使用道具 举报

    发表回复

    本版积分规则

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