css 样式隔离-ShadowRoot

作者:Administrator 发布时间: 2024-07-17 阅读量:2 评论数:0

ShadowRoot

Shadow DOM API 的 ShadowRoot 接口是一个 DOM 子树的根节点,它与文档的主 DOM 树分开渲染。

ShadowRoot 的模式——可以是 open 或者 closed。这定义了 shadow root 的内部实现是否可被 JavaScript 访问及修改 — 也就是说

ShadowRoot的特性

7357573D-3784-4D8E-B2FE-9DF9CC7D1995.png

图片来源:掘金(https://juejin.cn/post/6979489951108825095)

1. 自定义的样式和布局:Shadow DOM可以创建一个私有的样式和布局环境,使得组件可以在自己的环境中独立地定义样式和布局,而不会影响到其他组件或页面的样式和布局。

2. 隔离的DOM结构:Shadow DOM可以创建一个私有的DOM结构,使得组件可以在自己的环境中独立地定义DOM结构,而不会影响到其他组件或页面的DOM结构。

3. 嵌套使用:Shadow DOM可以嵌套使用,一个Shadow DOM可以包含另一个Shadow DOM,从而实现更复杂的组件结构。

ShadoRoot 样式/组件隔离

由于Shadow Dom 是一个独立的节点,所以我们可以利用 Shadow Dom 实现样式隔和组件隔离。

ShadowRoot 内事件机制和正常的dom结构一致。但是不管是冒泡还是捕获事件,一旦达到边ShadowHost的时event.targetShadow Host

利用ShadowRoot的特性对插件开发进行优化 (shadowroot使用场景)

chrome插件开发过程之中,如果你使用了像tailwindcss之类的样式库,不难避免遇到样式冲突的问题。

在开发过程中,我们可以利用ShadowRoot的特性,将样式隔离到ShadowRoot中,从而避免样式冲突。

引入样式文件

import style from '@/styles/main.css'

import popupStyle from '@/styles/popup.scss'

这里首先导入了组件依赖的样式文件: main.csspopup.scssmain.css为tailwindcss的样式popup.scss为自定义的组件样式。

Popup.vue中**不必引入样式文件**(因为打包之后样式文件是作用于全局的,无法在shadow root中使用)。

注入样式文件

mountEl 为创建的挂载节点

mountEl.attachShadow({ mode: 'open' }): mountEl下面挂载了一个新创建shadowRoot节点。

vm = createApp(Popup).mount(shadowEl); Popup组件挂载shadowEl中。

mountEl.shadowRoot.appendChild(document.createElement('style')): shadowRoot中添加了一style

shadowEl.querySelector('style').innerHTML = (style + popupStyle): main.csspopup.scss注入shadowRoot中。

这样样式就隔离shadowRoot中了,不会影响到ShadowRoot之外的结构。

code

import style from '@/styles/main.css'

import popupStyle from '@/styles/popup.scss'

import Popup from '@/Popup.vue'

const MOUNT_EL_ID = "oimi-auto-flow";

let mountEl = document.getElementById(MOUNT_EL_ID);

if (mountEl) mountEl.innerHTML = "";

mountEl = document.createElement("div");

mountEl.setAttribute("id", MOUNT_EL_ID);

document.body.appendChild(mountEl)

// create shadow root to isolation style

const shadowEl = mountEl.attachShadow({ mode: 'open' })

// mounted Popup vue component to shadow root

vm = createApp(Popup).mount(shadowEl);

// add style to shadow root

mountEl.shadowRoot.appendChild(document.createElement('style'))

// add popup style and tailwind style to shadow root

shadowEl.querySelector('style').innerHTML = (style + popupStyle);

评论