(React Native) 加载本地 HTML 文件到 WebView

46

我尝试在 React Native 中将本地的 .html 文件加载到 WebView 中:

// load local .html file
const PolicyHTML = require('./Policy.html');

// PolicyHTML is just a number of `1`
console.log('PolicyHTML:', PolicyHTML);

// will cause an error: JSON value '1' of type NSNumber cannot be converted to NSString
<WebView html={PolicyHTML} />

读取 .html 文件时应该将其作为字符串而不是资源代表来读取。

如何在React Native中将 .html 文件加载到 WebView 中?


顺便问一下,从 require() 获取的资源代表的类型是什么?是 number 吗?


你找到解决方案了吗?请更新正确的答案。 - SoundStage
@Rai 还没有。:( - Xaree Lee
1
现在已经是2019年了,但仍然没有简单的方法! - mukesh.kumar
7个回答

47

试一下:

const PolicyHTML = require('./Policy.html');

<WebView
  source={PolicyHTML}
  style={{flex: 1}}
 />

你能解释一下这段代码是做什么的,或者为什么它能够工作吗? - Omri Luzon
@Fmussap,嗯,但我在iOS发布版本上使用了这个解决方案,它有效。 - Vitalii Obideiko
2
我想使用带有查询参数的HTML:?title=test&sound=1 由于我们“需要”一个HTML文件,我该如何添加参数? - user2078023
react-native-webview 在 Expo Web 中无法工作。 - Iman Marashi
1
在安卓上无法工作。 - famfamfam
显示剩余2条评论

16

我在搜索静态HTML加载时遇到了这篇文章。
如果您的HTML代码是通过API检索的,您可以以以下方式呈现WebView:

<WebView
    originWhitelist={['*']}
    source={{ html: html, baseUrl: '' }}
/>

请注意,如文档所述,originWhitelist是必需的:

请注意,静态HTML将需要设置originWhitelist,例如["*"]。


值得一提的是,这里的“baseUrl”部分是我需要修复的部分,所以感谢您指出了这一点。 - Cheyne
1
谢谢你指出了这个baseUrl的问题,你救了我的一天。 - Waheed Akhtar

6
<View style={{flex: 1}}>
    <WebView
      style={{flex: 1}}
      source={require("./resources/index.html")}
    />
</View>

为了创建 WebView,父元素必须具有尺寸或 flex:1 属性。我们还可以将 WebView 设置为 flex:1,以便它填充整个父元素。

4

使用Expo工具和通常使用Expo:

import { WebView } from "react-native-webview";
import { readAsStringAsync } from "expo-file-system";
import { useAssets } from "expo-asset";

export const MusicSheet = () => {
  const [index, indexLoadingError] = useAssets(
    require("../assets/musicsheetview/index.html")
  );

  const [html, setHtml] = useState("");

  if (index) {
    readAsStringAsync(index[0].localUri).then((data) => {
        setHtml(data);
    });
  }

  return (
    <View style={styles.container}>
      <WebView
        onLoad={() => {}}
        source={{ html }}
        onMessage={(event) => {}}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    height: 100,
    display: "flex",
  },
});

2
如果您需要提供本地资源,那么:
1. 将所有资源与index.html一起放置在android/app/src/main/assets/www中(您可以使用gradle任务将它们复制到该位置)。 2. 然后:
  var uri = Platform.OS == "android" ?
    "file:///android_asset/www/index.html" :
    "./web/www/index.html"
  return <WebView source={{ uri }} />

对于iOS尚未测试,请添加说明,应如何存储资产


2
我得到了"ERR_FILE_NOT_FOUND"。 - SeanMC

2
如果您正在处理资源,项目目录在构建项目后会与设备目录不同,因此您不能仅通过字符串URL引用它们。

Expo

如果使用Expo,则必须require每个资产,然后在要缓存到设备本地存储的require上使用useAssets

useAssets将返回一个包含localUri(这是已缓存图像的URI)的对象。

然后,您可以使用localUri并将其作为图像的src

    import { useAssets } from 'expo-asset';
    /* . . . */
    const IndexHTML = require('./assets/index.html');
    const myImage = require('./assets/splash.png');

    // url link after image is cached to the device
    const [imgSrc, setImgSrc] = useState('');

    const [image, imerr] = useAssets(myImage);
    const [html, error] = useAssets(IndexHTML);

    const webViewProps = {
        javaScriptEnabled: true,
        androidLayerType: 'hardware',
        originWhitelist: ['*'],
        allowFileAccess: true,
        domStorageEnabled: true,
        mixedContentMode: 'always',
        allowUniversalAccessFromFileURLs: true,

        onLoad: () => {
            console.log(image[0].localUri);
            setImgSrc(image[0].localUri);
        },
        source: {
            html: '<img src="' + imgSrc + '"/>',
        },
    };

    return <WebView {...webViewProps} />

    const webViewProps = {
        ...
        source: IndexHTML,
    };

注意:对于 Expo 方法,IndexHTML 中引用的文件将找不到

  1. 窍门是将您的 HTML 转换为 字符串文字 以利用 模板字符串

  2. 然后,您必须手动要求每个这些资产来连接 localUrl

  3. require() 支持有限类型,您需要在根文件夹中添加 metro.config.js

  4. 如果您 require() 一个 .js 文件,它会出现错误,因为它将其读取为模块,解决方法是 打包您的资产

const { getDefaultConfig } = require('expo/metro-config');

const config = getDefaultConfig(__dirname);

config.resolver.assetExts.push(
    // Adds support for asset file types
    'css', 'ppt', 'obj'
);

module.exports = config;

此外,Expo 可以热重载使用缓存资产所做的更改。
React Native 如果你的目录中有 android 文件夹,请导航到
android > app > build.gradle 然后添加。
android {
    /* link assets to the local storage of device */
    sourceSets { 
        main { assets.srcDirs = ['src/main/assets', '../../source/assets/'] } 
        //                      [do not touch,    'relative to your asset'] }
    }
    . . .

最后,你在Gradle中链接的相对文件夹可以通过file:///android_asset/访问。

例如:file:///android_asset/index.html -> /asset/index.html

return <WebView source={{uri: `file:///android_asset/index.html`}} />
  • 对于IOS,这是如何操作的

  • 另一方面,您需要重建vanilla react以查看资产中的更改...大约需要20分钟左右

替代方案

一个快速解决方案是集成静态服务器, 但这是一个最近的fork,它只适用于vanilla react native。


0

试试这个:

  • .html文件添加到您的项目中。
  • 在您想要使用WebView组件的文件中编写如下代码:

    const OurStoryHTML = require ('./OurStory.html')

  • <WebView source={OurStoryHTML} style={{flex: 1, marginTop : 44}} />

这可能会对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接