React api: dangerouslySetInnerHTML

今天在项目中,遇到了一个需求:将后台返回的 [微笑] [撇嘴] 这种表情文字转化为emoji表情...

表情转化组件

// 定义所有表情文字
const word = ["微笑","撇嘴","色","发呆","得意" ...]
    ...

class Face extends React.PureComponent {
    ...
// 文字转图片接口
public insetFace(content: string): any {
    if (!content || content.trim().length <= 0) {
        return "";
    }
    let reg = /\[.*?\]/gi;  //匹配表情正则
    let rgArr = content.match(reg);
    if (rgArr && rgArr.length > 0) {
        rgArr.map((item: string) => {
            let w = item.replace(/^\[|\]$/gi, "");
            if (word.indexOf(w) != -1) {
                content = content.replace(
                    item,
                    ``
                );
            }
        });
    }
    return content;
}
    ...
export const insetFace = FaceFun.insetFace;

类似于微信聊天,由于数据中既有 图片 又有 文字+表情,所以这里要判断是否是图片this.isImg,是图片的话就将地址赋值给src,若包含[微笑]这种emoji标签,则需要引用insetFace这个接口,将data传入进行转换。

index.tsx

// 引入
import { insetFace } from "@component/face";
  ...
export default class ScriptBox extends ListPage {
    constructor(props: Props) {
        super(props);
    }
    ...
    // 判断是否图片函数
    isImg(data: string) {
        if (!data || data.length <= 0) {
            return false;
        }
        let reg = /^https?:\/\/.*?.(png|jpg|jpeg)$/gi;
        return reg.test(data);
    }
  ...
     {targetData &&targetData.scriptmessage &&targetData.scriptmessage.length > 0 &&
        targetData.scriptmessage.map(
                (v: any, i: number) => {
                    return (
                        
                            {v[0] && v[0].length > 0 && (
                                
A:
{this.isImg(v[0]) ? () : ( insetFace(v[0]) )}
)} ... ...
}

渲染出来结果是下图:


失败.png

总结原因:

这里将insetFace接口返回的当作字符串来渲染。类似于JS的innerText,而需求则是将其作用为innerHTML
所以这里需要引入react的一个apidangerouslySetInnerHTML

dangerouslySetInnerHTML api官方文档介绍

dangerouslySetInnerHTML 是 React 为浏览器 DOM 提供 innerHTML 的替换方案。通常来讲,使用代码直接设置 HTML 存在风险,因为很容易无意中使用户暴露于跨站脚本(XSS)的攻击。因此,你可以直接在 React 中设置 HTML,但当你想设置 dangerouslySetInnerHTML 时,需要向其传递包含 key 为 __html 的对象,以此来警示你。例如:

function createMarkup() {
  return {__html: 'First · Second'};
}

function MyComponent() {
  return 
; }

在此次应用中,将index.tsx中的代码改为:

...
...
{targetData.scriptmessage.map(
        (v: any, i: number) => {
            return (
                
                    {v[0] && v[0].length > 0 && (
                        
A:
` : insetFace( v[0] ) }} >
)}
... ...

结果:

成功.png

注意:

  1. dangerouslySetInnerHTML的语法:第一层{ }代表JSX语法,第二层{ }是一个__html:string键值对
  2. 最初未用反引号包裹结果渲染的全是[object Object],想了半天才反应过来__html:string
  3. 用反引号包裹的html代码不再是JSX语法,所以clasName要改为class

你可能感兴趣的:(React api: dangerouslySetInnerHTML)