纯 JavaScript 类的 CSS in JS

4
如果我创建一个像这样的纯JS组件:
class TestComponent {
  constructor(el) {
    this.render(el);
  }

  render(el) {
    var html = `
      <div>
        <p>Some dummy content</p>
      </div>
    `;
    document.getElementById(el).innerHTML = html;
  }
}

我可以在JS中添加CSS吗?我的意思是类似这样:

const styles = {
  backgroundColor: 'palevioletred',
  color: 'papayawhip',
};

所以上述的渲染方法将会是这样的:
render(el) {
  var html = `
    <div style={styles}>
      <p>Some dummy content</p>
    </div>
  `;
  document.getElementById(el).innerHTML = html;
}

能否在类似Angular/React之外的框架中实现此功能?

3
任何JavaScript框架或库所能实现的功能,使用纯JavaScript也能够实现,因为所有这些框架和库都是用纯JavaScript编写的,最终都会输出纯JavaScript代码。人们往往会忘记或不知道这一点。 - Rob
你为什么不想使用类? - pixlboy
1
@rach8garg,因为我希望它成为一个独立的组件,包括自己的HTML和CSS。在我看来,内联CSS不是一个好的解决方案,我喜欢CSS-in-JS的方法(就像使用Radium和其他工具时所得到的那样)。 - vindict
3个回答

5

您正在将JS对象用作HTML(字符串)中的内容。因此,您需要将对象转换为有效的HTML字符串:

const styles = {
  // CSS key is `background-color` instead of `backgroundColor`
  'background-color': 'palevioletred', 
  color: 'papayawhip',
}


render(el) {
  // Loop every keys, and create an array contain every
  // key:value
  // join every items on array to create a single String.
  var string_styles = Object.keys(styles).map(s => { 
    return s + ":" + styles[s]
  }).join(';')

  // Or
  string_styles = JsToCss(styles)  


  var html = '<div style="' + string_styles + '">' +
      '<p>Some dummy content</p>' +
    '</div>';
  document.getElementById(el).innerHTML = html;
}

// Decomposed function:
let JsToCss = (styles) => {
  let keys = Object.keys(styles) 
  // keys = [ 'background-color', 'color']

  let css_values = keys.map(key => {
    return key + ":" + styles
  })
  // css_values = [
  //     'background-color:palevioletred', 
  //     'color:papayawhip'
  // ]

  return css_values.join(';') 
  // return "background-color:palevioletred;color:papayawhip;" 
}

代码未经测试,但这是想法。


简洁的回答。我相信应该是 style="${string_styles}" - Khauri
而且,您还没有解决从驼峰式语法到连字符语法的转换问题。 - Scott Marcus
@KhauriMcClain 谢谢,我更新了我的答案。还为转换添加了一条注释。 - Arthur
@Arthur 我认为你仍然需要用引号将其括起来。将驼峰式转换为连字符式的建议:s.replace(/([A-Z])/g, "-$1").toLowerCase() - Khauri
@KhauriMcClain,好的,我没有使用新的ES6语法来进行concat操作,所以我用旧的方式重新做了一遍(以确保它能够正常工作)。这不是回复的重点,所以不是很重要(关于ES6模板字符串的更多信息:https://developers.google.com/web/updates/2015/01/ES6-Template-Strings)。 - Arthur
在你纠正这行代码'<div style="' + {string_styles} + '">'之前,这段代码将无法工作。 - Scott Marcus

1
你需要将对象转换为有效的CSS。
因为在这里你要求将一个对象转换为字符串,<div style={styles}> 不起作用,转换结果不是你想要的。

const styles = {
  backgroundColor: 'palevioletred',
  color: 'papayawhip',
};

console.log(styles.toString());

您可以使用 JSON.stringify(),但即使如此,您仍需要删除大括号,将逗号转换为分号,删除多余的引号,并将驼峰式命名转换为连字符式命名。
我已经完成了所有这些操作,并将其分解成单个步骤,以展示必须完成的工作,但可以将其压缩为单个语句,并使用正则表达式使其更紧凑。但是,这应该让您有所了解。
注意:您需要在模板文字前面加上$,以将其标识为模板文字。

const styles = {
  backgroundColor: 'palevioletred',
  color: 'papayawhip',
};

let cssString = JSON.stringify(styles);
console.log(cssString);

// Remove the braces
cssString = cssString.replace("{","").replace("}","");
console.log(cssString);

// Remove the quotes
cssString = cssString.replace(/"/g, "")
console.log(cssString);

// Change comma to semi-colon and add trailing semi-colon
cssString = cssString.replace("," ,";") + ";";
console.log(cssString);

// Convert camel case to hyphen
cssString = cssString.replace("backgroundColor", "background-color");
console.log(cssString);

class TestComponent {
  constructor(el) {
    this.render(el);
  }

  render(el) {
    var html = `
      <div style=${cssString}>
        <p>Some dummy content</p>
      </div>
    `;
    document.getElementById(el).innerHTML = html;
  }
}

let tc = new TestComponent("test");
<div id="test"></div>


能否解释一下为什么对一个带有解释的可行答案进行了负评? - Scott Marcus
1
@H.Pauwelyn 我的回答清楚地指出连字符是一个问题,我的解决方案也明确指出只是一个示例。 - Scott Marcus
@ScottMarcus 为什么你先创建了一个错误的字符串并更新它,而不是先构建正确的字符串呢? - Arthur
@Arthur 我会问你和brk一样的问题,当你对他做出同样的评论时——你在说什么?我的代码创建的字符串是正确的。 - Scott Marcus
@Arthur 或许你没有仔细阅读我的回答,只看了代码。我解释了如果使用 JSON.stringify(),字符串中有很多东西需要改变,然后我明确说明了我正在将其分解为单个步骤展示,但这是可以避免的。 - Scott Marcus
显示剩余3条评论

0
我编写了一个简单的genCSS函数,它接受JavaScript对象中的CSS并将其转换为CSS字符串,并生成应用于样式标签的CSS。
const genCSS = (style) => {
  let result = '';
  for (props in style) {
     let keyValuePair = `${props}:${style[props]};`;
     result += keyValuePair;
   }
   return result;
};

const styles = {
  background: '#2196f3',
  color: 'white',
  padding: '5px 10px'
};

class TestComponent {
  constructor(el) {
    this.render(el);
  }

  render(el) {
    const genStyle = genCSS(styles);

    var html = `
      <div style="${genStyle}">
        <p>Some dummy content</p>
      </div>
    `;
    document.getElementById(el).innerHTML = html;
  }
}

const test = new TestComponent('root');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接