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

脚本猫UI库初版

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

    [LV.10]以坛为家III

    31

    主题

    552

    回帖

    1555

    积分

    荣誉开发者

    积分
    1555

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

    发表于 2023-7-3 17:17:58 | 显示全部楼层

    本帖最后由 steven026 于 2023-7-3 17:19 编辑

    cxxjackie 发表于 2023-6-29 23:02

    这个我看过了,没有摆脱React依赖,我还是更想要一个原生的,因为创建元素和绑定数据这些都不难,搞一个R ...

    摆脱React依赖目前来说实在是有点困难了……
    毕竟这样从样式、渲染、响应之类的全要自己去实现,现在用的arco.design UI库,一共有6、70个组件,每个组件还有不同的API方法,UI库的底层用的就是React,如果要摆脱React依赖实现这些功能的代码量估计要爆炸
    目前还是打算直接用React+Arco,把框架的API暴露出来,直接调用框架的样式、调用React创建元素、渲染、响应,相当于是把UI框架优化一遍,转换成脚本猫(或者其他脚本管理器)能用的脚本逆向UI框架(利用shadowroot,不与页面原有框架冲突,不会主动污染页面样式,也不会被页面的全局样式污染)
    目前打算先这样试试水,说不定后期成熟了可能还可以切换框架(……随便想想)


    之前哥哥看到的函数式是一之哥哥写的,他是预计将所有组件都自行封装一遍,直接让用0户调用。
    优点是

    • 组件调用起来方便
    • 底层实现直接是TSX,不存在兼容问题
    • 后续可能可以通过d.ts实现代码提示补全……

    缺点是

    • 所有组件(包括组件的子组件)都要手动封装一遍,加大UI库开发难度
    • 组件调用起来可能会形成嵌套地狱。

    而且我在静态封装的时候越封装越觉得这条路有点歪,因为为了实现一些组件的API,需要把这些API都重新封装一遍,这究竟是框架API还是库API……
    因此我尝试了用Object.assign的方法, 想要动态封装减少代码量,不去主动修改API,只将组件暴露出来,所有调用方法都是框架原生的方法


    然后我就打算换一种形式去实现,把JSX文本转成AST再转成React.createElement,然后通过eval或者new Function去实现
    一开始用的Babel,结果发现Babel没有ts版本的按需导出,core方法只有standalone版本能用,而standalone实在是太大了2.7MB,甚至比这个库还大出将近一倍,实在是下下策。无奈翻了很久github(可能是UI库的这种需求几乎没有,都找不到现成的例子),终于找到一个压缩完只有10KB左右的库jsxLoader,虽然作者说有点小瑕疵,但终究是能用,比Babel小了几百倍。
    目前JSX文本式方法算是基本实现了,只有偶尔几个API需要额外单独优化一下,其余基本还是直接调用UI框架的原生API。

    但是也存在一些问题

    • (一开始用的eval,但是存在作用域问题,后来发现了哥哥写的传递参数,感觉很好,参考了哥哥的方案,改成了new Function+解构,实现了传参),
      但是这个方法也存在缺陷new Function/eval可能会被一些页面的CSP策略所禁止,
    • 然后文本的话可能会加大脚本开发难度,参数要手动传递,没法获取上下文,
      而且文本难以自动提示(写vscode插件可能太麻烦了,然后脚本猫插件的monaco编辑器里又可能没法用)
    • 有些方法不太好封装,需要用到React或者ReactDOM的方法去实现
      依赖jsxLoader不清楚实际上会不会遇到作者说的瑕疵,至少目前暂时没遇到……

    好处可能是

    • 开发简单,现在代码只写了1~200行基本大致实现了(后续可能需要单独优化几个特殊API)
    • 熟练的人写起来比较方便,直接用JSX方法写成文本形式就行,改动起来也略微方便(如果用vscode之类的编辑器的话)

    不知道哥哥对此有啥看法
    我的设想是两条路线互不冲突,可以混用
    函数式直接CAT_UI.XXXX静态调用;
    文本式需要new class动态调用const cat=CAT_UI;cat.createApp(jsx)


    最后说一下写这个脚本库的初衷,一是我自己有用的需求,毕竟有需求才有开发动力(一之哥哥是为了吸引更多人用脚本猫😄),二是为了降低门槛,让更多的人也能一起用。
    很多脚本(尤其是中小型脚本)都没有自己的UI交互界面,并不是不需要UI交互界面,只是因为开发成本过高,不如不去开发。
    脚本的UI开发实在是太麻烦了,样式、渲染、响应都要自己实现,写这个脚本UI库的初衷是降低开发门槛,人人都能用这个库去快速编写UI交互界面,让更多脚本拥有UI交互界面,提高开发体验、用户体验。(目前只完成了基础组件,后续可能会将这些组件封装出一个中级组件模板供微调后直接使用)
    主流的UI框架都是为正向开发准备的,我试过好几个框架都不支持shadowroot,差一点的框架根本不考虑样式冲突,好一点的框架会写作用域不主动去污染其他框架,但是在一些技术比较差的网站页面里会被页面的全局样式污染,我找了很多框架都没法满足这个需求。后来萌生出了自己魔改框架的想法,奈何技术太差魔改失败,后来求助一之哥哥,一之哥哥竟然说好【……
    然后就是一之哥哥写底层,我在其基础上进行优化。

    目前打包出来的库经过最小化处理大概还有2.2MB(React+Acro基础大约1MB,Acro图标组件大约400KB,剩余组件加起来800KB),大小确实是个问题,可能需要后续拆分一些组件、功能,减少体积,按需导出。

    函数式主分支(剩余组件有待封装):https://github.com/scriptscat/lib
    JSX文本方法分支(大致成型):https://github.com/DreamNya/lib/tree/DOG_UI

    (写太多了……有点意识模糊了,写到后面有点语无伦次了,都忘记一开始想写什么了,不知道哥哥有没有理解,希望哥哥见谅)

    回复
    订阅

    使用道具 举报

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

    [LV.7]常住居民III

    305

    主题

    4189

    回帖

    4056

    积分

    管理员

    积分
    4056

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

    发表于 2023-7-3 17:32:04 | 显示全部楼层

    steven026 发表于 2023-7-3 17:17

    [md]> cxxjackie 发表于 2023-6-29 23:02
    ...

    所有组件(包括组件的子组件)都要手动封装一遍,加大UI库开发难度

    一方面是我写的问题,简单的大部分都是直接return,这些可以批量封起来

    另外一些是得特殊处理,不管用啥方式,该特殊处理还是要特殊处理

    https://github.com/scriptscat/lib/blob/main/src/ui/ui.tsx#L91


    组件调用起来可能会形成嵌套地狱

    这个都会有吧


    关于ast方式我一直是持反对态度的,哥哥都举出这么多缺点了,不过哥哥都实现了,我也不说了,反正哥哥搞

    上不慕古,下不肖俗。为疏为懒,不敢为狂。为拙为愚,不敢为恶。
    回复

    使用道具 举报

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

    [LV.1]初来乍到

    22

    主题

    881

    回帖

    1379

    积分

    荣誉开发者

    积分
    1379

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

    发表于 2023-7-3 23:02:31 | 显示全部楼层
    steven026 发表于 2023-7-3 17:17
    [md]> [cxxjackie 发表于 2023-6-29 23:02](forum.php?mod=redirect&goto=findpost&pid=64197&ptid=4723)
    > ...

    我之所以反对React除了体积问题,还有一个是会模糊UI库的定位,库变成了React的二次封装,有人用着别扭的不如直接去引用React,有人想要轻量级的结果发现比React还大,这让库更多适用于不知道怎么写的新手,对于成熟脚本可能不是一个理想的方案。
    函数式我认为可以保留,jsx的做成插件形式就行了,解决体积问题也可以做插件,把库一些占用较大的组件分离出来让用户按需引入,可以一定程度上缓解问题。如果注定要依赖React,那甚至库本身也可以是插件,提供一个打包后的React,引用库需要先引用React,这样做的好处是假如页面本身有React,那可以直接套用以减少体积,还有React也可以单独引入来满足部分人的开发需求。
    我写的那个传值其实双向绑定这块有点问题,因为不确定库要怎么实现就没做,要参考的话最好注意一下。还有jsx解析为什么不考虑DOMParser呢?原生的方式效果好体积小,可定制化程度也高,如果是因为一些特殊符号DOMParser报错的话,可以对字符串做一下预处理,参考我用正则加引号的做法。
    回复

    使用道具 举报

    12
    返回列表 发新帖

    发表回复

    本版积分规则

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