影子域中的FontAwous SVG
我正尝试在Web组件中使用字体强大的js/svg库,但图标不会显示。这可能吗?
我正在尝试在现有的WebForms项目中实现一个角度组件,而不会"出血"出CSS和脚本,有什么其他建议可以做到这一点的吗?IFrame不是一个选项。
<html>
<head>
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js" defer>
</script>
<script>
customElements.define('my-holder', class extends HTMLElement {
constructor() {
super();
console.log("constructor");
let shadowRoot = this.attachShadow({
mode: 'open'
});
const t = document.querySelector('#holder');
const instance = t.content.cloneNode(true);
shadowRoot.appendChild(instance);
}
connectedCallback() {
console.log("callback");
}
});
</script>
</head>
<body>
<div id="outside">
light dom
<div class="fa-4x">
<span class="fa-layers fa-fw" style="background:MistyRose">
<i class="fas fa-circle" style="color:Tomato"></i>
<i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
</span>
</div>
</div>
<template id="holder">
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js" defer></script>
dark shadow dom
<div class="fa-4x">
<span class="fa-layers fa-fw" style="background:MistyRose">
<i class="fas fa-circle" style="color:Tomato"></i>
<i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
</span>
</div>
</template>
<div id="inside">
<my-holder></my-holder>
</div>
</body>
</html>
解决方案
许多旧库使用document.
访问主DOM。
因此他们无法对shadowDOM
这意味着您不可能实现不释放脚本的目标。
FONT-必须在主DOM中加载非常棒的(脚本和样式)。
如果您不想将样式释放到shadowDOM之外,则必须遵守规则:
字体-非常棒的图标定义必须保留在主DOM中
lightDOM是shadowDOM时隙内容的(Main DOM)‘原始’
lightDOM由主DOM设置样式
(如果元素本身在另一个shadowDOM中,则为其shadowDOM容器)槽lightDOM保留在lightDOM中,仅反映到其
<slot></slot>
您不希望在每个lightDOM中重复FontAwose图标定义
(那么您不妨根本不使用自定义元素)
<span class="fa-4x fa-layers fa-fw">
<i class="fas fa-circle"></i>
<i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
</span>
- 自定义元素可以访问整个DOM
解决方案:
编写自定义元素
- 创建自己的lightDOM
- 哪个槽
<slot></slot>
(反映!未移动!) - 从属性获取配置
<awesome-icon background="lightcoral" color="red"></awesome-icon>
<awesome-icon background="lightgreen" color="green"></awesome-icon>
<awesome-icon></awesome-icon>
JSFidlle:https://jsfiddle.net/CustomElementsExamples/1pmvasnj/
数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假"><script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js" defer></script>
<script>
customElements.define('awesome-icon', class extends HTMLElement {
constructor() {
super().attachShadow({mode: 'open'})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
}
connectedCallback() {
let setProperty =
(prop, value)=>this.shadowRoot.host.style.setProperty('--' + prop, value);
setProperty('fa-background', this.getAttribute('background'));
setProperty('fa-color', this.getAttribute('color'));
// move icon HTML back to lightDOM so FontAwesome can style it
this.innerHTML = this.shadowRoot.querySelector('#ICON').innerHTML;
}
});
</script>
<template id="AWESOME-ICON">
<style>
::slotted(*) {
/* lightDOM SPAN has higher Specificity, only way out is using !important */
background: var(--fa-background,grey) !important;
color: var(--fa-color,darkgrey) !important;
}
</style>
<template id="ICON">
<span class="fa-4x fa-layers fa-fw">
<i class="fas fa-circle"></i>
<i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
</span>
</template>
<slot><!--lightDOM REFLECTED here--></slot>
</template>
<awesome-icon><!-- lightDOM CREATED here --></awesome-icon>
<awesome-icon background="lightcoral" color="red"></awesome-icon>
<awesome-icon background="lightgreen" color="green"></awesome-icon>
<style>
span{
background:lightblue; /* !important inside shadowDOM overrules these settings */
color:red;
}
</style>
不使用shadowDOM和插槽
并依赖于限定作用域的css属性,使代码更简单:
<script>
customElements.define('awesome-icon', class extends HTMLElement {
connectedCallback() {
this.append(document.getElementById(this.nodeName).content.cloneNode(true));
this.style.setProperty('--fa-background', this.getAttribute('background') );
this.style.setProperty('--fa-color' , this.getAttribute('color') );
}
});
</script>
<template id="AWESOME-ICON">
<span class="fa-4x fa-layers fa-fw">
<i class="fas fa-circle"></i>
<i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
</span>
</template>
<awesome-icon background="lightcoral" color="red"></awesome-icon>
<awesome-icon background="lightgreen" color="green"></awesome-icon>
<awesome-icon></awesome-icon>
<style>
span {
background: var(--fa-background);
color: var(--fa-color );
}
</style>
相关文章