【问题标题】:converting a function into jsx将函数转换为 jsx
【发布时间】:2018-05-22 13:56:50
【问题描述】:

我有两个函数,一个是解析 html 字符串以将其标题放入数组中

const str = "<h1>test-1<h1><h2>test1-1<h2><h3>test1-1-1</h3><h1>test1-2<h1><h2>test1-2-1</h2><h3>test1-2-2</h3><h1>test-2</h1><h1>test-3</h1><h1>test-4</h1>
"
const wrapper = document.createElement('div');
wrapper.innerHTML = str.trim();

let tree = [];
let leaf = null;

for (const node of wrapper.querySelectorAll("h1, h2, h3, h4, h5, h6"))
{
    const nodeLevel = parseInt(node.tagName[1]);
    const newLeaf = { level: nodeLevel, text: node.textContent, children: [], parent: leaf };

    while (leaf && newLeaf.level <= leaf.level)
        leaf = leaf.parent;

    if (!leaf)
        tree.push(newLeaf);
    else
        leaf.children.push(newLeaf);

    leaf = newLeaf;
}

另一个将这些标题解析为目录功能的列表

const ol = document.createElement("ol");

(function makeOl(ol, leaves)
{
    for (const leaf of leaves)
    {
        const li = document.createElement("li");
        li.appendChild(new Text(leaf.text));

        if (leaf.children.length > 0)
        {
            const subOl = document.createElement("ol");
            makeOl(subOl, leaf.children);
            li.appendChild(subOl);
        }

        ol.appendChild(li);
    }
})(ol, tree);

它会输出这样的字符串

"<ol><li>test-1<ol><li>test1-1<ol><li>test1-1-1</li></ol></li><li>test1-2<ol><li>test1-2-1</li><li>test1-2-2</li></ol></li></ol></li><li>test-2</li><li>test-3</li><li>test-4</li></ol>"

渲染成类似

的东西
  1. 测试1
    1. test1-1
      1. test1-1-1
    2. 测试1-2
      1. test1-2-1
      2. test1-2-2
  2. 测试2
  3. test-3
  4. test-4

我仍然习惯于 React 的 jsx 部分,我想知道如何转换该函数,以便 ol 和 li 是 React/jsx 元素而不是原始 html 字符串,因为这需要另一个步骤渲染例如。

<div dangerouslySetInnerHTML={{__html: olString}} />

我使用 jsx 和数组的方式是这样的

const list = tree.map((headers) => <li>{headers.value}</li>)
<div><ul>{list}</ul></div>

【问题讨论】:

  • 我不确定你在这里问什么。 JSX 只是一个语法规范。您是否只是想将已解析的 HTML 树重建为 React 元素节点树?
  • @LINKIWI,没错

标签: javascript reactjs


【解决方案1】:

您可以随时使用React.createElement

例如

React.createElement('div', null, `Hello ${this.props.toWhat}`);

但是,最佳实践可能是这样的。

// reusable Tree component
export default class Tree extends Component {

  static propTypes = {
    children: PropTypes.array.isRequired
  }

  render() {

    const { children } = this.props

    return (
      <ol>
        {children.map(leaf =>
          <li key={leaf.id}>
            <span>{leaf.text}</span>
            {leaf.children && <Tree children={leaf.children}/>}
          </li>
        )}
      </ol>
    )
  }
}

// (re)use it 
function render() {
  return (
    <Tree children={ tree } />
  );
}

您甚至可以将 HTML Elements 设为变量。

<Tree children={ tree } listNode="ul" listElementNode="li" />

然后在 Tree 组件中

function render() {
    const {listNode: UL, listElementNode: LI} = this.props;
    return (<UL></UL>);
}

【讨论】:

  • 虽然我很确定这是 OP 想要完成的任务,但要直接回答如何转换为 JSX 语法的问题,您可以这样做 const Elem = 'li'; return &lt;Elem&gt;...&lt;/Elem&gt;
  • 我现在正在写这个。 :)
  • 您的每个列表元素中是否都有唯一的“id”?
  • 似乎在每个h3之后创建空的ol标签
  • 好吧,那是一些实现问题。我可以非常自信地向您保证,我的回答总体上是有效的。我建议,你用你得到的更新你的代码/问题。或者,使用您拥有的代码和遇到的问题/错误创建一个新问题。
【解决方案2】:

目前,您有一个递归函数 (makeOl),我将其替换为 renderLeaf 函数:

一种渲染方式是:

class Tree extends React.Component {
  render() {
    let leafs = this.props.children
    return (
      <React.Fragment>
        {leafs.map(this.renderLeaf)}
      </React.Fragment>
    )
  }
  renderLeaf(leaf) {
    return (
      <ol>
        <li>
          {leaf.text}
          {leaf.children && leaf.children.map(this.renderLeaf)}
        </li>
      </ol>
    )
  }
}

然后您可以将其用作:&lt;Tree children={tree} /&gt;

【讨论】:

    猜你喜欢
    • 2018-11-07
    • 2016-09-27
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 2021-12-08
    相关资源
    最近更新 更多