【问题标题】:Use Babel Transform inside of React code在 React 代码中使用 Babel Transform
【发布时间】:2017-09-25 19:08:51
【问题描述】:

我正在尝试将字符串转换为有效的 JSX 代码,然后将其注入到我的 React 组件中。

const babel = require('babel-core')
let result = eval(babel.transform('<p className="greeting">Hello</p>').code)

但是我遇到了很多错误,因为我试图在浏览器中使用 Babel:

ERROR in ./~/babel-core/lib/api/node.js
Module not found: Error: Can't resolve 'fs' in '/Users/ben/Desktop/Work/code/ru-coding-challege/node_modules/babel-core/lib/api'
 @ ./~/babel-core/lib/api/node.js 72:10-23
 @ ./~/babel-core/index.js
 @ ./src/js/containers/app-container.js
 @ ./src/js/index.js
 @ multi (webpack)-dev-server/client?http://localhost:3000 ./src/js/index.js

...more similar errors

是的,我知道从字符串创建代码并注入它是不赞成,但是 D3 动态创建元素(即您不能以声明方式编写它们)例如:轴的值和数量刻度会根据数据而变化。我已经成功地将 D3 轴更改为带有 htmltojsx 的 JSX,但它返回了 String。我需要将 String 转换为可以注入到我的代码中的有效 JSX 组件。

编辑:正如 Michael Lyons 在下面所说,我可以使用 dangerouslySetInnerHTML,但我会尽量避免使用此选项,除非其他所有方法都不起作用。尽量保持在 React 范式内。

这是我的组件的渲染方法的外观:

<svg width='100%' height='600'>
  <g transform='translate(50, 50)'>
    <path d='...' className='path-0'></path>
  </g>
  {/* Insert JSX elements here. e.g. axes below */}
  {axes}
</svg>

这是我的webpack.config.js

const CopyWebpackPlugin = require('copy-webpack-plugin')
const path = require('path')
const webpack = require('webpack')

module.exports = {
  entry: './src/js/index.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].bundle.js',
  },
  devServer: {
    inline: true,
    contentBase: path.join(__dirname, 'dist'),
    port: 3000
  },
  plugins: [
    new CopyWebpackPlugin([
      { from: 'src/html/index.html' }
    ]),
    new webpack.DefinePlugin({
      IN_BROWSER: true,
    }),
  ],
  module: {
    loaders: [
      {
        test: /\.scss$/,
        exclude: /(node_modules)/,
        loader: 'style-loader!css-loader!sass-loader'
      },
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  }
}

【问题讨论】:

  • 这个 JSX 代码实际上是从哪里来的?当用户加载页面时,您将尝试编译它,这意味着您正在尝试将整个 Babel 捆绑并发送到您的用户客户端,这很糟糕。
  • 您可以只使用 D3 的 HTML 输出并危险地设置组件中的包装器 div 的内部 html。检查此链接:React Docs
  • @loganfsmyth - 正如我上面所说,JSX 代码来自htmltojsx,我在 D3 的输出中。如果有另一种方法可以将 D3 输出转换为有效的 JSX,我很想了解它。
  • @MichaelLyons - 我曾考虑过使用dangerouslySetInnerHTML,但我试图避免这条路线,因为至少通过转译到 JSX,我仍然在某种程度上使用 React 方法。

标签: javascript reactjs d3.js babeljs babel-core


【解决方案1】:

您可以直接通过 React 组件渲染该 html,而不是将 HTML 转换为 JSX,然后在客户端使用 babel 进行渲染。

Facebook 的 DOM 元素实现已为此用例内置了功能,您是对的,出于安全原因,它通常不受欢迎,因为它会向cross-site scripting 开放漏洞。

Facebook 甚至将其标记为“dangerouslySetInnerHTML”以提醒开发人员这是危险的。

所以如果你有一个字符串格式的 HTML,你可以在 JSX 中以如下方式呈现它:

getMarkup() {
  return { __html: '<p class="greeting">Hello</p>' }
}
render() {
  return <div dangerouslySetInnerHTML={this.getMarkup()} />;
}

这直接来自此处的 React DOM 元素文档:Docs

此方法还应该允许您绕过将 d3 输出转换为 JSX

编辑:介绍句

【讨论】:

  • 我考虑过使用dangerouslySetInnerHTML,但我试图避免这条路线,因为至少通过转译到 JSX,我仍然在某种程度上使用 React 方法。如果没有其他方法真的有效,那么我将回退到dangerouslySetInnerHTML
猜你喜欢
  • 2018-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-11
  • 2016-02-04
  • 2016-10-28
  • 2021-02-04
  • 2021-01-21
相关资源
最近更新 更多