React api: dangerouslySetInnerHTML

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

表情转化组件

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

class Face extends React.PureComponent<Props, State> {
    ...
// 文字转图片接口
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,
                    `<img class="emoji-item" src='${require("@img/face/face_" +word.indexOf(w) +".png")}'/>`
                );
            }
        });
    }
    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<Props, State> {
    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 (
                        <React.Fragment key={i}>
                            {v[0] && v[0].length > 0 && (
                                <div className="detail-item">
                                    <div className="name"> A:</div>
                                    <div className="content">
                                        {this.isImg(v[0]) ?
                                          (<img className="detail_img" src={v[0]} />) : ( insetFace(v[0]) )}
                                    </div>
                                </div>
                                )}
                               ...
                               ...
                      </React.Fragment>
}

渲染出来结果是下图:


失败.png

总结原因:

这里将insetFace接口返回的<img class="emoji-item" src='${require("@img/face/face_" +word.indexOf(w) +".png")}'/>当作字符串来渲染。类似于JS的innerText,而需求则是将其作用为innerHTML
所以这里需要引入react的一个apidangerouslySetInnerHTML

dangerouslySetInnerHTML api官方文档介绍

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

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

function MyComponent() {
  return <div dangerouslySetInnerHTML={createMarkup()} />;
}

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

...
...
{targetData.scriptmessage.map(
        (v: any, i: number) => {
            return (
                <React.Fragment key={i}>
                    {v[0] && v[0].length > 0 && (
                        <div className="detail-item">
                            <div className="name">A:</div>
                            <div className="content"
                                dangerouslySetInnerHTML={{
                                    __html: this.isImg(v[0])
                                        ? `<img class="detail_img" src=${v[0]} />`
                                        : insetFace( v[0] )
                                }}
                            >
                            </div>
                        </div>
                    )}
                </React.Fragment>
                ...
                ...

结果:

成功.png

注意:

  1. dangerouslySetInnerHTML的语法:第一层{ }代表JSX语法,第二层{ }是一个__html:string键值对
  2. 最初未用反引号包裹<img className="detail_img" src=${v[0]} />结果渲染的全是[object Object],想了半天才反应过来__html:string
  3. 用反引号包裹的html代码不再是JSX语法,所以clasName要改为class
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 在Jq,原生javascript时期,在写页面时,往往强调的是内容结构,层叠样式,行为动作要分离,三者之间分...
    itclanCoder阅读 740评论 0 2
  • HTML模版 之后出现的React代码嵌套入模版中。 1. Hello world 这段代码将一个一级标题插入到指...
    ryanho84阅读 6,314评论 0 9
  • GUIDS 第一章 为什么使用React? React 一个提供了用户接口的JavaScript库。 诞生于Fac...
    jplyue阅读 3,595评论 1 11
  • 以下内容是我在学习和研究React时,对React的特性、重点和注意事项的提取、精练和总结,可以做为React特性...
    科研者阅读 8,297评论 2 21
  • 今天傍晚,刚下完雨,空气湿润,落山的太阳恋恋不舍,一道彩虹挂在天上,五颜六色很好看,像一座彩色的桥。这是我第一次见...
    美人如玉剑如虹_a962阅读 297评论 0 0