将 HTML 传递给自定义组件

Posted

技术标签:

【中文标题】将 HTML 传递给自定义组件【英文标题】:Pass HTML into custom Component 【发布时间】:2021-12-28 11:38:45 【问题描述】:

我创建了一个自定义组件来简单地在 IonCardContent 中布局内容。到目前为止,这非常适合我的需求:

interface ContainerProps 
    position?: string;
    content?: string,
    colour?: string;
    custClass?: string;


const CardContainer: React.FC<ContainerProps> = ( position = "right", content = "n/a", colour = "", custClass = "" ) => 
    
    if ( position.trim().toLowerCase() === "right" ) 
        return <><div className="ion-float-right " + custClass >content</div><div className="clear-right"></div></>
     else if ( position.trim().toLowerCase() === "left" ) 
        return <div className="ion-float-left " + custClass>content</div> 
     else if ( position.trim().toLowerCase() === "full" ) 
        return <div className=""  + custClass>content</div>
     else if ( position.trim().toLowerCase() === "empty" )  
        return <div className=""  + custClass>&nbsp;</div> 
     else 
        return null
      
;

export default CardContainer;

但是,我现在想开始将一些 html 元素传递给组件,这样我就可以通过使文本变为粗体或将部分字符串包装在 span 中并添加一个 css 类来突出显示文本部分它。

目前,将 html 添加到 content 属性只会导致 this 显示为文字字符串。这显然是由于“内容”被声明为字符串。

显示 html 的解决方案是简单地更改接口中的类型声明吗?如果是这样,该怎么办?还是需要更复杂的解决方案?

谢谢。

【问题讨论】:

我不知道 ionic,但是你不能用 React 的 children 属性来传递它们吗?- reactjs.org/docs/composition-vs-inheritance.html#containment 这能回答你的问题吗? How to safely render html in react? @Dilshan,感谢您的提示。奇怪的是,这对我来说是一个新概念。我不确定它在这种情况下是否真的有效,但它确实帮助我处理了我遇到的另一个问题。 @E.Maggini 我不确定是不是。我不需要清理,因为“html”是系统生成的。我只需要能够将传入的字符串显示为 html 而不是字符串。因此,例如将其传递给组件“HELLO”,它会显示为 html,而不是显示为文字字符串。谢谢。 @E.Maggini 我已经考虑了这些信息,否则我将无法说; “我不确定它是不是”。根据blog.logrocket.com/…,您在使用 dangerouslySetInnerHTML 时不需要进行清理。此外,我从自定义组件本身返回 html,没有进行任何清理。因此,我的回应是; “我不确定是不是”。 【参考方案1】:

来自 cmets 中的重复答案:

import sanitizeHtml from 'sanitize-html';

const MyComponent = () => 
  dirty = '<a href="my-slug" target="_blank" onClick="evil()">click</a>';
  const clean = sanitizeHtml(dirty, 
    allowedTags: ['b', 'i', 'em', 'strong', 'a'],
    allowedAttributes: 
      a: ['href', 'target']
    
  );
  return (
    <div 
      dangerouslySetInnerHTML=__html: clean
    />
  );
;

因此

import sanitizeHtml from 'sanitize-html';

interface ContainerProps 
    position?: string;
    content?: string,
    colour?: string;
    custClass?: string;


 const CardContainer: React.FC<ContainerProps> = ( position = "right", 
 content = "n/a", colour = "", custClass = "" ) => 

const myHTML = null;
    
    if ( position.trim().toLowerCase() === "right" ) 
        myHTML = '<div className="ion-float-right " + custClass >content</div><div className="clear-right"></div>'
     else if ( position.trim().toLowerCase() === "left" ) 
        myHTML = '<div className="ion-float-left " + custClass>content</div>' 
     else if ( position.trim().toLowerCase() === "full" ) 
        myHTML = '<div className=""  + custClass>content</div>'
     else if ( position.trim().toLowerCase() === "empty" )  
        myHTML = '<div className=""  + custClass>&nbsp;</div>'
    

 const clean = sanitizeHtml(myHTML, 
    allowedTags: ['b', 'i', 'em', 'strong', 'a'],
    allowedAttributes: 
      a: ['href', 'target']
    
  );
  return (
    <div 
      dangerouslySetInnerHTML=__html: clean
    />
  );
;

export default CardContainer;

您当然需要调整 allowedTags 和 allowedAttribute 值以满足您的需要

【讨论】:

谢谢,这很有帮助。我试试看。 不幸的是,这给了我在条件语句中生成的标记字符串中显示变量的各种问题。另外,我很困惑为什么我的 if/else 字符串显示没有经过清理,但是你说 html 必须在 react 可以显示之前进行清理。 我已经设法进行了一些更改,以使我更接近最终结果。谢谢。【参考方案2】:

将我的所有 html 输出以及通过变量传入的动态内容传递到 santizer 中意味着变量要么被剥离,要么它们的调用显示为文字标记。

因此,有必要只清理包含传递给组件的 html 内容的变量。

import React from 'react';
import './CardContainer.css';
import sanitizeHtml from 'sanitize-html';

interface ContainerProps 
    position?: string;
    content?: string,
    colour?: string;
    custClass?: string;


const CardContainer: React.FC<ContainerProps> = ( position = "right", content = "n/a", colour = "", custClass = "" ) => 
    
    const clean = sanitizeHtml(content, 
        allowedTags: ['b', 'i', 'em', 'strong', 'a', 'div', 'span'],
        allowedAttributes: 
          a: ['href', 'target'],
          div: ['class', 'className'],
          span: ['style', 'class', 'className']
        
    );
    


    if ( position.trim().toLowerCase() === "right" ) 
        return <><div className="ion-float-right " + custClass dangerouslySetInnerHTML=__html: clean/><div className="clear-right"></div></>
     else if ( position.trim().toLowerCase() === "left" ) 
        return <div className="ion-float-left " + custClass dangerouslySetInnerHTML=__html: clean/>
     else if ( position.trim().toLowerCase() === "full" ) 
        return <div className=""  + custClass dangerouslySetInnerHTML=__html: clean/>
     else if ( position.trim().toLowerCase() === "empty" )  
        return <div className=""  + custClass>&nbsp;</div> 
     else 
        return null
      
;

export default CardContainer;

【讨论】:

以上是关于将 HTML 传递给自定义组件的主要内容,如果未能解决你的问题,请参考以下文章

如何将 navigator.pop 传递给自定义反应原生组件

如何在尚未对其进行评估的情况下将变量传递给自定义组件?

如何将 `value` 道具和 `v-model` 道具分配给自定义 Vue 组件?

AngularJs给自定义组件添加样式不起作用怎么办?

Vue中给自定义属性添加属性

道具不会传递给 React Native Navigation v2 中的自定义顶部栏标题组件