使用dangerouslySetInnerHTML的疑惑

#1

我需要把markdowon转化成html在页面中呈现,所以我使用了dangerouslySetInnerHTML

<div ref="article" className="markdown" dangerouslySetInnerHTML={{__html: this.props.content}}></div>

我写了一个自动为文章生成目录的库,并希望在render完成后为它生成目录:

componentDidMount () {
  let article = React.findDOMNode(this.refs.article);
  let index = autoIndex(article);
  this.props.onIndexed(index);
}

然而我发现此时获取到的article中并没有children,于是我推测此时组件虽然被挂载,但文章却还并没有被render。

于是我试着在下一次事件循环再生成目录。

setTimeout(() => {
  let article = React.findDOMNode(this.refs.article);
  let index = autoIndex(article);
  this.props.onIndexed(index);
}, 0);

然而并没有什么用。现在我用一个1s的timeout来让目录生成出来,但这样的方式并不靠谱,有什么办法可以确认dangerouslySetInnerHTML真正的把html给set好呢?感谢大家 :blush:


回来填坑:

过了段时间又回过头来看这个问题,在github上也提了issue,突然发现是自己傻了:

其实这并不是dangerouslySetInnerHTML的问题,经过多次测试,componentDidMount的时候,dangerouslySetInnerHTML已经完成了自己的工作。我遇到这个问题的原因其实是因为我的文章内容是异步获取然后更新我的Render组件的props,所以Render组件第一次mount,content其实还没有拿到…在componentDidUpdate的时候看content更新的话,就重新生成一次目录即可。

1 Like
#2

我看componentDidMount只能保证ref#article存在了, 你可以把set this.props.content这个动作放在componentDidMount里完成article。innerHTML= this.props.content,不过这越来越像传统模式,操作DOM,背离react风格

#3

嗯 这正是我纠结的地方

#4

感觉这样要弄明白 React 内部的渲染逻辑才行, 一般我们写组件, 都是基于 React 的语法写的, 不会自己去碰 DOM.
另外 innerHTML 我的似乎以前也碰到过问题, 觉得可能要特殊处理, anyway, 内部渲染逻辑不清楚.

#5

同不建议自己处理 DOM

#6

我也是逼不得已,在考虑更好的解决方案

#7

把autoindexer 改一下,不要用 document.getElementById,用element.querySelector,这样就可以传入element。
react这边不需要用 dangerouslySetInnerHTML,把article转为element,再调用autoindexer,最后直接render这个element。

#8

我的autoIndexer本来就是直接传入一个HTMLElement,另外你说的article转element,我可以得到的是用marked编译得到的html字符串,如何转为element,还望指教 :anguished:

#9
var div = document.createElement('<div>.....</div>')

div.querySelector 可以不需要添加到DOM,document.getElementById 必须要加入DOM才能操作

#10

如果

dangerouslySetInnerHTML={{__html: this.props.content}}

里面的 content包含 自定义的react组件和 表标签怎么处理呢?比如:

 dangerouslySetInnerHTML={{__html: <span>
            {
               <ClassA text={`被引用${item.refCount}`}>
                <i className="color-version">{item.refCount}</i>
               </ClassA>
            }
          </span>}} 

这样还是会变成 object,有没有更好的办法?

#11

找到了解决方案 。。。。

#12

请问是怎么解决的呢?

#13

请问最后的解决方案是怎样的?我现在也遇到了同样的问题