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

[油猴脚本开发指南]元素规则校验和检测的触发

[复制链接]
  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    632

    主题

    5162

    回帖

    6042

    积分

    管理员

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

    积分
    6042

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

    发表于 2021-11-11 11:11:11 | 显示全部楼层 | 阅读模式

    前言

    本文基于cxxjackie口述而写,请大家观看的时候默念cxxjackie永远的神!

    正文

    在平时我们经常可以碰到一个问题,就是明明设置了输入框或选择框的value,但是点击提交的时候依然会提示没有输入数据,无法正常提交,这是因为元素存在数据校验或者规则校验,我们触发一下规格校验使其正常检测一下就可以运行了,那我们该如何触发数据呢?

    var event = new Event('change');
    element.dispatchEvent(event);

    我们使用new Event('事件名')来生成一个事件


    补充
    根据https://developer.mozilla.org/zh-CN/docs/Web/API/Event/Event
    我们可以知道new Event有第二个参数
    接受bubbles,cancelable,composed
    bubbles代表我们投递到某个元素,此时如果为true,则逐步向上继续触发监听器
    cancelable代表着该event不可被在传递的过程中中途取消
    composed代表如果我们在一个shadow root元素中,此时是否继续向上传递
    如果不理解也没关系,为了更通用推荐全部改为true(cxxjackie墙裂推荐)
    图片.png


    element是我们对应的元素,通过对元素调用dispatchEvent传入事件,即可以正常触发

    我们以

    图片.png

    为例

    图片.png


    Framework监听器的作用
    可以参考https://umaar.com/dev-tips/158-framework-event-listeners/
    以及cxxjackie大佬的发言

    ============================================================
    framework监听器是chrome自己搞出来的,其作用是尝试解析框架的事件委托,比如jQuery的委托,不勾选的话事件会定位到jQuery源码,勾选后有可能定位到源头(实际上没这么智能)。然而框架毕竟多种多样,这种解析很不靠谱,像Vue、React的就完全没用,jQuery视不同版本也可能有bug,像这个例子的change事件估计被定位到别的事件那去了。这玩意我记得以前是没有的,后面不知道哪个版本加进来了,开不开看个人吧, 我的建议是默认不勾选,需要时勾一下看看就好。

    ============================================================

    总结:
    Framework监听器实际就是在使用框架的时候不定位框架源码,直接定位到调用框架的函数的那个位置,但是在现代框架中几乎已经失效了,其他框架也或多或少存在文件,推荐默认不勾选,如果需要的时候再钩一下


    这时候去掉祖先,还剩这些监听器

    通常我们应该注意

    input、change、propertychange

    这里有一个input,我们尝试一下

    图片.png

    可以看到并没有效,我们再试了一下change,也不行,这是为什么呢?难道是我们的理论出错了么?

    并不是,这是因为有的组件会直接监听,而有的组件会存在监听器触发的先后顺序

    前者我们直接之前那样书写即可,而后者,我们需要在触发input监听器之前,先触发其他监听器

    这里应该是focus,因为foucs是聚焦焦点,而blur是失去焦点,焦点就是点击后产生光标

    关于每个监听器的含义大家可以百度一下

    那么我们大概排序一下,可以确定应该是

    focus聚焦

    input输入内容

    change内容改变

    blur取消聚焦

    图片.png

    我们按这个顺序触发,可以发现已经没了检测,所以证明是对的

    注意,这里dispatchEvent的东西是我声明的变量,已经提前new Event('名字')声明好了

    根据多次测试,我们可以知道change没有任何作用

    所以就变成了focus->input->blur即可

    关于Jquery的处理方案

    一部分复古网页依然在使用jquery,如果你window.$能看到金钱符号,并且能在源代码中看到美元.on代码

    我们可以使用

    $._data(对象,'events');

    来获取事件列表,注意,在0.18.0版本之前应该使用data函数,而非_data函数

    图片.png

    可以看到有许多绑定的监听器

    图片.png

    通常我们找到对应的handle处理器即可

    没有任何监听器的时候的处理方案

    我们偶尔会遇到这样的输入框

    图片.png

    这里可以看到事件监听器是没有的

    这时候我们可以尝试使用

        const evt = new Event('change');
        ele.dispatchEvent(evt);
        const prop = Object.keys(ele).find(p => p.startsWith('__reactEventHandlers'));
        ele[prop].onChange(evt);

    该方法为react的,如果这种方式也不行,只能考虑自己查看框架源码找核心注入点进行hook了

    我们来分析一下这种方法

    const evt = new Event('change');

    创建一个事件

    ele.dispatchEvent(evt);

    对其进行事件触发

    const prop = Object.keys(ele).find(p => p.startsWith('__reactEventHandlers'));

    获取元素的所有键名,并通过find函数进行查找,fine函数会根据传入的函数进行判断,返回正确的值,而我们的函数是判断前缀是否是__reactEventHandlers

    ele[prop].onChange(evt);

    获取到对应键名的对象,得到该对象的onchange函数,并且传入event

    我们可以查看一下ele[prop]

    图片.png

    可以看到有onChange,onKeyDown等等

    这些我们都可以进行尝试是否是我们想要的,但是要注意new Event的时候其事件名也要相应的改变

    关于不是一个元素,而是一个元素内包含许多元素的解决方法

    这种情况通常是其中某一个元素的prop内存在相应的方法

    推荐获取该组件最上层的元素,导出prop查看,然后查看children内的prop是否有onchange等字样

    如果有,则打印出来onchange,进入相应函数打断点,尝试是否在修改的组件内容的时候触发了断点

    如果触发则证明是该函数

    则直接传入对应数据即可

    关于React搜索下拉框的处理

    通常我们需要输入一些内容,触发下拉框然后触发点击,这时候就像我们之前所说的

    需要进行组合事件

    比如

    parent[prop].children[0][0].props.onFocus()

    通过最上方组件按child级找到底层哪个进行焦点触发,先进行焦点触发

    input=document.querySelector('#idname input')

    触发焦点后组件才进行input的渲染,这里我们找到input

    input.__reactEventHandlers$xxxx.onChange({target:{value:'1234'}})

    我们对input输入框触发修改,来让其进行搜索

    然后获取返回结果,这里需要进行一定的延时

    list=document.querySelector('.select li')

    获取渲染出来的选择列表

    list.__reactEventHandlersxxx.onClick()

    回调触发选择的样式,完成选择。

    如果不想这样可以参考下面的关于直接在数据修改的方法

    关于Angular的处理方案

    通常其相关元素的xxxx的数组中的callback即为对应的调用代码
    例如文中是
    zone_symbol__inputfalse
    图片.png
    打印可以发现是
    图片.png
    所以我们直接

    $0.__zone_symbol__inputfalse[0].callback({target:{value:"222"}})

    即可触发事件

    关于如何更方便的调试

    建议安装React Developer Tools插件

    可以更简单的查看事件以及属性

    关于我不想做网页点击代码,直接想在数据上进行修改

    这时候我们可以直接在ReactDeveloperTools查看数据的绑定项,然后在代码中做相应的修改

    图片.png

    可以看到这里state的currentItem是存储选择的对象的

    图片.png

    我们可以直接组件的最上级的元素,然后根据存储对象的属性名一层一层往下找,这里可以发现在组件的最上层的元素的react属性的child的owner的memoizedState里存在currentItem属性,所以我们直接设置即可

    但是这里又有一个问题,我们设置了属性,可以发现数据虽然改变了,但是页面没有改变,这是因为我们没有使用选择框进行点击,选择框点击后修改选择框内容,然后修改数据。

    这个问题我目前没有找到很好的办法,即使找到目测也有一定的复杂程度,更推荐修改数据之后顺手innerHtml一下吧,也算挺方便的

    Tips

    但是注意一个问题,如果直接修改属性内容,可能也会导致页面的校验出现问题

    这时候应该调用响应的触发函数并传入修改数据,来完成元素的数据校验

    target.children[0]._owner.memoizedState.currentItem= 数据;

    无法触发响应

    target.children[0]._owner.memoizedProps.onSelected({name: 2002, key: 2002})

    调用相关的函数,并传入对应的数据,可触发响应

    关于React在__reactEventHandlers找不到

    这个时候可以在控制台输入el.__react来看看都有哪些属性

    也可能在__reactProps等属性中有对应的事件

    也可以尝试在__reactFiberxxx.alternate.return.memoizedProps寻找数据

    结语

    那么到这里我们就了解了如何触发组件的校验

    在此感谢cxxjackie

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
  • TA的每日心情
    慵懒
    2022-3-8 11:41
  • 签到天数: 2 天

    [LV.1]初来乍到

    22

    主题

    860

    回帖

    1359

    积分

    荣誉开发者

    积分
    1359

    荣誉开发者卓越贡献油中2周年生态建设者油中3周年挑战者 lv2

    发表于 2021-11-11 12:08:27 | 显示全部楼层
    李恒道 发表于 2021-11-11 11:17
    @cxxjackie 大佬还有啥其他知识点么
    大佬太牛逼了...这个知识根本没接触过

    啊这,谬赞了,这个就是特殊框架特殊处理,没有什么特别的技巧,要说知识点的话每个框架可能都有自己的一套规律,实战还是要具体问题具体分析的。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    632

    主题

    5162

    回帖

    6042

    积分

    管理员

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

    积分
    6042

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

    发表于 2021-11-11 11:17:13 | 显示全部楼层
    @cxxjackie 大佬还有啥其他知识点么
    大佬太牛逼了...这个知识根本没接触过
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2022-7-5 00:02
  • 签到天数: 124 天

    [LV.7]常住居民III

    5

    主题

    170

    回帖

    927

    积分

    版主

    积分
    927

    荣誉开发者油中2周年

    发表于 2021-11-11 12:46:36 | 显示全部楼层
    李恒道
    d=====( ̄▽ ̄*)b👍
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    632

    主题

    5162

    回帖

    6042

    积分

    管理员

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

    积分
    6042

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

    发表于 2021-11-11 13:06:32 | 显示全部楼层
    cxxjackie 发表于 2021-11-11 12:08
    啊这,谬赞了,这个就是特殊框架特殊处理,没有什么特别的技巧,要说知识点的话每个框架可能都有自己的一 ...

    我很好奇哥哥是咋知道这个的...翻源码了还是之前别人讲过鸭
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2022-3-8 11:41
  • 签到天数: 2 天

    [LV.1]初来乍到

    22

    主题

    860

    回帖

    1359

    积分

    荣誉开发者

    积分
    1359

    荣誉开发者卓越贡献油中2周年生态建设者油中3周年挑战者 lv2

    发表于 2021-11-11 20:28:51 | 显示全部楼层
    李恒道 发表于 2021-11-11 13:06
    我很好奇哥哥是咋知道这个的...翻源码了还是之前别人讲过鸭

    因为之前接触过几个react的页面,我做那个全局属性的脚本时又发现了不少东西,然后翻了一些文章+自己总结的。另外这么一说我又想起来,jquery可以通过$._data(ele, 'events')来获取到事件,这个应该知道的人比较多。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    632

    主题

    5162

    回帖

    6042

    积分

    管理员

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

    积分
    6042

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

    发表于 2021-11-12 11:57:05 | 显示全部楼层
    cxxjackie 发表于 2021-11-11 20:28
    因为之前接触过几个react的页面,我做那个全局属性的脚本时又发现了不少东西,然后翻了一些文章+自己总结 ...

    哥哥牛逼!
    又get一个
    我学前端的时候已经大部分vue了...jq基本没用过

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    632

    主题

    5162

    回帖

    6042

    积分

    管理员

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

    积分
    6042

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

    发表于 2021-11-12 16:55:08 | 显示全部楼层
    cxxjackie 发表于 2021-11-11 12:08
    啊这,谬赞了,这个就是特殊框架特殊处理,没有什么特别的技巧,要说知识点的话每个框架可能都有自己的一 ...

    大佬,又遇到一个问题!
    我碰到一个组合式的输入框
    大概是点击之后触发一个input,然后搜索,点击菜单项再在输入框里显示出来
    我是这样处理的,不知道对不对

    parent[prop].children[0][0].props.onFocus()

    通过最上方组件按child级找到底层哪个进行焦点触发,先进行焦点触发

    input=document.querySelector('#idname input')

    触发焦点后组件才进行input的渲染,这里我们找到input

    input.__reactEventHandlers$xxxx.onChange({target:{value:'1234'}})

    我们对input输入框触发修改,来让其进行搜索

    然后获取返回结果,这里需要进行一定的延时

    list=document.querySelector('.select li')

    获取渲染出来的选择列表

    list.__reactEventHandlersxxx.onClick()

    回调触发选择的样式,完成选择。

    感觉好麻烦啊...
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2022-3-8 11:41
  • 签到天数: 2 天

    [LV.1]初来乍到

    22

    主题

    860

    回帖

    1359

    积分

    荣誉开发者

    积分
    1359

    荣誉开发者卓越贡献油中2周年生态建设者油中3周年挑战者 lv2

    发表于 2021-11-12 20:28:22 | 显示全部楼层
    李恒道 发表于 2021-11-12 16:55
    大佬,又遇到一个问题!
    我碰到一个组合式的输入框
    大概是点击之后触发一个input,然后搜索,点击菜单项 ...

    这个也不算麻烦吧,就算没有框架,正常用dispatchEvent也是差不多的流程,要说有什么可以优化的地方就是这个__reactEventHandlers$xxxx的属性名应该都是一样的,只需要查找一次保存起来就行了。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    632

    主题

    5162

    回帖

    6042

    积分

    管理员

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

    积分
    6042

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

    发表于 2021-11-12 20:43:20 | 显示全部楼层
    cxxjackie 发表于 2021-11-12 20:28
    这个也不算麻烦吧,就算没有框架,正常用dispatchEvent也是差不多的流程,要说有什么可以优化的地方就是 ...

    组件dom元素过多
    找onfucs
    onchange
    onclick什么的太卧槽了
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

    发表回复

    本版积分规则

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