【问题标题】:Can I use jsx without React to inline HTML in script?我可以在没有 React 的情况下使用 jsx 在脚​​本中内联 HTML 吗?
【发布时间】:2020-03-28 04:56:39
【问题描述】:

我可以通过像 jsx 这样的库在下面的脚本中使用内联 HTML:

<script src="jsx-transform.js"></script>
<script type="text/jsx">
define('component', function () {
   return (<div>test html code</div>);
});
</script>

【问题讨论】:

  • 你试过了吗?
  • @AliGajani 不工作
  • 据我所知,你需要 React,而 JSX 不能独立工作。我可能错了。
  • 但我只想使用没有反应的jsx

标签: javascript reactjs


【解决方案1】:

我能够编写 JSX 文件并使用“假”React 文件将它们注入 HTML 页面。

no-react.js

/**
 * Include this script in your HTML to use JSX compiled code without React.
 */

const React = {
    createElement: function (tag, attrs, children) {
        var element = document.createElement(tag);

        for (let name in attrs) {
            if (name && attrs.hasOwnProperty(name)) {
                let value = attrs[name];
                if (value === true) {
                    element.setAttribute(name, name);
                } else if (value !== false && value != null) {
                    element.setAttribute(name, value.toString());
                }
            }
        }
        for (let i = 2; i < arguments.length; i++) {
            let child = arguments[i];
            element.appendChild(
                child.nodeType == null ?
                    document.createTextNode(child.toString()) : child);
        }
        return element;
    }
};

然后编译你的 jsx。

test.jsx

const title = "Hello World";
document.getElementById('app').appendChild(
    <div>
        <h1>{title}</h1>
        <h2>This is a template written in TSX, then compiled to JSX by tsc (the Typescript compiler), and finally
            injected into a web page using a script</h2>
    </div>
);

生成的编译'test.js'

var title = "Hello World";
document.querySelector('#app').appendChild(React.createElement("div", null,
    React.createElement("h1", null, title),
    React.createElement("h2", null, "This is a template written in TSX, then compiled to JSX by tsc (the Typescript compiler), and finally" + " " + "injected into a web page")));

最后是包含这两个脚本的 HTML 页面。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>no-react</title>
    <script src="no-react.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>

<script src="test.js"></script>

【讨论】:

  • 如何编译我的 jsx?或者有没有办法在运行时通过js编译?
  • Typscript 编译器让您可以选择编译 jsx (tsx) 或将其传递给 babel 等转译器。
  • 这似乎使我无法运行 onClick 函数,有什么想法吗?
  • 这里有一个完整的解决方案:github.com/nicojs/typed-html
【解决方案2】:

React 使用诸如 React.createElement 之类的函数(以及片段等)将 JSX html 语法呈现给 JS。但这一切都归结为 @babel/plugin-transform-react-jsx 插件,该插件执行此转换:

return(<div id="hello">Hello World</div>)

进入这个...

return React.createElement('div', {id: 'hello'}, 'Hello World');

但是,您可以用您自己的函数替换 React.createElement 来执行此操作。你可以在这里阅读更多内容:https://babeljs.io/docs/en/next/babel-plugin-transform-react-jsx.html

您还应该查看执行此操作的库,例如 nervjs、jsx-render 和 deku。所有这些都使用 JSX html 语法而没有反应。有些(例如 jsx-render)只专注于将 JSX 转换为最终的 JS,这可能就是您要寻找的。​​p>

那个包的作者在这里写了一篇关于它的文章:https://itnext.io/lessons-learned-using-jsx-without-react-bbddb6c28561

如果你使用 Typescript 也可以做到这一点......但我没有第一手经验。

总结一下

你可以不使用 React,但不能不使用 Babel 或 Typescript。

【讨论】:

【解决方案3】:

JSX 不是基于字符串的模板语言;它编译为实际的 JavaScript 函数调用。例如,

<div attr1="something" attr2="other">
  Here are some <span>children</span>
</div>

转译为

React.createElement("div", {attr1: "something", attr2: "other"}, 
  "Here are some ", React.createElement("span", null, "children")
)

【讨论】:

  • 谢谢,但它需要 React。有像 jsx 这样的单个库来执行此操作吗?
  • @SKing7 做什么?你的问题没有意义。 JSX 将类似于 XML 的语法转换为 JavaScript 函数调用。你真正想要它做什么?
  • 它们是独立的虚拟 DOM 库,例如 this one。
  • @SKing7 使用字符串对你有用吗? return ("&lt;div&gt;test html code&lt;/div&gt;"); 如果没有,为什么不呢?也许这将有助于缩小你想要做的事情。
  • @SKing7 如果您使用的是 ES6 转译器(例如 JSX Transformer 附带的转译器),您可以使用支持多行的模板字符串(带有反引号)。请参阅此示例:jsfiddle.net/BinaryMuse/hovssy49
