?工具类utils.js
function changeShadowDOMStyles(shadowRootElement, styles, insertBeforeSelector) {
const root = shadowRootElement?.shadowRoot;
if (!root) {
return;
}
const styleElements = root.querySelectorAll('style');
const result = Array.from(styleElements).some(el => el.innerHTML === styles);
if(result) {
return;
}
const newStyleTag = document.createElement('style');
newStyleTag.innerHTML = styles;
root.insertBefore(newStyleTag, root.querySelector(insertBeforeSelector));
}
const waitTime = async (milliseconds) => await new Promise((resolve) => setTimeout(resolve, milliseconds));
export {
changeShadowDOMStyles,
waitTime
}
?demo
<!DOCTYPE html>
<html lang="en" md="">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="format-detection" content="telephone=no">
<link rel="stylesheet" href="./css/ionic.bundle.css" />
<link rel="stylesheet" href="./css/init.css" />
<link rel="stylesheet" href="./css/common.css" />
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
<script src="./js/jquery-3.6.0.js"></script>
<title>日历demo</title>
<style>
</style>
</head>
<body>
<ion-app>
<ion-fab id="btn-fab" vertical="bottom" horizontal="end" slot="fixed"
style="display: none;position:fixed; bottom: 40px;">
<ion-fab-button id="btnBack2Top">
<ion-icon name="arrow-up-circle-outline"></ion-icon>
</ion-fab-button>
</ion-fab>
<ion-page class="ion-page" id="main-content">
<ion-header mode="md">
<ion-toolbar color="primary">
<ion-title>
demo系统
<div class="language">
<ion-icon name="globe" size="large"></ion-icon>
<ion-select id="selLanguage" value="jp" slot="end" interface="popover">
<ion-select-option value="jp" selected>日本語</ion-select-option>
<ion-select-option value="eng">English</ion-select-option>
<ion-select-option value="zn">中文</ion-select-option>
</ion-select>
</div>
</ion-title>
</ion-toolbar>
</ion-header>
<ion-datetime id="custom-datetime" presentation="date" locale="en-GB">
<ion-buttons slot="buttons">
<ion-button id="confirmBtn">Good to go!</ion-button>
<ion-button id="cancelBtn">Reset</ion-button>
</ion-buttons>
</ion-datetime>
<ion-datetime presentation="time"></ion-datetime>
<ion-footer>
<ion-toolbar class="copyright" color="primary">
Copyright ? Matsudo City, All rights reserved.
</ion-toolbar>
</ion-footer>
</ion-page>
</ion-app>
</body>
<script type="module">
import { changeShadowDOMStyles, waitTime } from './js/utils.js'
window.onload = async function() {
await waitTime(50);
const datetimeComponent = document.querySelector("ion-datetime");
const shadowRoot = datetimeComponent.shadowRoot;
console.dir(shadowRoot);
const nodeList = shadowRoot.querySelectorAll(".calendar-month-grid");
console.log(nodeList);
const activeDay = shadowRoot.querySelector(".calendar-month-grid > .calendar-day-active");
console.log(activeDay);
$(activeDay).click(function(event) {
console.dir(event);
const {
target: {
innerText
}
} = event;
alert(`今天的日期是${innerText}号`);
})
const styles1 = `
.calendar-month-grid {
background: #ffc409 !important;
}
`;
changeShadowDOMStyles(datetimeComponent, styles1);
const styles2 = `
.calendar-day-active {
color: blue !important;
}
.calendar-month-grid button {
border: 1px solid blue !important;
border-radius: 16px;
}
`
changeShadowDOMStyles(datetimeComponent, styles2, ".datetime-calendar");
const calendarMonth = $(shadowRoot).find('.calendar-month-grid')[1];
const firstGrid = $(calendarMonth).find('button')[0];
const customEle = `
<span style="color:red;">自定义<span>
`;
$(firstGrid).append(customEle);
const confirmBtn = document.querySelector('#confirmBtn');
$(confirmBtn).click(function() {
datetimeComponent.confirm();
})
$(cancelBtn).click(function() {
datetimeComponent.reset();
})
}
</script>
</html>
- 由于ShadowDOM和LightDOM做了隔离,因此组件的样式无法直接修改
- 可以将css样式通过style标签的形式插入到ShadowDOM中,
从而修改组件中的样式,插入之后的效果如下图
😑修改前 🤨改修后
参考资料: [译] Web Components简介 https://juejin.cn/post/6844903807734775816 [译] 编写可以复用的 HTML 模板 https://juejin.cn/post/6844903813116067853 [译] 从 0 创建自定义元素 https://github.com/xitu/gold-miner/blob/master/TODO1/creating-a-custom-element-from-scratch.md [译] 使用 Shadow DOM 封装样式和结构 https://juejin.cn/post/6844903821550829581 [译] Web Components 的高级工具 https://juejin.cn/post/6844903816865775630 日本人的demo https://qiita.com/alangdm/items/cec32f21151a9da3c3f2 https://github.com/alangdm/shadow-dom-quiz https://alangdm.github.io/shadow-dom-quiz/ 神秘的 shadow-dom 浅析 https://www.cnblogs.com/Red-ButterFly/p/7661996.html 【shadow dom入UI】web components思想如何应用于实际项目 https://www.cnblogs.com/yexiaochai/p/4167554.html Angular之 ViewEncapsulation 与 Shadow DOM https://www.cnblogs.com/xianrongbin/p/10931064.html 博客园 shadow DOM https://recomm.cnblogs.com/blogpost/5040504 shadow-dom-inject-styles 样式修改插件 https://github.com/adamlacombe/Shadow-DOM-inject-styles https://www.npmjs.com/package/shadow-dom-inject-styles 官方shadow_DOM案例 https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_shadow_DOM https://developer.mozilla.org/zh-CN/docs/Web/API/ShadowRoot ionic--修改默认组件样式 https://blog.csdn.net/weixin_43964866/article/details/108534242 ionic4关于CSS Custom Properties修改组件样式 https://www.jianshu.com/p/3a9423a2c94c ShadowDOM css样式处理详解 https://cloud.tencent.com/developer/article/1965869
|