React 15.6.2使用dangerouslySetInnerHTML渲染页面时图片无法显示求助
问题根因
你的问题本质是相对路径的解析上下文不一致:
- 你通过fetch拿到的HTML文件本身存放在
/assets/getting_started/路径下,当它作为独立页面加载时,内部的images/help-feature_main-menu.jpeg相对路径会被解析为/assets/getting_started/images/help-feature_main-menu.jpeg,可以正常访问 - 当你用
dangerouslySetInnerHTML把这段HTML插入当前React页面的DOM树时,这段内容属于当前页面的上下文,相对路径会以当前浏览器地址栏的URL为基准进行解析,和原HTML文件的路径无关,自然找不到对应的图片 - 控制台无报错大概率是因为你的SPA配置了所有不存在路径都fallback返回首页HTML,状态码为200,浏览器不会抛出404错误,但无法将HTML内容识别为图片,所以只显示破损图标
- iframe能正常加载是因为iframe是独立的文档上下文,路径基准就是iframe的src地址,和原HTML独立访问的逻辑一致。
可行解决方案
方案1:批量补全所有相对资源的绝对路径(推荐,无副作用)
拿到HTML字符串后,用正则匹配所有img标签的src属性,给相对路径补全原HTML所在的路径前缀即可:
componentDidMount() { fetch('/assets/getting_started/index.html') .then(response => { if(response.status >= 400) { throw new Error(`${response.status}: ${response.statusText}`); } return response.text(); }) .then(html => { // 处理img的相对路径 const processedHtml = html.replace(/<img [^>]*src=['"]([^'"]+)['"][^>]*>/gi, (match, src) => { // 已经是http/https开头或者/开头的绝对路径不需要处理 if (src.startsWith('http') || src.startsWith('/')) return match; // 补全原HTML所在目录的前缀 return match.replace(src, `/assets/getting_started/${src}`); }); this.setState({ html: processedHtml }); }); }
如果你的HTML里还有CSS、JS等其他相对路径资源,只需要补充对应正则规则即可。
方案2:插入base标签统一指定路径基准(更省事)
在HTML的head部分插入base标签,统一指定所有相对路径的解析基准,不需要挨个处理资源:
componentDidMount() { fetch('/assets/getting_started/index.html') .then(response => { if(response.status >= 400) { throw new Error(`${response.status}: ${response.statusText}`); } return response.text(); }) .then(html => { // 插入base标签,指定路径基准为原HTML所在目录 const baseTag = '<base href="/assets/getting_started/">'; const processedHtml = html.replace('</head>', `${baseTag}</head>`); this.setState({ html: processedHtml }); }); }
注意:这个方案会影响插入HTML内所有a标签的跳转路径,如果你的HTML内有锚点跳转或者站内跳转,需要按需调整base的href属性,或者单独处理a标签的target属性。
内容的提问来源于stack exchange,提问作者michael
相关产品推荐
相关产品推荐

