注入js文件_React - 让组件注入 style

本文介绍了如何在React组件中实现样式内聚和复用,通过StyleInjectReact组件,动态将样式规则注入document,避免了CSS模块导入和样式分离的问题。文章详细展示了转换JavaScript样式为CSS样式的方法,并提供了使用示例,使得组件在导入时即完成样式初始化,保证了组件的样式生效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ce652a8adf69fde26ca67843ece28328.png

StyleInject

7bcc177ba5bf8e2b7e4e8861af0b9ee0.png

React 组件样式依赖的内聚解决方案

将 css 样式规则随着组件导入注入到 document 中,纯 ts/js 实现。

痛点 Introduction

在实际业务中,我们创造了大量的 Presentational Components 来为我们渲染 UI。很多时候,我们希望这样的组件能够表现出某种样式风格。基于其复用的需求,我们会想到对元素设置 className,然后在样式表文件中制定对应的规则。

textarea.rc-MarkDown, section.rc-MarkDown {
    padding: 0.6rem 1rem;
    text-align: left;
    font-family: var(--sans-serif);
    /* more */
}
section.rc-MarkDown, {
    lineHeight: 1.5;
}

但是,这样带来另一个问题:按照 React 对组件复用的理念,我们希望能通过简单的 import 语句导入一个组件,在不同的环境中使用它。然而,如果我们像上面那样做,组件的样式与其渲染逻辑分离,就会面临不得不将样式文件一同导入的问题。

于是,我们又常常选择 css in js,把样式定义到标签里。

<section
    style={
        padding: "0.6rem 1rem",
        textAlign: "left",
        fontFamily: "var(--sans-serif)",
        /* more */
    }
 />

这是一般组件开发时推崇的写法,但是它违背了样式的复用性,生成了很长的标签内容。

另一方面,我们希望对组件使用优雅的 CSS transition,这就让操作样式规则成为一个应考虑的方向。

解决 Solution

最重要的问题,就是解决在导入组件文件的同时,其样式依赖也一并生效。因此,我采用添加标签的方式,动态地将 js 中的样式信息添加到文档中。(为什么使用 js 格式?在 js 的格式下,我们更容易获取样式的类型信息,包括枚举,这也符合 react 的标签语法)

命名转换部分

/**
 * Change a set of style rules from JavaScript style to CSS style.
 *
 * @param {(Properties<string|number>)} rules
 * @returns
 */
const resolveCSSRule = (rules: Properties<string|number>) => {
    let ruleList: string[] = [];

    for (const key in rules) {
        if (rules.hasOwnProperty(key)) {
            let name: string = key;
            let flag: number = name.search(/[A-Z]/);
            while (flag !== -1) {
                name = name.slice(0, flag)
                        + "-" + name.charAt(flag).toLowerCase() + name.slice(flag + 1);
                flag = name.search(/[A-Z]/);
            }
            const value = rules[key as keyof Properties<string|number>];
            ruleList.push(`${ name }: ${ value };`);
        }
    }

    return ruleList;
};

导出接口

let style: HTMLStyleElement | null = null;

/**
 * Append new css rules.
 *
 * @param {string} selector                     CSS selector, separated by ',' .
 * @param {(Properties<string | number>)} rules CSS styles object, in JavaScript style.
 * @param {number} [index=0]                    The newly inserted rule's position in CSSStyleSheet.cssRules.
 */
const styleinject = (selector: string, rules: Properties<string|number>, index: number=0) => {
    if (!style) {
        // Initialize
        style = document.createElement("style");
        style.type = "text/css";
        document.head.appendChild(style);
    }

    // Append rules
    (style.sheet as CSSStyleSheet).insertRule(
        `${ selector } { ${
            resolveCSSRule(rules).join("n")
        } }`, Math.min(index, (style.sheet as CSSStyleSheet).rules.length)
    );
};

安装 styleinject

npm:

npm i -s styleinject-y

用例

使用时,只需要给组件的渲染内容加上 className,然后在组件文件中直接调用此方法,加入对应样式规则即可。

import styleinject from "styleinject";

const MarkDown: React.FC<MarkDownProps> = props => (
    <div className="rc-MarkDown" >
        // ...
    </div>
);

// Additional css rules
styleinject("div.rc-MarkDown", {
    display: "flex",
    alignItems: "stretch",
    justifyContent: "center",
    width: "80vw",
    minHeight: "500px",
    maxHeight: "90vh"
});
styleinject("section.rc-MarkDown, textarea.rc-MarkDown", {
    lineHeight: 1.5
});

这样就可以使得当组件被导入的时候,样式进行初始化注入 document,从而使组件的样式生效。

项目地址:

GitHub​github.comstyleinject-y​www.npmjs.com
5f39ff02c78d4dab0d8f72734d169784.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值