fix shadow dom

This commit is contained in:
Gabe Yuan
2023-08-24 14:57:54 +08:00
parent 792a1bfcad
commit a2762e6ce6
3 changed files with 78 additions and 40 deletions

View File

@@ -21,6 +21,7 @@
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root">
<h2>React is a JavaScript library for building user interfaces.</h2>
<div id="addtitle"></div>
<h2>Shadow 1</h2>
<div id="shadow1"></div>
<br />
@@ -236,13 +237,28 @@
To create a production bundle, use `npm run build` or `yarn build`.
-->
<script>
for (var i = 1; i <= 2; i++) {
var shadow = document.querySelector("#shadow" + i);
var cont = document.querySelector(".cont" + i);
var root = shadow.attachShadow({ mode: "open" });
// root.appendChild(document.importNode(cont, true));
root.appendChild(cont.cloneNode(true));
}
setTimeout(function () {
for (var i = 1; i <= 2; i++) {
var shadow = document.querySelector("#shadow" + i);
var cont = document.querySelector(".cont" + i);
var root = shadow.attachShadow({ mode: "open" });
// root.appendChild(document.importNode(cont, true));
root.appendChild(cont.cloneNode(true));
var newLine = document.createElement("p");
newLine.innerText = "new line";
root.appendChild(newLine);
}
}, 3000);
</script>
<script>
setTimeout(function () {
var el = document.querySelector("h2");
el.innerText = "hello world";
var title = document.querySelector("#addtitle");
title.innerHTML = "<p>second title</p>";
}, 1000);
</script>
</body>
</html>

View File

@@ -10,21 +10,7 @@ import {
} from "../config";
import Content from "../views/Content";
import { fetchUpdate, fetchClear } from "./fetch";
/**
* 获取节点列表并转为数组
* @param {*} selector
* @param {*} rootNode
* @returns
*/
function queryNodes(selector, rootNode = document) {
const childRoots = Array.from(rootNode.querySelectorAll("*"))
.map((item) => item.shadowRoot)
.filter(Boolean);
const childNodes = childRoots.map((item) => queryNodes(selector, item));
const nodes = Array.from(rootNode.querySelectorAll(selector));
return nodes.concat(childNodes).flat();
}
import { debounce } from "./utils";
/**
* 翻译类
@@ -33,6 +19,7 @@ export class Translator {
_rule = {};
_minLength = 0;
_maxLength = 0;
_skipNodeNames = [APP_LCNAME, "style", "svg", "img"];
// 显示
_interseObserver = new IntersectionObserver(
@@ -52,20 +39,35 @@ export class Translator {
// 变化
_mutaObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
try {
queryNodes(this.rule.selector, node).forEach((el) => {
this._interseObserver.observe(el);
});
} catch (err) {
//
if (
mutation.target.localName !== APP_LCNAME &&
mutation.addedNodes.length > 0
) {
const addedNodes = Array.from(mutation.addedNodes).filter((node) => {
if (!this._skipNodeNames.includes(node.localName)) {
return true;
}
return false;
});
if (addedNodes.length > 0) {
this._reTranslate();
}
});
}
});
});
_overrideAttachShadow = () => {
const _this = this;
const _attachShadow = HTMLElement.prototype.attachShadow;
HTMLElement.prototype.attachShadow = function () {
_this._reTranslate();
return _attachShadow.apply(this, arguments);
};
};
constructor(rule, { fetchInterval, fetchLimit, minLength, maxLength }) {
fetchUpdate(fetchInterval, fetchLimit);
this._overrideAttachShadow();
this._minLength = minLength ?? TRANS_MIN_LENGTH;
this._maxLength = maxLength ?? TRANS_MAX_LENGTH;
this.rule = rule;
@@ -116,16 +118,27 @@ export class Translator {
this.rule = { ...this.rule, textStyle };
};
_queryNodes = (rootNode = document) => {
const childRoots = Array.from(rootNode.querySelectorAll("*"))
.map((item) => item.shadowRoot)
.filter(Boolean);
const childNodes = childRoots.map((item) => this._queryNodes(item));
const nodes = Array.from(rootNode.querySelectorAll(this.rule.selector));
return nodes.concat(childNodes).flat();
};
_register = () => {
// 监听节点变化;
this._mutaObserver.disconnect();
this._mutaObserver.observe(document, {
childList: true,
subtree: true,
characterData: true,
// characterData: true,
});
// 监听节点显示
queryNodes(this.rule.selector).forEach((el) => {
this._queryNodes().forEach((el) => {
this._interseObserver.unobserve(el);
this._interseObserver.observe(el);
});
};
@@ -135,12 +148,10 @@ export class Translator {
this._mutaObserver.disconnect();
// 解除节点显示监听
queryNodes(this.rule.selector).forEach((el) =>
this._interseObserver.unobserve(el)
);
this._queryNodes().forEach((el) => this._interseObserver.unobserve(el));
// 移除已插入元素
queryNodes(this.rule.selector).forEach((el) => {
this._queryNodes().forEach((el) => {
el?.querySelector(APP_LCNAME)?.remove();
});
@@ -148,9 +159,18 @@ export class Translator {
fetchClear();
};
_reTranslate = debounce(() => {
if (this.rule.transOpen === "true") {
this._queryNodes().forEach((el) => {
this._interseObserver.unobserve(el);
this._interseObserver.observe(el);
});
}
}, 500);
_render = (el) => {
// 含子元素
if (queryNodes(this.rule.selector, el).length > 0) {
if (this._queryNodes(el).length > 0) {
return;
}
@@ -172,8 +192,10 @@ export class Translator {
el.appendChild(span);
el.style.cssText +=
"-webkit-line-clamp: unset; max-height: none; height: auto;";
el.parentElement.style.cssText +=
"-webkit-line-clamp: unset; max-height: none; height: auto;";
if (el.parentElement) {
el.parentElement.style.cssText +=
"-webkit-line-clamp: unset; max-height: none; height: auto;";
}
const root = createRoot(span);
root.render(<Content q={q} translator={this} />);

View File

@@ -39,7 +39,7 @@ import { isGm } from "./libs/browser";
const $action = document.createElement("div");
$action.setAttribute("id", "kiss-translator");
document.body.parentElement.appendChild($action);
const shadowContainer = $action.attachShadow({ mode: "open" });
const shadowContainer = $action.attachShadow({ mode: "closed" });
const emotionRoot = document.createElement("style");
const shadowRootElement = document.createElement("div");
shadowContainer.appendChild(emotionRoot);