[油猴脚本开发指南]shadowroot基础介绍
# ShadowRoot我们可以参考MDN
https://developer.mozilla.org/zh-CN/docs/Web/API/ShadowRoot
Shadow DOM API 的 ShadowRoot 接口是一个 DOM 子树的根节点, 它与文档的主 DOM 树分开渲染。
说白了
ShadowRoot技术就是在一个dom树下创建一个隔离的封闭的空间
用来隔绝网页的一些污染,让html实现一些模块化的思想
创建类似html元素标签的封闭html块
其目的个人推测
是因为浏览器随着时代逐渐发展
会不断的拓展一些新功能
这时候普通用户可以使用ShadowRoot技术以及以前其他浏览器技术
用来创建一些基础的html标签等等
其一是方便用户开发和隔离污染
其二是一旦某种ShadowRoot元素在全世界受到广泛的欢迎
浏览器可以无缝过度实现该功能
并且即使浏览器没有实现
也可以利用ShadowRoot来实现进行发布和测试
其想法来源于
```
Shadow DOM removes the brittleness of building web apps. The brittleness comes from the global nature of HTML, CSS, and JS. Over the years we've invented an exorbitant number of tools to circumvent the issues. For example, when you use a new HTML id/class, there's no telling if it will conflict with an existing name used by the page. Subtle bugs creep up, CSS specificity becomes a huge issue (!important all the things!), style selectors grow out of control, and performance can suffer. The list goes on.
Shadow DOM fixes CSS and DOM. It introduces scoped styles to the web platform. Without tools or naming conventions, you can bundle CSS with markup, hide implementation details, and author self-contained components in vanilla JavaScript.
```
# 实践
ShadowRoot使用Element.attachShadow()函数进行创建
创建后的一些数据
我们通常对元素的Element.shadowRoot属性进行读取
那么我们实践一下
首先创建一个没有shadow的一个页面,大家应该都非常了解了
![图片.png](data/attachment/forum/202206/01/154204i8vh6riqvhiqft22.png)
![图片.png](data/attachment/forum/202206/01/154209cofl5jvjiffgvfzf.png)
然后我们将其改造成ShadowRoot模式
我们查看一下attachShadow函数
var shadowroot = element.attachShadow(shadowRootInit);
通过attachShadow创建后,返回一个shadowroot对象或null
而attachShadow传入一个shadowRootInit对象
shadowRootInit对象有两个参数
mode 模式 字符串
有两个参数,一个是open,一个是closed
如果是为open,则从可以外部获得字符串
如果是为close,则从外部无法获得字符串,只能从返回的引用中获取
delegatesFocus 焦点委托
这个据说是提高焦点性能问题,以及点击不可点击的可以转移到第一个可以点击的焦点参数
该参数拓展了元素的焦点行为,除了点击不可点击的可以转移到第一个可以点击的焦点外,当shadow dom中的节点获取焦点时,除了焦点元素有focus外,附加shadowdom的宿主(host)元素将也会被应用上focus。
资料来源https://web.dev/shadowdom-v1/#focus
因为delegatesFocus在平时并不常用,所以这里就不尝试了(由于没有尝试,所以上述资料请自行辨别真假)
我们可以实践一下代码
```html
<body>
<div class="wrap">
</div>
</body>
<script>
let shadow= document.querySelector('.wrap').attachShadow({mode: 'open'})
shadow.innerHTML=` <span>我是ShadowRoot</span>`
</script>
```
![图片.png](data/attachment/forum/202206/01/160023a7mtiip4pj45nklk.png)
这里可以看到显示了shadow-root
![图片.png](data/attachment/forum/202206/01/160028ljtfsy0sfrw7ysj7.png)
我们也可以根据shadow的宿主元素找到shadowRoot然后innerHTML读取
![图片.png](data/attachment/forum/202206/01/160050yrucr511irzircyt.png)
但是如果将其改为closed
![图片.png](data/attachment/forum/202206/01/160133goqia73gwvvsgx7b.png)
那么在页面中根本拿不到了shadowRoot属性,而且控制器里也显示closed
![图片.png](data/attachment/forum/202206/01/160141u4zoccfx9fxtea67.png)
如果我们将attach的函数返回的sahdow对象放置到windows上
![图片.png](data/attachment/forum/202206/01/160239nmyfzfzrgyx1mc9s.png)
可以发现这时候是可以拿到的
![图片.png](data/attachment/forum/202206/01/160246s6yu31jxyqz7cjjh.png)
那么我们总结一下
1.如果是open状态可以直接根据宿主元素拿到shadowroot对象然后拿innerhtml等
2.如果是closed对象,只能拿到创建时返回的应用才可以进一步操作shadow内对象
如果我们想要解决页面的shadowroot的问题,有两种方式
1.直接针对attachShadow函数进行劫持,将所有的创建的shadow都改成open模式
```
let old=Element.prototype.attachShadow
Element.prototype.attachShadow=function(...args){
args.mode='open'
return old.call(this,...args)
}
```
1.1更优秀的解决办法,来自cxxjackie
我们可以调用old后拿到了shadowRoot引用对象
然后赋值到元素的_shadowRoot属性上
这样就可以在不破坏原有的参数
以及closed的mode模式的情况下
拿到引用!
```
let old=Element.prototype.attachShadow
Element.prototype.attachShadow=function(...args){
const shadowRoot = old.call(this, ...args);
this._shadowRoot = shadowRoot;
return shadowRoot;
}
```
2.分析页面拿到attachShadow函数返回的对象
这个具体情况具体分析
暂且不表
那么我们这节课就算完成了
# 结语
撒花~ 油猴 king! 王一之 发表于 2022-6-1 17:11
油猴 king!
我是要成为豆油美猴王的男人! gg学到了! 劫持这样感觉好一点,尽量不破坏原有的设计:
const shadowRoot = old.call(this, ...args);
this._shadowRoot = shadowRoot;
return shadowRoot; cxxjackie 发表于 2022-6-1 20:35
劫持这样感觉好一点,尽量不破坏原有的设计:
品到了!明天改一下!
这个确实是好思路 cxxjackie 发表于 2022-6-1 20:35
劫持这样感觉好一点,尽量不破坏原有的设计:
现在加上了!
大佬牛逼!
我写的时候其实就感觉脏
但是没想到这个好办法 李恒道 发表于 2022-6-1 20:47
现在加上了!
大佬牛逼!
我写的时候其实就感觉脏
只是一点微小的改动,不要尬吹不要尬吹。 cxxjackie 发表于 2022-6-2 11:05
只是一点微小的改动,不要尬吹不要尬吹。
话说大佬对Ts学的好吗
我对基础ts是理解的
但是碰到很好的精品项目或者框架的ts
直接升天
感觉有一些鸿沟
但是不知道怎么补
大佬有经验吗 李恒道 发表于 2022-6-2 14:05
话说大佬对Ts学的好吗
我对基础ts是理解的
但是碰到很好的精品项目或者框架的ts
ts的问题还是问一之大佬吧,我更习惯用js写。
页:
[1]