Angular/Ionic 修改 ShadowRoot 元素样式

在使用Ionic的时候,难免会出现要修改原有样式的情况。但新版的Ionic采用了ShadowRoot来隔离样式,不能愉快的直接通过CSS修改ShadowRoot下的样式,但我们又想修改,怎么办呢?

方法一

使用 CSS3 ::part伪元素 (但该方法有局限性,有些组件并未对外提供足够的CSS Shadow Parts,且一些浏览器尚未支持该伪元素。)

首先打开你想修改样式的组件的开发文档(笔者这里以 ion-back-button 组件为例),找到CSS Shadow Parts(一些组件并未提供CSS Shadow Parts,解决办法详见方法二)。

ion-back-button CSS Shadow Parts

可以看到该组件提供了三个CSS Shadow Part,然后我们使用快捷键F12 或者 ctrl + shift + i打开Web开发者工具,找到ion-back-button,并找到这三个Part。

ion-back-button dom.png

笔者这里想要修改ion-back-button的文字样式,则使用::part伪元素选中text这个part,方法如下:

ion-back-button::part(text) {
  background: var(--custom-color-gray);
  padding: 0.2rem 0.4rem;
  font-size: 0.8rem;
  border-radius: 1rem;
}

这样子就大功告成啦!

方法二

原理:通过注入一个style元素到ShadowRoot下来覆盖样式。

方法如下:

import { Component, ElementRef, OnInit, Renderer2 } from '@angular/core';
/*
  此处省略非关键代码
*/
export class ExamplePage implements OnInit {
    constructor(
        private renderer2: Renderer2,
        private element: ElementRef
    ) { }

    ngAfterViewInit() {
        // 修改返回按钮中文本的样式
        const ionBackButton = this.element.nativeElement.querySelector('ion-back-button');
        const styleSheet = `
            .button-text {
                background: var(--custom-color-gray);
                padding: .2rem .4rem;
                font-size: .8rem;
                border-radius: 1rem;
            }
        `;
        this.injectStyleToShadowRoot(this.renderer2, ionBackButton, styleSheet);
    }

    /**
     * 注入CSS样式到目标元素的ShadowRoot中
     * @param renderer 渲染器
     * @param element 目标元素
     * @param styleSheet CSS样式
     */
    injectStyleToShadowRoot(renderer: Renderer2, element: HTMLElement, styleSheet: string): void {
        const style = renderer.createElement('style');
        style.innerHTML = styleSheet;
        element.shadowRoot.appendChild(style);
    }
}

由于Angular不建议直接用原生的方法来操作DOM,在这里故使用ElementRef,Renderer2 来实现。
注意:将修改样式的代码放置于 ngAfterViewInit() 生命周期函数中,避免获取不到元素的问题。

Tips:当然,将 injectStyleToShadowRoot() 方法封装在一个公共的工具类中是更好的做法,笔者这里为了便于展示代码,直接封装在Component中了。

你可能感兴趣的:(Angular/Ionic 修改 ShadowRoot 元素样式)