React api: dangerouslySetInnerHTML

今天在項目中,遇到了一個需求:將后臺返回的 [微笑] [撇嘴] 這種表情文字轉(zhuǎn)化為emoji表情...

表情轉(zhuǎn)化組件

// 定義所有表情文字
const word = ["微笑","撇嘴","色","發(fā)呆","得意" ...]
    ...

class Face extends React.PureComponent<Props, State> {
    ...
// 文字轉(zhuǎn)圖片接口
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;

類似于微信聊天,由于數(shù)據(jù)中既有 圖片 又有 文字+表情,所以這里要判斷是否是圖片this.isImg,是圖片的話就將地址賦值給src,若包含[微笑]這種emoji標簽,則需要引用insetFace這個接口,將data傳入進行轉(zhuǎn)換。

index.tsx

// 引入
import { insetFace } from "@component/face";
  ...
export default class ScriptBox extends ListPage<Props, State> {
    constructor(props: Props) {
        super(props);
    }
    ...
    // 判斷是否圖片函數(shù)
    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>
}

渲染出來結(jié)果是下圖:


失敗.png

總結(jié)原因:

這里將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 的替換方案。通常來講,使用代碼直接設(shè)置 HTML 存在風險,因為很容易無意中使用戶暴露于跨站腳本(XSS)的攻擊。因此,你可以直接在 React 中設(shè)置 HTML,但當你想設(shè)置 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>
                ...
                ...

結(jié)果:

成功.png

注意:

  1. dangerouslySetInnerHTML的語法:第一層{ }代表JSX語法,第二層{ }是一個__html:string鍵值對
  2. 最初未用反引號包裹<img className="detail_img" src=${v[0]} />結(jié)果渲染的全是[object Object],想了半天才反應過來__html:string
  3. 用反引號包裹的html代碼不再是JSX語法,所以clasName要改為class
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 在Jq,原生javascript時期,在寫頁面時,往往強調(diào)的是內(nèi)容結(jié)構(gòu),層疊樣式,行為動作要分離,三者之間分...
    itclanCoder閱讀 801評論 0 2
  • HTML模版 之后出現(xiàn)的React代碼嵌套入模版中。 1. Hello world 這段代碼將一個一級標題插入到指...
    ryanho84閱讀 6,423評論 0 9
  • GUIDS 第一章 為什么使用React? React 一個提供了用戶接口的JavaScript庫。 誕生于Fac...
    jplyue閱讀 3,700評論 1 11
  • 以下內(nèi)容是我在學習和研究React時,對React的特性、重點和注意事項的提取、精練和總結(jié),可以做為React特性...
    科研者閱讀 8,398評論 2 21
  • 今天傍晚,剛下完雨,空氣濕潤,落山的太陽戀戀不舍,一道彩虹掛在天上,五顏六色很好看,像一座彩色的橋。這是我第一次見...
    美人如玉劍如虹_a962閱讀 301評論 0 0

友情鏈接更多精彩內(nèi)容