使用 HtmlComponent 组件
<HtmlComponent
html={'html'}
onMessage={(message) => {
console.log("Received message===>:", message);
}}
/>
创建 HtmlComponent.tsx
import { WebView, WebViewMessageEvent } from "react-native-webview";
import AutoHeightWebView from "react-native-autoheight-webview";
import css from "./css";
import js from "./javascript";
import { Platform, View, ViewStyle } from "react-native";
import { useEffect } from "react";
import WebViewAutoHeight from "./WebViewAutoHeight";
type Props = {
html: string;
onLayout?: any;
styles?: ViewStyle;
htmlCss?: string;
baseCss?: boolean;
onMessage?: (message: { type: string; data: any }) => void;
};
export function HtmlComponent({
html,
onLayout,
styles,
htmlCss,
baseCss,
onMessage,
}: Props) {
// web端onMessage事件回调
const postMessage = (message: { type: string; data: any }) => {
if (Platform.OS === "web") {
onMessage && onMessage(message);
}
};
useEffect(() => {
if (Platform.OS === "web") {
eval(js);
}
}, []);
return Platform.OS === "web" ? (
<View
style={[{ width: "100%" }, styles]}
onLayout={onLayout}>
{baseCss != false && <style>{css}</style>}
<style>{htmlCss}</style>
<div
className={baseCss != false ? "article-detail-html" : ""}
dangerouslySetInnerHTML={{ __html: html }}
/>
</View>
) : (
<WebViewAutoHeight
style={styles}
onLayout={onLayout}
source={{
html:
"<style>" +
htmlCss +
"</style>" +
`<div class="${baseCss != false ? "article-detail-html" : ""}">` +
html +
"</div>",
}}
webStyle={baseCss != false ? css : ""}
webScript={js}
onMessage={(event) => {
const message = JSON.parse(
event.nativeEvent?.data || "{type: '', data: {}}"
);
onMessage && onMessage(message);
}}
/>
);
}
创建 WebViewAutoHeight.tsx
用于替代 import AutoHeightWebView from “react-native-autoheight-webview”
注意 react-native-autoheight-webview 加载内容动态变化时存在闪问题
import WebView, { WebViewProps } from "react-native-webview";
import { StyleProp, ViewStyle, View } from "react-native";
import { useState } from "react";
import { WebViewSourceHtml } from "react-native-webview/lib/WebViewTypes";
export interface SizeUpdate {
width: number;
height: number;
}
export interface Props extends WebViewProps {
onSizeUpdated?: (size: SizeUpdate) => void;
style?: StyleProp<ViewStyle>;
webScript?: string;
webStyle?: string;
}
export default function WebViewAutoHeight({
style,
source,
webScript,
webStyle,
onMessage,
onSizeUpdated,
}: Props) {
let [height, setHeight] = useState(0);
// size更新
const sizeUpdateScript = `
(function () {
getCurrentSize();
function getCurrentSize() {
let lastHeight = null;
let lastWidth = null;
const fun = () => {
const currentHeight = document.getElementById("webview_root_html").offsetHeight;
const currentWidth = document.getElementById("webview_root_html").offsetHeight;
if (lastHeight !== currentHeight) {
if (window.ReactNativeWebView?.postMessage) {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: "size",
data: { height: currentHeight, width: currentWidth },
}));
}
lastHeight = currentHeight;
lastWidth = currentWidth;
}
};
setInterval(fun, 500);
fun();
}
})();
`;
// 注入html、css、js
const injectHtml = (html: string) => {
return `
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
${webStyle}
</style>
</head>
<body>
<div id="webview_root_html">
${html}
</div>
<script>
${sizeUpdateScript}
${webScript}
true;
</script>
</body>
</html>
`;
};
return (
<View style={[{ width: "100%", height: height || "100%" }]}>
<WebView
style={[{ width: "100%", height: "100%" }, style]}
source={
(source as WebViewSourceHtml)?.html != undefined
? { html: injectHtml((source as WebViewSourceHtml).html) }
: source
}
scalesPageToFit={false}
onMessage={(event) => {
const message = JSON.parse(
event.nativeEvent?.data || "{type: '', data: {}}"
);
// console.log("Received from web:", message);
if (message && message.type && message.data) {
// 尺寸更新
if (message.type == "size") {
setHeight(message.data?.height);
onSizeUpdated && onSizeUpdated(message.data);
} else {
onMessage && onMessage(event);
}
} else {
onMessage && onMessage(event);
}
}}
/>
</View>
);
}
&spm=1001.2101.3001.5002&articleId=147616034&d=1&t=3&u=05005df626ca4ebebf124ba983afa9f4)
311

被折叠的 条评论
为什么被折叠?