【解决方案4】:

我自己也在寻找这样的东西。 一种为简单项目编写组件和 JSX 的方法。 没有找到我喜欢的,所以我建立了这个: https://github.com/SagiMedina/Aviya#aviya 看看吧,也许它也能解答你的问题。

【讨论】:

    【解决方案5】:

    您需要一些东西来将 JSX 转换为 JS 函数调用。 React 使用 Babel 来做到这一点——你可能也最好这样做。

    Preact 的创建者提供了一个库,它基本上可以满足您的需求,称为 vhtml。标语是“将 JSX/Hyperscript 渲染为 HTML 字符串,无需 VDOM”。

    这是撰写本文时自述文件的副本:

    用法

    // import the library:
    import h from 'vhtml';
    
    // tell babel to transpile JSX to h() calls:
    /** @jsx h */
    
    // now render JSX to an HTML string!
    let items = ['one', 'two', 'three'];
    
    document.body.innerHTML = (
      <div class="foo">
        <h1>Hi!</h1>
        <p>Here is a list of {items.length} items:</p>
        <ul>
          { items.map( item => (
            <li>{ item }</li>
          )) }
        </ul>
      </div>
    );
    

    新:“排序”组件!

    vhtml 故意不将 JSX 转换为 Virtual DOM,而是将其直接序列化为 HTML。但是,仍然可以将基本的纯功能组件用作一种“模板部分”。

    当 vhtml 被赋予一个 Function 作为 JSX 标记名称时,它将调用该函数并将其传递给 { children, ...props }。这与 react/preact 中的纯功能组件签名相同,除了 children 是一个已经序列化的 HTML 字符串数组。

    这实际上意味着可以使用这些简单的组件甚至更高阶的组件来构建组合模板修饰符。

    这是上一个示例的更复杂的版本,它使用组件来封装迭代项:

    让 items = ['one', 'two'];

    const Item = ({ item, index, children }) => (
      <li id={index}>
        <h4>{item}</h4>
        {children}
      </li>
    );
    
    console.log(
      <div class="foo">
        <h1>Hi!</h1>
        <ul>
          { items.map( (item, index) => (
            <Item {...{ item, index }}>
              This is item {item}!
            </Item>
          )) }
        </ul>
      </div>
    );
    

    以上输出如下 HTML:

    <div class="foo">
      <h1>Hi!</h1>
      <ul>
        <li id="0">
          <h4>one</h4>This is item one!
        </li>
        <li id="1">
          <h4>two</h4>This is item two!
        </li>
      </ul>
    </div>
    

    【讨论】:

      【解决方案6】:

      看起来dom-chef 包可以做到这一点。来自自述文件:

      • 没有 API,JSX 会自动转换为实际的 DOM 元素。

      // babel.config.js
      
      const plugins = [
        [
          '@babel/plugin-transform-react-jsx',
          {
            pragma: 'h',
            pragmaFrag: 'DocumentFragment',
          }
        ]
      ];
      
      // ...
      

      const {h} = require('dom-chef');
      
      const handleClick = e => {
          // <a> was clicked
      };
      
      const el = (
          <div class="header">
              <a href="#" class="link" onClick={handleClick}>Download</a>
          </div>
      );
      
      document.body.appendChild(el);
      

      【讨论】:

        【解决方案7】:

        您可以查看文档:in-browser JSX transform, 另见Babel documentation

        你可以实现你想要的,但在生产中不鼓励......

        【讨论】:

          【解决方案8】:

          Jsx 将 return (&lt;div&gt;test html code&lt;/div&gt;); 解析为类似 return React.createElement('div', {...}); 的东西

          那么如果你不使用react.js,那么浏览器将不知道React是什么并触发错误。

          【讨论】:

          • 你只能在没有 jsx 的情况下使用 react.js,但反过来不行,jsx 只是 react 的语法糖。
          • 谢谢,有没有像 jsx 这样的单一库可以做到这一点?
          • 你的意思是jsx编译器吗?如果你这样做了,是的,react 有一个可以做这件事的工具,npm install -g react-tools 这会给你一个 jsx 二进制文件,你可以在facebook.github.io/react/downloads.html获得更多信息
          • @louisthebang 我不同意。 JSX 只是超脚本的合成糖。
          猜你喜欢
          • 2022-12-30
          • 2015-01-02
          • 2021-06-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-31
          • 2019-01-31
          • 2016-08-11
          相关资源
          最近更新 更多