这是我参与11月更文挑战的第1天,活动详情查看:11月更文挑战
前言:
在一次与第三方对接的过程中,向后端发起了一个请求,他直接返回了一个html,然后需要展示到页面上。于是展开了下面的行动。
dangerouslySetInnerHTML
dangerouslySetInnerHTML 是 React 为浏览器 DOM 提供 innerHTML 的替换方案。通常来讲,使用代码直接设置 HTML 存在风险,因为很容易无意中使用户暴露于跨站脚本(XSS)的攻击。因此,你可以直接在 React 中设置 HTML,但当你想设置 dangerouslySetInnerHTML 时,需要向其传递包含 key 为 __html 的对象,以此来警示你。例如:
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
在了解到这个属性以后,我直接三下五除二,就直接一手复制。大致代码如下。
// 请求部分去取到回填htmlText 变量中
// react return
<div dangerouslySetInnerHTML={{ __html: htmlText }}></div>
虽然页面展示出来了,但是还有几个问题,js没法加载,以及script里面的js也没有执行。于是我就先做了最简单的尝试,我把htmlText换成了如下的代码.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
console.log('test---');
</script>
<div>test</div>
</body>
</html>
这个html就是一个div,然后会打印console.log。然后发现,这个代码的console也打印不出来,于是我猜想dangerouslySetInnerHTML可能就只是把html直接加进入,script是不会解析的。于是这个办法没辙,只能另寻他法。
iframe
于是我想到了iframe,这个可以直接内嵌网页的好东西。但是我这次需要发起的请求是post,传统我们了解到的iframe都是默认是get请求。那如何去做post请求呢,果然google上好东西,大家之前都有过探索了。
结合form表单,利用form表单的post请求方式达到目的,实现方式如下
实现方式 增加一个form表单的标签,method设置为post,target设置一个标识,假如target=”target1” 在iframe设置name属性,name需要与target一致 name = “target1”
发送请求时通过发送form submit请求来使用post方式
html代码
<div>
<form id="form1" action="" target="target1" method="post"></form>
<iframe id="xxx" name="target1" src=""></iframe>
</div>
具体在react中的实现如下。
import { isOrdinaryCompany } from '@/common/project';
import { message, Result, Spin } from 'antd';
import React, { useEffect } from 'react';
export default () => {
const handleClick = () => {
dispatch({
type: 'insurance/fetchPcOrganizeDockingInsurance',
payload: {
creditCode: currentUser?.creditCode || '',
},
})
.then((res) => {
const r = JSON.parse(res);
// 将参数回填至表单最终提交
const { ediparam = '', edisign = '' } = r;
document.getElementById('ediparam').value = ediparam;
document.getElementById('edisign').value = edisign;
document.getElementById('form1').submit();
})
.catch((err) => {
message.error(err);
});
};
useEffect(() => {
if (isOrdinaryCompany()) {
handleClick();
}
}, []);
return (
<>
<div>
<Spin spinning={loading}>
<form
id="form1"
action={`${window.location.origin}/ProjectInsurance/gateway.do`}
target="target1"
method="post"
>
<input id="edisign" name="edisign" value="隐藏域" type="hidden" />
<input id="ediparam" name="ediparam" value="隐藏域" type="hidden" />
</form>
<iframe
id="xxx"
name="target1"
src=""
width="100%"
height="500"
title="红绿灯"
frameBorder="no"
/>
</Spin>
</div>
</>
);
};
最终的效果
iframe嵌入成功。