【问题标题】:Embeding JSX as a string variable into other JSX code in React JS将 JSX 作为字符串变量嵌入到 React JS 中的其他 JSX 代码中
【发布时间】:2019-01-03 19:27:18
【问题描述】:

我有 JSX 代码,但它在一个字符串中。尝试将该代码注入 React 组件内的其他 JSX 中并遇到问题...

我正在使用 dangerouslySetInnerHTML 但是 JSX 以某种方式被视为 HTML。我有 JSX 格式的 className = "test" ......所以,当呈现它时,它有 HTML 测试类(红色背景)

React 组件尝试将 JSX 字符串注入其他 JSX 代码

  createMarkup(){  
    var htmlString = '<div className="test">TESTING</div>';
    return {__html : htmlString}

  }

  render() {
     return (
        <div id="pageContent" className="container" dangerouslySetInnerHTML={this.createMarkup()}></div>
      );   
  }

它正在插入字符串变量,但是当您检查它时,输出是这样的:(您可以看到外部 div 的 className 现在是 class,但是插入的字符串仍然被视为 className

浏览器检查器查看渲染代码

<div id="pageContent" class="container"><div classname="test">TESTING</div></div>

【问题讨论】:

    标签: javascript reactjs jsx


    【解决方案1】:

    所以也许我迟到了一两年,但我怀疑dangerouslySetInnerHTML 期望的不是 JSX 字符串,而是 HTML 字符串。

    class App extends React.Component {
      createMarkup() {
        var htmlString = '<div class="test">TESTING</div>'; // class instead of className
        return { __html: htmlString };
      }
    
      render() {
        return (
          <div
            id="pageContent"
            className="container"
            dangerouslySetInnerHTML={this.createMarkup()}
          />
        );
      }
    }
    
    
    let main = document.getElementById("main");
    ReactDOM.render(<App />, main);
    
    console.log("The innerHTML of `#main` is:")
    console.log(main.innerHTML)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    
    <div id="main"></div>

    `innerJSX` 而不是 `innerHTML`

    如果您绝对必须设置 innerJSX 而您似乎没有设置,您可以使用 babel 进行设置,但根据您使用的是 node 还是 browser js,方法会有所不同。

    NodeJS:您需要 @babel/core@babel/plugin-transform-react-jsx 来实现这一点,React with webpack 将支持这一点。

    let parseJSX = (function() {
      let babel = require("@babel/core");
      return function(str) {
        let code = babel.transformSync(str, {
          plugins: ["@babel/plugin-transform-react-jsx"]
        }).code;
        return eval(code);
      }
    })()
    

    浏览器:这是指仅浏览器内的 ReactJS。为此,您还需要 babel。

    // Assuming babel is already loaded.
    function parseJSX(str) {
      return eval(
        Babel.transform(str, 
          {
            presets: [],
            plugins: ["transform-react-jsx"]
          }
        ).code
      )
    }
    

    测试

    浏览器

    // Browser Version (Babel is loaded)
    function parseJSX(str) {
      return eval(
        Babel.transform(str, 
          {
            presets: [],
            plugins: ["transform-react-jsx"]
          }
        ).code
      )
    }
    
    class App extends React.Component {
      createMarkup() {
        var jsxString = '<div className="test">TESTING</div>'; // className as in JSX
        return parseJSX(jsxString);
      }
    
      render() {
        return (
          <div
            id="pageContent"
            className="container"
          >
          {this.createMarkup()}
          </div>
        );
      }
    }
    
    
    let main = document.getElementById("main");
    ReactDOM.render(<App />, main);
    
    console.log("The innerHTML of `#main` is:")
    console.log(main.innerHTML)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    
    <div id="main"></div>

    【讨论】:

      【解决方案2】:

      由于通过dangerouslySetInnerHTML 传递的内容应该是 HTML 并且它没有被 React 解析,因此 className 属性不会被解析为 class,内容必须遵循添加属性的 HTML 约定必须看起来喜欢

      createMarkup(){  
          var htmlString = '<div class="test">TESTING</div>';
          return {__html : htmlString}
      
        }
      
        render() {
           return (
              <div id="pageContent" className="container" dangerouslySetInnerHTML={this.createMarkup()}></div>
            );   
        }
      

      不过你也可以这样写

        createMarkup(){  
          return <div className="test">TESTING</div>
        }
      
        render() {
           return (
              <div id="pageContent" className="container">{this.createMarkup()}</div>
            );   
        }
      

      【讨论】:

      • 那我该如何传入 JSX 呢?我需要它是 JSX(在某些情况下该字符串中有组件)
      • 您宁愿将它们渲染为 div 的子级,而不是使用 dangerouslySetInnerHTML
      • 但这并不能解决这个字符串问题。我仍然会将孩子作为字符串传递,而 React 不会将字符串解析为 JSX
      • 为什么要将孩子作为字符串传递
      • 真正的问题是为什么你的JSX被表示为一个字符串?
      猜你喜欢
      • 2019-01-21
      • 2019-03-23
      • 1970-01-01
      • 2021-01-19
      • 1970-01-01
      • 2020-07-10
      • 2018-12-30
      • 2021-08-24
      • 2017-11-14
      相关资源
      最近更新 更多