用React.js组件替换部分html字符串并渲染(没有dangerouslySetInnerHTML)

时间:2016-10-26 14:51:06

标签: javascript wordpress reactjs

我正在使用从WordPress API获取数据的Node.js / React.js客户端,而且我遇到了相当棘手的问题。但希望你可以帮助我! :)

所以我把这种数据作为WordPress API(单页内容)中的字符串:

"<h1>Curabitur turpis.</h1>
<p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>
[gravityform id=&#8221;42&#8243; title=&#8221;true&#8221; description=&#8221;true&#8221;]
<h2>Donec vitae orci sed</h2>
<p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p>
<blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote>
<ul><li>item</li><li>item</li><li>item</li></ul>"

我需要做的是将短代码[gravityform id=&#8221;42&#8243; title=&#8221;true&#8221; description=&#8221;true&#8221;]替换为React组件<GravityForm />和想要的事件处理程序等,并按原样渲染其他html元素。

我正在做替换,如:

export const replaceGravityFormShortcode = html => {
    if(!html) return html;
    const gravityFormRegexp = /\[gravityform id=.([0-9]{1,}).*?\]/g;
    return replace(
        html,
        gravityFormRegexp,
        function (fullMatch, id) {
            return <GravityForm key={id} formId={id} />;
        }
    );
};

因此,已经涵盖了用React组件替换[shortcodes],但之后html数据如下所示: [ 0:"<h1>Curabitur turpis.</h1><p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>" 1:Object (GravityForm-component) 2:"<h2>Donec vitae orci sed</h2><p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p><blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote><ul><li>item</li><li>item</li><li>item</li></ul>" ]

很明显,因为

而无法在render()内工作
  1. 如果我只渲染该数据,表单工作正常,但默认情况下所有html字符串都会被转义
  2. 如果我使用dangerouslySetInnerHTML,它看起来像这样(<GravityForm />[object Object]dangerouslySetInnerHTML-screenshot
  3. 对于这个问题,有没有合理的解决方案?或者应该从不同的角度来看待它?

    感谢您的帮助!

    修改

    @joy是的,您的解决方案是将html字符串更改为React Components,但它仍然无法解决html转义问题。所以我仍然有像(screenshot

    这样的输出
    <h1>Curabitur turpis.</h1><p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>
    <h2>Donec vitae orci sed</h2><p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p><blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote><ul><li>item</li><li>item</li><li>item</li></ul>
    

    但是,甚至可以在不从字符串中逐个解析html元素的情况下渲染该html吗?

    编辑2(解决方案 - 种类)

    所以我终于找到了〜解决这个案例的方法。

    1. 我使用react-html-parser来解析数据字符串中的html元素
    2. 然后数据就像(Objects is React elements): [ 0:Object 1:Object 2:"[gravityform id=”42″ title=”true” description=”true”]" 3:Object 4:Object 5:Object 6:Object ]
    3. 最后循环显示数据replaceGravityFormShortcodesFromArrayOfObjects(arrayOfObjects),将[gravityform id=”42″ title=”true” description=”true”]替换为<GravityForm />,然后只渲染数据
    4. export const replaceGravityFormShortcodesFromArrayOfObjects =(dataArray) => {
          if(!dataArray) return dataArray;
          const gravityFormRegexp = /\[gravityform id=.([0-9]{1,}).*?\]/g;
          forEach(dataArray, (value, index) => {
              if(typeof value === 'string'){
                  const temp = replace(
                      value,
                      gravityFormRegexp,
                      function (fullMatch, id) {
                          return <GravityForm key={id} formId={id} />;
                      }
                  );
                  if(temp.length === 1 && isObject(temp[0])){
                      dataArray = [
                          ...dataArray.slice(0, index),
                          temp[0],
                          ...dataArray.slice(index + 1),
                      ];
                  }
              }
          }
          return dataArray;
      };
      

      但是只有在html结构深度为一级时才有效。如果"[gravityform id=”42″ title=”true” description=”true”]"位于React元素props.children中,那么它会变得棘手,我还没有找到可行的解决方案。

1 个答案:

答案 0 :(得分:0)

我遇到了完全相同的问题,这是我的解决方案:

定义字符串:

const s = `<h1>Curabitur turpis.</h1>
<p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>
[gravityform id=&#8221;42&#8243; title=&#8221;true&#8221; description=&#8221;true&#8221;]
<h2>Donec vitae orci sed</h2>
<p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p>
<blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote>
<ul><li>item</li><li>item</li><li>item</li></ul>`

[*]分割字符串:

const normalText = s.split(/\[[\s\S]+\]/g)

提取ID:

let ids = [];
const re = /\[gravityform id=.*([0-9]{1,}).*\]/g;
s.replace(re, (fullMatch, id) => {
  ids.push(id)
})

现在,数组normalTextids具有我们想要连接的内容。简单地说吧:

const output = normalText.map((text, index) => {
  <div>
    {text}
    <GravityForm key={ids[index]} formId={ids[index]} />
  </div>
})

// Then put `output` in the `render` function

您可能希望稍微调整正则表达式,因为您的字符串包含一些像&#8221;这样的unicode。要么先移除它们,要么先逃脱它们。

更新

为了不逃避HTML:

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

参考:https://facebook.github.io/react/docs/dom-elements.html