如何阻止React为自闭合HTML标签<source>添加闭合标签?
如何阻止React渲染 时生成闭合标签?
我用HTML的<picture>、<source>和<img>标签创建了一个React组件,组件会生成多个<source>选项,末尾设置了备用的<img>标签。React渲染组件时,<img>能正确以自闭合形式呈现,但每个<source>元素都被自动添加了闭合标签</source>,导致W3C验证报错,请问该如何阻止这种行为?
我定义了六个存储不同分辨率图片的变量,JSX代码如下:
<source media={`(max-width: 200px)`} srcset={`${small_src}, ${small_src2x} 2x`} /> <source media={`(max-width: 400px)`} srcset={`${mid_src}, ${mid_src2x} 2x`} /> <img src={large_source} srcset={`${large_source}, ${large_source2x} 2x`} />
渲染后的HTML结果为:
<picture> <source media="(max-width: 200px)" srcset="..pathToSmall, ..pathToSmall@2x 2x"> </source> <source media="(max-width: 400px)" srcset="..pathToMid, ..pathToMid@2x 2x"> </source> <img src="..pathToLarge" srcset="..pathToLarge, ..pathToLarge@2x 2x"> </picture>
可见<img>没有多余的闭合标签,但<source>被添加了</source>。虽然浏览器能正常运行,但W3C验证会标记错误:
<picture> <source media="(max-width: 200px)" srcset="pic1.jpg, pic1@2x.jpg 2x"></source> <source media="(max-width: 400px)" srcset="pic2.jpg, pic2@2x.jpg 2x"></source> <img alt="hi" src="pic2.jpg"> </picture>
错误提示:Stray end tag source.
解决办法
1. 使用React.createElement手动创建<source>元素
JSX编译器会对部分空元素自动补全闭合标签,直接用createElement可以精准控制输出,避免生成多余的闭合标签。示例代码:
import React from 'react'; function ResponsivePicture() { // 定义图片路径变量 const small_src = 'path/to/small.jpg'; const small_src2x = 'path/to/small@2x.jpg'; const mid_src = 'path/to/mid.jpg'; const mid_src2x = 'path/to/mid@2x.jpg'; const large_source = 'path/to/large.jpg'; const large_source2x = 'path/to/large@2x.jpg'; return ( <picture> {React.createElement('source', { media: '(max-width: 200px)', srcset: `${small_src}, ${small_src2x} 2x` })} {React.createElement('source', { media: '(max-width: 400px)', srcset: `${mid_src}, ${mid_src2x} 2x` })} <img src={large_source} srcset={`${large_source}, ${large_source2x} 2x`} alt="描述图片内容" // 记得添加alt属性提升可访问性 /> </picture> ); } export default ResponsivePicture;
2. 借助dangerouslySetInnerHTML(不推荐)
如果不想用createElement,也可以通过dangerouslySetInnerHTML直接插入HTML字符串,但这种方式存在XSS风险,仅在确定内容安全的场景下使用:
import React from 'react'; function ResponsivePicture() { const small_src = 'path/to/small.jpg'; const small_src2x = 'path/to/small@2x.jpg'; const mid_src = 'path/to/mid.jpg'; const mid_src2x = 'path/to/mid@2x.jpg'; const large_source = 'path/to/large.jpg'; const large_source2x = 'path/to/large@2x.jpg'; const pictureHTML = ` <picture> <source media="(max-width: 200px)" srcset="${small_src}, ${small_src2x} 2x"> <source media="(max-width: 400px)" srcset="${mid_src}, ${mid_src2x} 2x"> <img src="${large_source}" srcset="${large_source}, ${large_source2x} 2x" alt="描述图片内容"> </picture> `; return <div dangerouslySetInnerHTML={{ __html: pictureHTML }} />; } export default ResponsivePicture;
内容的提问来源于stack exchange,提问作者Walrus
相关产品推荐
相关产品推荐

