简体   繁体   English

如何将 JSON 样式 object 转换为 CSS 字符串?

[英]How to convert a JSON style object to a CSS string?

I wanted to set my element's style as such:我想这样设置元素的样式:

this.refs.element.style = {
    ...this.props.style,
    background: 'blue',
};

But apparently you can't use an object to set the ref's style.但显然你不能使用 object 来设置裁判的风格。 I have to use a CSS style string with ;我必须使用 CSS 样式的字符串; separating the prop:values分离prop:values

I'm aware that most people would set style in the render function, but for performance reasons, I can't repeatedly re-render.我知道大多数人会在渲染 function 中设置样式,但出于性能原因,我不能重复重新渲染。

A performant answer is to map and join the Object.entries with semicolons:一个Object.entries答案是用分号mapjoin Object.entries

const style = {
  ...this.props.style,
  background: 'blue',
};

const styleString = (
  Object.entries(style).map(([k, v]) => `${k}:${v}`).join(';')
);

It unwraps background:'blue', to background:blue;它将background:'blue',background:blue; which works well for CSS这适用于 CSS


To replace any capital letter with dash lowercase letter用破折号小写字母替换任何大写字母

k = k.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);

this solution works in IE and handles camelCase keys like backgroundColor这个解决方案适用于 IE 并处理像 backgroundColor 这样的驼峰键

 const style = { width: '1px', height: '1px', backgroundColor: 'red', transform: 'rotateZ(45deg)', } const styleToString = (style) => { return Object.keys(style).reduce((acc, key) => ( acc + key.split(/(?=[AZ])/).join('-').toLowerCase() + ':' + style[key] + ';' ), ''); }; console.log(styleToString(style)); // output - "width:1px;height:1px;background-color:red;transform:rotateZ(45deg);"

Use https://www.npmjs.com/package/json-to-css .使用https://www.npmjs.com/package/json-to-css Note it will not add a semicolon to the last property to fix it you can beautify it with https://www.npmjs.com/package/cssbeautify Example请注意,它不会在最后一个属性中添加分号来修复它,您可以使用https://www.npmjs.com/package/cssbeautify示例对其进行美化


    const cssbeautify = require('cssbeautify')

    const Css = require('json-to-css')

    const json = {
        "h1": {
            "font-size": "18vw",
            "color": "#f00"
        },
        ".btn": {
            "font-size": "18vw",
            "color": "#f00"
        }
    }


    const r = Css.of(json)
    console.log(r)

    const beautified = cssbeautify(r, {
        autosemicolon: true
    })

    console.log(beautified)

Result结果


  console.log src/utils/playground/index.spec.ts:22 // json-to-css
    h1{font-size:18vw;color:#f00}
    .btn{font-size:18vw;color:#f00}

  console.log src/utils/playground/index.spec.ts:29 // cssbeautify
    h1 {
        font-size: 18vw;
        color: #f00;
    }
    
    .btn {
        font-size: 18vw;
        color: #f00;
    }
   

Adding to the great answer of @Artem Bochkarev添加到@Artem Bochkarev 的伟大答案

I'm adding a snippet to do the opposite conversion as well (string to object) which may come in handy to anyone stumbling here我正在添加一个片段来进行相反的转换(字符串到对象),这对在这里绊倒的人可能会派上用场

 const style = { width: '1px', height: '1px', backgroundColor: 'red', transform: 'rotateZ(45deg)', }; const styleToString = (style) => { return Object.keys(style).reduce((acc, key) => ( acc + key.split(/(?=[AZ])/).join('-').toLowerCase() + ':' + style[key] + ';' ), ''); }; const stringToStyle = (style) => { const styles = {}; style.split(';').forEach((s) => { const parts = s.split(':', 2); if (parts.length > 1) { styles[parts[0].trim().replace(/-([az])/ig, (_, l) => l.toUpperCase())] = parts[1].trim(); } }); return styles; }; console.log(styleToString(style)); // output - "width:1px;height:1px;background-color:red;transform:rotateZ(45deg);" console.log(stringToStyle(styleToString(style)));

TL;DR: The problem is that you are overwriting the entire "style" property of the element and losing its prototype and methods. TL;DR:问题在于您正在覆盖元素的整个“样式”属性并丢失其原型和方法。 You must add your style object without change the entire property.您必须在不更改整个属性的情况下添加样式 object。 If you want to apply an object-like style to a DOM element, just do:如果你想将类似对象的样式应用于 DOM 元素,只需执行以下操作:

Object.assign(this.refs.element.style, {
    background: 'blue',
    color: 'white',
    /** style properties:values goes here */
});

Explanation: The property "style" is an instance of the "CSSStyleDeclaration" interface.说明:属性“style”是“CSSStyleDeclaration”接口的一个实例。 If you overwrite the interface it wont be a "CSSStyleDeclaration" anymore.如果您覆盖接口,它将不再是“CSSStyleDeclaration”。 It works when you set a string as value because javascript will pass the string directly to the element, without process anything.当您将字符串设置为值时它会起作用,因为 javascript 会将字符串直接传递给元素,而不进行任何处理。

CSSStyleDeclaration Reference Doc: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration CSSStyleDeclaration 参考文档: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration

If you want to do a test, go to your navigator > inspector > console and paste the code below:如果你想做一个测试,go 到你的导航器 > 检查器 > 控制台并粘贴下面的代码:

const p1 = document.createElement('p');
p1.style = { color: 'blue' };

const p2 = document.createElement('p');
Object.assign(p2.style, { color: 'blue' });

console.log(p1);
console.log(p2);

The output will be: output 将是:

<p style=""></p>
<p style="color: blue;"></p>

the css function in @material-ui/system can help you out check more info here @material-ui/systemcss函数可以帮助您在此处查看更多信息

import React from 'react';
import styled, { ThemeProvider } from 'styled-components';
import NoSsr from '@material-ui/core/NoSsr';
import { createMuiTheme } from '@material-ui/core/styles';
import { compose, spacing, palette, css } from '@material-ui/system';

const Box = styled.div`
  ${css(
    compose(
      spacing,
      palette,
    ),
  )}
`;

const theme = createMuiTheme();

export default function CssProp() {
  return (
    <NoSsr>
      <ThemeProvider theme={theme}>
        <Box color="white" css={{ bgcolor: 'palevioletred', p: 1, textTransform: 'uppercase' }}>
          CssProp
        </Box>
      </ThemeProvider>
    </NoSsr>
  );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM