Reatjs ile ham html oluşturma


154

Öyleyse reaktjs ile ham html oluşturmanın tek yolu bu mu?

// http://facebook.github.io/react/docs/tutorial.html
// tutorial7.js
var converter = new Showdown.converter();
var Comment = React.createClass({
  render: function() {
    var rawMarkup = converter.makeHtml(this.props.children.toString());
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2>
        <span dangerouslySetInnerHTML={{__html: rawMarkup}} />
      </div>
    );
  }
});

Ben JSX ile şeyler işaretlemek için bazı serin yolları olduğunu biliyorum, ama ben esas olarak (tüm sınıflar, satır içi stilleri, vb ..) ham html render edebilmek ilgileniyorum. Böyle karmaşık bir şey:

<!-- http://getbootstrap.com/components/#dropdowns-example -->
<div class="dropdown">
  <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-expanded="true">
    Dropdown
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Another action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Something else here</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated link</a></li>
  </ul>
</div>

JSX tüm bunları yeniden yazmak zorunda kalmak istemem.

Belki de bunların hepsini yanlış düşünüyorum. Lütfen düzelt beni.


1
Bu neredeyse JSX. Ham HTML olarak çok fazla işaretleme yaparsanız, React gibi bir kitaplık kullanmanın avantajını kaybedersiniz. React öğelerini işlemek için küçük değişiklikler ("class" -> "className" gibi) yapmanızı tavsiye ederim.
Ross Allen

2
Bu özel örnek için birisi sizin için işi zaten yapmıştır , ancak soru hala genel durum için geçerlidir.
Randy Morris

Yanıtlar:


43

html-to-reactNpm modülünden yararlanabilirsiniz .

Not: Modülün yazarıyım ve birkaç saat önce yayınladım. Lütfen hataları veya kullanılabilirlik sorunlarını bildirmekten çekinmeyin.


24
dangerouslySetInnerHTML dahili olarak kullanıyor mu?
Yash Sharma

2
Kodu kontrol ettim. Tehlikeli olarak görünmüyorSetInnerHTML.
Ajay Raghav

Mike hala bu npm modülünü aktif olarak sürdürüyor musunuz?
Daniel

Hey Daniel, yapmadım ve katkıda bulunanlardan biri devraldı ve son sürümü 7 ay önce yayınladı. Bkz. Github.com/aknuds1/html-to-react
Mike

Bu, tehlikeli olarak SetSnerHTML kullanmaz.
Tessaracter

185

HTML oluşturmak için artık daha güvenli yöntemler var. Bir önceki yanıtta bu örtülü burada . 4 seçeneğiniz var, son kullanımlar dangerouslySetInnerHTML.

HTML oluşturma yöntemleri

  1. En kolay - Unicode'u kullanın, dosyayı UTF-8 olarak kaydedin ve UTF-8 olarak ayarlayın charset.

    <div>{'First · Second'}</div>

  2. Daha Güvenli - Bir Javascript dizesindeki varlık için Unicode numarasını kullanın.

    <div>{'First \u00b7 Second'}</div>

    veya

    <div>{'First ' + String.fromCharCode(183) + ' Second'}</div>

  3. Veya dizeleri ve JSX öğeleri içeren karışık bir dizi.

    <div>{['First ', <span>&middot;</span>, ' Second']}</div>

  4. Last Resort - kullanarak ham HTML ekleyin dangerouslySetInnerHTML.

    <div dangerouslySetInnerHTML={{__html: 'First &middot; Second'}} />


Tek ihtiyacım 3 ya da 4
Nicolas S.Xu

dangerouslySetInnerHTML__html dışında diğer özelliklerin ne olduğunu merak ediyor
Juan Solano

30
Ben bu iş parçacığı seviyorum ... dolaylı olarak: "# 4 kullanmamak için elinden geleni yap". Herkes: "# 4 harika çalıştı!"
deepelement

1
@JuanSolano yok, bir TypeScript ortamındaki otomatik tamamlama girişlerine göre.
Andreas Linnert

Benzer bir soruda stackoverflow.com/questions/19266197/… , bu cevap çok iyi sonuç vermedi. Belki bu soru için daha uygun veya belki insanlar cevabı okumuyor ...: D
425nesp

27

Bunu hızlı ve kirli durumlarda kullandım:

// react render method:

render() {
    return (
      <div>
        { this.props.textOrHtml.indexOf('</') !== -1
            ? (
                <div dangerouslySetInnerHTML={{__html: this.props.textOrHtml.replace(/(<? *script)/gi, 'illegalscript')}} >
                </div>
              )
            : this.props.textOrHtml
          }

      </div>
      )
  }

7
Bu güvenli değil - HTML içeriyorsa ne olur <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" onload="alert('test');">?
yjwong

11
Oluşturulan HTML'nin kontrolü sizde güvende
John

18

Bu saf bileşeni denedim:

const RawHTML = ({children, className = ""}) => 
<div className={className}
  dangerouslySetInnerHTML={{ __html: children.replace(/\n/g, '<br />')}} />

Özellikleri

  • Alır classNamepervane (tarzına o kadar kolay)
  • Yerini \niçin <br />(genellikle bunu yapmak ister)
  • Aşağıdaki gibi bir bileşeni kullanırken içeriği çocuk olarak yerleştirin :
  • <RawHTML>{myHTML}</RawHTML>

Bileşeni HTML oluşturmak için Github: RawHTML: ReactJS saf bileşeninde bir Gist'e yerleştirdim


12
export class ModalBody extends Component{
    rawMarkup(){
        var rawMarkup = this.props.content
        return { __html: rawMarkup };
    }
    render(){
        return(
                <div className="modal-body">
                     <span dangerouslySetInnerHTML={this.rawMarkup()} />

                </div>
            )
    }
}

Yukarıdaki iş benim için, html modal vücuda geçiyordu.
Jozcar

12

dangerouslySetInnerHTML , React'ın DOM tarayıcısında innerHTML kullanımı yerine geçer. Genel olarak, HTML'yi koddan ayarlamak risklidir çünkü kullanıcılarınızı yanlışlıkla siteler arası komut dosyası (XSS) saldırısına maruz bırakmak kolaydır.

Ham HTML'nizi DOM yoluyla enjekte etmeden önce (örn. DOMPurify kullanarak) sterilize etmek daha iyi / daha güvenlidir dangerouslySetInnerHTML.

DOMPurify - HTML, MathML ve SVG için yalnızca DOM, süper hızlı, uber toleranslı XSS ​​dezenfektanı. DOMPurify güvenli bir varsayılanla çalışır, ancak birçok yapılandırılabilirlik ve kanca sunar.

Örnek :

import React from 'react'
import createDOMPurify from 'dompurify'
import { JSDOM } from 'jsdom'

const window = (new JSDOM('')).window
const DOMPurify = createDOMPurify(window)

const rawHTML = `
<div class="dropdown">
  <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-expanded="true">
    Dropdown
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Another action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Something else here</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated link</a></li>
  </ul>
</div>
`

const YourComponent = () => (
  <div>
    { <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(rawHTML) }} /> }
  </div>
)

export default YourComponent

Bu cevapta aradığım şey tam olarak bu. Daha fazla oy olmalı
llamerr

6

Ayrıştırıcı adı verilen bu kütüphaneyi kullandım . İhtiyacım olan şey için çalıştı.

import React, { Component } from 'react';    
import Parser from 'html-react-parser';

class MyComponent extends Component {
  render() {
    <div>{Parser(this.state.message)}</div>
  }
};

3
21KB (8KB sıkıştırılmış). Bunu tarayıcı kodu için doğrulayamadım.
Peter Bengtsson

bu kütüphane Expo uygulamamı kırıyor
ekkis

5

dangerouslySetInnerHTMLkesinlikle gerekli olmadıkça kullanılmamalıdır. Dokümanlara göre, "Bu esas olarak DOM string manipülasyon kütüphaneleri ile işbirliği yapmak içindir" . Bunu kullandığınızda, React'in DOM yönetiminden faydalanırsınız.

Sizin durumunuzda, geçerli JSX sözdizimine dönüştürmek oldukça kolaydır; sadece classnitelikleri olarak değiştirin className. Veya yukarıdaki yorumlarda belirtildiği gibi, Bootstrap öğelerini React bileşenlerine kapsülleyen ReactBootstrap kitaplığını kullanabilirsiniz .


8
Cevabınız için teşekkürler. İnnerHTML kullanmanın güvenlik üzerindeki etkilerini anlıyorum ve JSX'e dönüştürebileceğimi biliyorum. Ancak özellikle React'in ham HTML snippet'lerini kullanma desteğini soruyorum.
vinhboy

"React'in ham HTML snippet'lerini kullanma desteği" ile tam olarak ne demek istiyorsun?
Breno Ferreira

2

İşte daha önce yayınlanan RawHTML işlevinin biraz daha az düşünülmüş bir sürümü. Size şunları sağlar:

  • etiketi yapılandır
  • isteğe bağlı olarak yeni satır için yerine <br />sitesindeki
  • RawHTML'nin oluşturulan öğeye ileteceği fazladan destek sağlama
  • boş bir dize ( RawHTML></RawHTML>) sağlama

İşte bileşen:

const RawHTML = ({ children, tag = 'div', nl2br = true, ...rest }) =>
    React.createElement(tag, {
        dangerouslySetInnerHTML: {
            __html: nl2br
                ? children && children.replace(/\n/g, '<br />')
                : children,
        },
        ...rest,
    });
RawHTML.propTypes = {
    children: PropTypes.string,
    nl2br: PropTypes.bool,
    tag: PropTypes.string,
};

Kullanımı:

<RawHTML>{'First &middot; Second'}</RawHTML>
<RawHTML tag="h2">{'First &middot; Second'}</RawHTML>
<RawHTML tag="h2" className="test">{'First &middot; Second'}</RawHTML>
<RawHTML>{'first line\nsecond line'}</RawHTML>
<RawHTML nl2br={false}>{'first line\nsecond line'}</RawHTML>
<RawHTML></RawHTML>

Çıktı:

<div>First · Second</div>
<h2>First · Second</h2>
<h2 class="test">First · Second</h2>
<div>first line<br>second line</div>
<div>first line
second line</div>
<div></div>

Kesilecek:

<RawHTML><h1>First &middot; Second</h1></RawHTML>

0

Başımda div'a izin verilmeyen onLoad özniteliğine sahip bir bağlantı kullanmam gerekiyordu, bu da bana önemli bir acı verdi. Geçerli geçici çözümüm orijinal komut dosyası etiketini kapatmak, ne yapmam gerektiğini yapmak, sonra komut dosyası etiketini açmak (orijinal tarafından kapatılacak). Umarım bu, başka seçeneği olmayan birine yardımcı olabilir:

<script dangerouslySetInnerHTML={{ __html: `</script>
   <link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans" as="style" onLoad="this.onload=null;this.rel='stylesheet'" crossOrigin="anonymous"/>
<script>`,}}/>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.