ReactNative WebView组件详解

作者: Code4Android | 来源:发表于2017-08-14 00:04 被阅读8081次

    源码传送门
    在开发Android的时候,一般我们会有一些加载网页的需求,或者执行一些JavaScript,我们都知道在Android中实现这个功能的控件是WebView,在ReactNative中也有实现此类需求额的组件,它的名字也是WebView。那么今天的这篇文章就来详细说说在ReactNative WebView的使用。本文示例效果图

    webview.gif

    属性

    • automaticallyAdjustContentInsets
      控制是否调整放置在导航条、标签栏或工具栏后面的web视图的内容。默认值为true

    • contentInset {top: number, left: number, bottom: number, right: number}
      设置网页内嵌边距

    • injectedJavaScript
      设置在网页加载之前注入一段js代码

    • mediaPlaybackRequiresUserAction
      设置页面中的HTML5音视频是否需要在用户点击后再开始播放。默认值为true

    • scalesPageToFit
      设置是否要把网页缩放到适应视图的大小,以及是否允许用户改变缩放比例。

    • source
      在WebView中指定加载内容html或者url,可以指定header,method等

    • startInLoadingState
      强制WebView在第一次加载时先显示loading视图。默认为true

    • domStorageEnabled(android)
      布尔值,指定是否开启DOM本地存储

    • javaScriptEnabled(android)
      布尔值,指定WebView中是否启用JavaScript。只在Android上使用,因为在iOS上默认启用了JavaScript。

    • mixedContentMode(android)
      指定混合内容模式。即WebView是否应该允许安全链接(https)页面中加载非安全链接(http)的内容,

      • 'never' (默认) - WebView不允许安全链接页面中加载非安全链接的内容
      • 'always' - WebView允许安全链接页面中加载非安全链接的内容。
      • 'compatibility' - WebView会尽量和浏览器当前对待此情况的行为一致
    • userAgent(android)
      为WebView设置user-agent字符串标识。这一字符串也可以在原生端用WebViewConfig来设置,但js端的设置会覆盖原生端的设置。

    • allowsInlineMediaPlayback(ios)
      指定HTML5视频是在网页当前位置播放还是使用原生的全屏播放器播放。 默认值为false,视频在网页播放还需要设置webkit-playsinline

    • bounces(ios)
      指定滑动到边缘后是否有回弹效果。

    • decelerationRate(ios)
      指定一个浮点数,用于设置在用户停止触摸之后,此视图应以多快的速度停止滚动。也可以指定预设的字符串值,如"normal"和"fast",

    • scrollEnabled(ios)
      是否启用滚动

    函数

    • injectJavaScript
      函数接受一个字符串,该字符串将传递给WebView,并立即执行为JavaScript
    • onError
      加载失败时回调
    • onLoad
      完成加载时回调
    • onLoadEnd
      加载成功或者失败都会回调
    • onLoadStart
      开始加载的时候回调
    • onMessage
      在webView内部网页中,调用window.postMessage可以触发此属性对应的函数,通过event.nativeEvent.data获取接收到的数据,实现网页和RN之间的数据传递
    • renderError
      返回一个视图用来提示用户错误
    • renderLoading
      返回一个加载指示器
    • onShouldStartLoadWithRequest(ios)
      请求自定义处理,返回true或false表示是否要继续执行响应的请求

    实战分析

    通过上面的介绍,我们已经对组件的属性以及函数有了大致的了解,当然只有这些是不够的,接下来就该组件的使用展开分析,效果图如文章开头的GIF图。对于该组件最简单的使用如下

            <WebView
                    source={{uri:'http://www.jianshu.com/u/d5b531888b2b'}}
                    style={{width:'100%',height:'100%'}}
                />
    

    指定source属性,加载网页,设置宽和高全屏,需要注意的是必须指定宽和高,否则将不显示组件,默认宽高都是0。
    给WebView增加加载时的回调

                        onLoad={(e) => console.log('onLoad')}
                        onLoadEnd={(e) => console.log('onLoadEnd')}
                        onLoadStart={(e) => console.log('onLoadStart')}
                        renderError={() => {
                            console.log('renderError')
                            return <View><Text>renderError回调了,出现错误</Text></View>
                        }}
                        renderLoading={() => {
                            return <View><Text>这是自定义Loading...</Text></View>
                        }}
    

    renderError可以自定义加载错误的提示信息View.当加载错误时会回调该函数,并且显示该函数返回的View。使用此方法我们可以自定义加载错误时的提示信息。
    而renderLoading函数可以自定义加载提示.当我们通过WebView加载一个网页时,往往我们有需求展示出请求的url,网页的标题,以及是否可前进或者后退。在WebView组件中有一个函数onNavigationStateChange可以实现此功能,他是在加载开始和结束的时候回调的,

       //添加属性
       onNavigationStateChange={this._onNavigationStateChange}
    
        _onNavigationStateChange = (navState) => {
            console.log(navState)
            this.setState({
                backButtonEnabled: navState.canGoBack,
                forwardButtonEnabled: navState.canGoForward,
                url: navState.url,
                status: navState.title,
                loading: navState.loading,
            });
        }
    

    当canGoBack返回值为true时,我们就可以使用this.webview.goBack();(this.webview是WebView的引用)对网页进行回退操作,同理当canGoForward为true时我们就可以使用 this.webview.goForward();对我们的网页进行跳转操作。当我们的网页url发生改变时我们可以使用 this.webview.reload();加载新的网页。

    加载HTML

         <WebView>
                style={{width:'100%',height:'100%'}}
                source={require('./helloworld.html');}
         </WebView>
    

    RN和Html通信

    当WebView加载html时我们可以实现html和rn之间的通信。rn向html发生数据可以通过postMessage函数实现。如下

    this.webview.postMessage('"Hello" 我是RN发送过来的数据');
    //在html中注册事件接收rn发过来的数据并显示在html中
        document.addEventListener('message', function(e) {
          messagesReceivedFromReactNative += 1;
          document.getElementsByTagName('p')[0].innerHTML =
            '从React Native接收的消息: ' + messagesReceivedFromReactNative;
          document.getElementsByTagName('p')[1].innerHTML = e.data;
        });
    
    

    在html中我们定义了一个按钮,并添加事件向rn发送数据

       //window.postMessage向rn发送数据
        document.getElementsByTagName('button')[0].addEventListener('click', function() {
          window.postMessage('这是html发送到RN的消息');
        });
    

    当html中调用了window.postMessage函数后,WebView的onMessage函数将会被回调,用来处理html向rn发送的数据,可以通过e.nativeEvent.data获取发送过来的数据。

        //接收HTML发出的数据
        _onMessage = (e) => {
            this.setState({
                messagesReceivedFromWebView: this.state.messagesReceivedFromWebView + 1,
                message: e.nativeEvent.data,
            })
            Alert.alert(e.nativeEvent.data)
        }
    

    JavaScript

    在android这个需要使用 javaScriptEnabled属性来支持JavaScript,ios默认是支持的,没有此属性。在WebView中提供了函数injectJavaScript(String),它有一个字符串参数,可以向webview中注入脚本,如下

        //脚本注入
        injectJS = () => {
            const script = 'document.write("Injected JS ")';  // eslint-disable-line quotes
            if (this.webview) {
                this.webview.injectJavaScript(script);
            }
        }
    

    最后需要注意的一点,ScrollView中嵌套WebView时滑倒会有冲突,需要特殊处理(目前还没研究处理方法。)今天的这篇文章就介绍这么多,所介绍的实例中,只提供了核心代码,如果想查看全部代码可以访问GitHub,由于认知有限,若有错误的地方欢迎指出,共同进步,谢谢。

    相关文章

      网友评论

      • lrxxhyf:请问,WebView 在Android端怎么禁止滚动,设置 scrollEnabled=false 只在iOS端有效,在Android端没效果
        Code4Android:@lrxxhyf 不让滚动的话,你超出内容就看不到了啊
      • 梦什么想_32d9:这个组件加载的网页怎么让他返回页面?,
        Code4Android:你看看这个,解决了android上不能选择图片拍照以及视频的缺陷,还有嵌套在ScrollView中高度问题,以及Android端部分手机闪退的bug。
        https://github.com/xiehui999/react-native-webview-plugin.git
      • turmando:有没有遇见过 rn里 webview 选择相册 在Android 设备没有效果
        blueblue_c41a:@乔同谢谢吆,解决了已经
        turmando:@blueblue_c41a https://github.com/Josin22/react-native-webview-android,可以看我这个
        blueblue_c41a:请问你解决了吗,我也遇到了同样的问题
      • marlti7:只有https在iOS可用,http怎么办
        Code4Android:@marlti7 现在都在主推https了,ios之前提出说不在支持http,使用http无法通过审核,不过最后又放开了,不知道现在还是啥情框,开发的时候是可以http的
      • 沧溟沧海啸:我用 var html2 = require('./helloworld.html'); 这种方式加载就成功,用 var html2 = `<p>...</p>` 的方式就报错,不知道为啥
        Code4Android:@lvbunny 你测试了吗?为啥我可以.一看你就是没试过。上传的demo也有显示html文件的
        lvbunny:require加载的是js文件,并不能加载html
        沧溟沧海啸:是因为在模拟器上网速慢所以显示不出来
      • uuuuuuw:作者你好 你这个通信 我用了没成功 方便加个方式 解答一下嘛 谢谢 onMessage这个方法不能被调用
        Code4Android: @lin_易困 你可以下载下demo操作下
      • 13ac8a3cf43f:请问,RN 的WebView加载一个设置了字体的H5页面,显示的还是默认字体,怎么让WebView显示H5上设置的字体?ios端没问题

      本文标题:ReactNative WebView组件详解

      本文链接:https://www.haomeiwen.com/subject/bgnrrxtx.html