yzqdev 发表于 2024-5-4 18:17:03

油猴脚本使用shadowDom添加界面并引入样式

ShadowDom是个好东西,可以隔离组件防止自己的组件被网站商店css,js啥的污染,所以编写油猴脚本添加自己的div时就可以放心的写样式,不用担心样式问题了

> 然而通常`import './app.css'` , css module, css in js ,tailwind等所生成的样式都是全局的,无法应用到shadowDom里面,这该怎么办呢?(我也很想知道,我想用tailwind啊)


其实style-components和emotioncss都有自己的api,可以把样式注入到任何位置,这样就不用担心样式在全局导致shadowDom样式不生效了,示例代码如下

main.tsx
```js
import { App } from "./App";
import { createRoot } from "react-dom/client";
import { StyleProvider } from "@ant-design/cssinjs";
import { StyleSheetManager } from "styled-components";


(function () {
const container = document.createElement("div");
container.id = "shadowContainer";

//创建shadowdom
const shadowDom = container.attachShadow({ mode: "open" });
const root = document.createElement("div");
shadowDom.appendChild(root);

//把dom附加到body去
document.body.appendChild(container);
const app = createRoot(root);
// mount react app
app.render(
    <StyleSheetManager target={shadowDom}>
      <StyleProvider container={shadowDom}>
      <App />
      </StyleProvider>
    </StyleSheetManager>
);
})();

```

其中target就是style-component指定把style注入到dom的哪个位置,直接注入shadowoDom也是可以的

App.tsx
```js

import { Button } from "antd";

import styled,{ css } from "styled-components";

const head=css`
position:fixed;
top: 0;
left: 0;
`
const Container = styled.div`
background-color: red;
color: white;
width: 200px;
border: 1px solid red;
height:200px;

&:hover {
    border-color: blue;
}
`;
export function App( ){

return (
   
      <div className={head}>
      hello
      <Button >aaa</Button>
      <Container></Container>
      </div>

);
}

```

效果如图,样式进入了shadowdom
!(data/attachment/forum/202405/04/180911r66jrgcptos9voj6.png)



各位大佬有什么好的办法在油猴脚本中使用shadowdom并添加css呢?

李恒道 发表于 2024-5-5 08:07:04

直接先下下来CSS然后创建shaodw通过原生网里写也可以吧

yzqdev 发表于 2024-5-6 15:16:25

> [李恒道 发表于 2024-5-5 08:07](forum.php?mod=redirect&goto=findpost&pid=81516&ptid=6981)
> > 直接先下下来CSS然后创建shaodw通过原生网里写也可以吧

想的是直接使用cssmodule, tailwind, cssinjs,或者直接`import './app.scss'`之类的用法;
shadowdom得手动创建style元素,然后把css文本扔进去,或者使用
`<link href="http://localhost:8080/a.css" rel="stylesheet">`这种,就很麻烦,开发的时候不爽

李恒道 发表于 2024-5-6 15:26:32

yzqdev 发表于 2024-5-6 15:16
> [李恒道 发表于 2024-5-5 08:07](forum.php?mod=redirect&goto=findpost&pid=81516&ptid=6981)
> >...

这种应该需要自己写shadow的css解析问题了

感觉可以试一下https://stackoverflow.com/questions/60659473/inject-css-styles-to-shadow-root-via-webpack


有一种方法可以用于style-loader此目的
这一切都取决于执行顺序。你的index.tsx被执行后style-loader::insert。但影子根之前必须存在。

最简单的方法是修改index.html.

这是一个完整的示例:

./src/index.html

...
<body>
    <div id="root"></div>
    <script>
      <!-- This gets executed before any other script. -->
      document.querySelector("#root").attachShadow({ mode: 'open' })
    </script>
</body>
...
./webpack.config.js

var HtmlWebpackPlugin = require('html-webpack-plugin');

const cssRegex = /\.css$/i

const customStyleLoader = {
loader: 'style-loader',
options: {
    insert: function (linkTag) {
      const parent = document.querySelector('#root').shadowRoot
      parent.appendChild(linkTag)
    },
},
}

module.exports = {
module: {
    rules: [
      {
      test: cssRegex,
      use: [
          customStyleLoader,
          'css-loader'
      ],
      },
    ],
},

plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
],
};

yzqdev 发表于 2024-5-6 15:42:34

本帖最后由 yzqdev 于 2024-5-6 15:44 编辑

> [李恒道 发表于 2024-5-6 15:26](forum.php?mod=redirect&goto=findpost&pid=81606&ptid=6981)
> > 这种应该需要自己写shadow的css解析问题了

感觉可以试一下https://stackoverflow.com/questions/6065947 ...

各种方法我都搜过了,就cssinjs设置注入到shadowdom这个体验跟正常一样,比如大佬这个方法,油猴脚本都是动态添加的,没法用style-loader的这个insert-into;
网上另外一种方法就是通过xxx-loader把引入的css变成字符串,手动创建style元素,然后把css文本扔进去
```js
import styleText from './style.scss';

const style = document.createElement('style');
style.appendChild(document.createTextNode(styleText));
shadow.appendChild(style)
```


我再搜搜看有没有tailwindcss和cssmodule用在shaowdom上的解决方案

李恒道 发表于 2024-5-6 15:47:12

yzqdev 发表于 2024-5-6 15:42
> [李恒道 发表于 2024-5-6 15:26](forum.php?mod=redirect&goto=findpost&pid=81606&ptid=6981)
> >...

打包webpack会走loader,哥哥的意思是在油猴的头上声明然后自动引入?

yzqdev 发表于 2024-5-6 16:10:03

李恒道 发表于 2024-5-6 15:47
打包webpack会走loader,哥哥的意思是在油猴的头上声明然后自动引入?

我这里使用webpack打包都是把css打包进xxx.user.js的不引入外部css


听了哥哥的说法,我想到了另一种方法:

把自己的脚本js和css分离开,然后把css传到云端,比如使用cdn,接下来shadowDom里面就可以引用了

```js

// @resource   customCSS https://xxx.com/a.css
// @grant      GM_addStyle
// @grant      GM_getResourceText
// ==/UserScript==


//第一种

const styleEl = document.createElement('link')
styleEl.setAttribute('rel', 'stylesheet')
styleEl.setAttribute('href', 'https://xx.com/a.css' )
shadowDOM.appendChild(styleEl)

//第二种
const newCSS = GM_getResourceText ("customCSS");
const style = document.createElement('style');
style.appendChild(document.createTextNode(newCSS));
shadow.appendChild(style)

```

李恒道 发表于 2024-5-6 16:12:38

yzqdev 发表于 2024-5-6 16:10
我这里使用webpack打包都是把css打包进xxx.user.js的不引入外部css




确实也是方法
我在想能不能提供一个header的parser工具
来方便大家在头上做文章

yzqdev 发表于 2024-5-6 16:21:23

> [李恒道 发表于 2024-5-6 16:12](forum.php?mod=redirect&goto=findpost&pid=81616&ptid=6981)
> > 确实也是方法
我在想能不能提供一个header的parser工具
来方便大家在头上做文章 ...

类似这种吗
(https://github.com/scriptscat/scriptcat-webpack-plugin)
(https://github.com/momocow/webpack-userscript)
(https://github.com/trim21/userscript-metadata-webpack-plugin)


我感觉(https://github.com/lisonge/vite-plugin-monkey)已经完全够用了,开发体验最爽
页: [1]
查看完整版本: 油猴脚本使用shadowDom添加界面并引入样式