Open Shadow 与 Closed Shadow 有什么区别
适合公众号,承接前面两篇系列文章,精简清晰,可以单独作为短文/知识点卡片
【开头导语】 在前面两篇文章里,我们反复提到 Open Shadow、Closed Shadow,也是自动化踩坑的核心根源。很多人分不清二者到底差在哪,今天用一张对比表 + 通俗解释讲清楚,以后看到 #shadow-root(open) 和 #shadow-root(closed) 立刻知道该怎么写代码。
创建方式只有 mode 字段不一样:
// Open
host.attachShadow({ mode: 'open' })
// Closed
host.attachShadow({ mode: 'closed' })
核心区别一览
| 对比项 | Open Shadow | Closed Shadow |
|---|---|---|
| 获取影子根 | host.shadowRoot ✅ 可以拿到 | host.shadowRoot ❌ 返回 null |
| 页面JS访问内部DOM | 可以通过 shadowRoot 继续 querySelector | 页面JS无法拿到影子根引用,常规查询失效 |
| Playwright locator | ✅ 原生自动穿透,直接CSS选择器定位 | ❌ 原生locator无法穿透,需要递归遍历DOM |
| 设计目的 | 隔离样式,但保留脚本访问能力 | 强隔离,防止外部JS随意读取、修改内部DOM |
| 使用场景 | 业务WebComponent、UI组件库 | Chrome插件面板、一些防篡改第三方组件(卖家精灵) |
| 开发者工具 | F12 都能看到内部节点 | F12 同样可以看到,只是页面JS拿不到引用 |
通俗理解
- Open Shadow:带锁但给了你钥匙 样式是隔离的,不会和外面互相污染;但是外部JS可以拿到 shadowRoot,进去读取、修改里面的元素。Playwright 原生支持直接定位,写代码最简单。
- Closed Shadow:上锁,钥匙不给页面JS 样式同样隔离。浏览器不会把 shadowRoot 暴露给页面上下文 JS。 重点误区:不是浏览器藏起来看不见!只是页面JS拿不到入口引用。 浏览器内核、CDP协议、F12开发者工具依然能看到完整DOM,这也是我们递归遍历方案可行的底层原因。
自动化实操重点(划重点)
- 看到
#shadow-root (open):直接用page.locator(),正常写CSS选择器就行; - 看到
#shadow-root (closed):locator、evaluate 里直接 querySelector 全部失效,要用递归遍历所有节点、递归进入 shadowRoot 的方案; - XPath:两种模式都不能穿透 shadow 边界,不要用XPath找shadow内部元素;
- Chrome插件(卖家精灵等)绝大多数是 Closed Shadow + isolated world 独立执行环境,坑会更多,甚至找到元素后click被拦截。
简短Demo 自测
<div id="openHost"></div>
<div id="closedHost"></div>
<script>
const openHost = document.querySelector('#openHost');
const openSr = openHost.attachShadow({mode:'open'});
openSr.innerHTML = `<button>Open按钮</button>`;
console.log('open shadowRoot:', openHost.shadowRoot); // 有值
const closedHost = document.querySelector('#closedHost');
const closedSr = closedHost.attachShadow({mode:'closed'});
closedSr.innerHTML = `<button>Closed按钮</button>`;
console.log('closed shadowRoot:', closedHost.shadowRoot); // null
</script>
【文末引导】 这个知识点是处理插件自动化的基础。理解二者差异,你就知道什么时候可以简单写locator、什么时候必须上递归查找方案。 前面配套两篇,一篇讲原理、一篇给完整Playwright实战代码,需要的可以翻看系列文章。 你平时做自动化有没有遇到其他ShadowDOM的奇葩坑?评论区一起交流。
系列回顾: 《ShadowRoot 到底是什么?》 《Playwright 踩坑:Closed ShadowDOM 元素定位终极方案》
公众号标签:#ShadowDOM #Playwright #浏览器自动化
