嘎哈像啥 發表於 2020-11-22 19:29:00

React Native 使用 react-native-webview 渲染 HTML

<p>在 App 中,渲染&nbsp;html&nbsp;是一个非常常见的功能,有可能是直接渲染&nbsp;html&nbsp;字符串或者是通过 URL 渲染远程 HTML页面。react&nbsp;Native 提供了一个 WebView 组件以供我们实现 HTML 的渲染。</p>
<p>早先 WebView 是在&nbsp;react&nbsp;Native 核心包中,后来为了减小 React Native 核心包的体积,便将其单独提出到react-native-webview&nbsp;组件中。</p>
<p>话不多说,让我们来试试这个组件吧。</p>
<p>&nbsp;</p>
<h2>渲染远程 HTML 内容</h2>
<p>在开始之前,你需要使用 yarn/npm&nbsp;来安装它:</p>
<pre><code class="hljs nginx"><span class="hljs-attribute">yarn add react-native-webview</span></code></pre>
<p>安装完成后,我们就可以在代码中使用它:</p>
<pre><code class="hljs javascript"><span class="hljs-keyword">import React, { Component } <span class="hljs-keyword">from <span class="hljs-string">'react';
<span class="hljs-keyword">import { View } <span class="hljs-keyword">from <span class="hljs-string">'react-native';
<span class="hljs-keyword">import { WebView } <span class="hljs-keyword">from <span class="hljs-string">'react-native-webview';

<span class="hljs-keyword">export <span class="hljs-keyword">default <span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">App <span class="hljs-keyword">extends <span class="hljs-title">Component {
render() {
    <span class="hljs-keyword">return (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">WebView <span class="hljs-attr">source=<span class="hljs-string">{{ <span class="hljs-attr">uri: '<span class="hljs-attr">https://<span class="hljs-attr">www.baidu.com' }} /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">View&gt;
    )
}
}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
<p>需要注意的是:第一次安装完成后,需要重新执行一次&nbsp;react-native run-*&nbsp;让 rn 帮我们自动 link 一次,否则会抛出以下错误:</p>
<p><img src="http://api.fly63.com/vue_blog/public/Uploads/20191023/5db04b2a8b404.jpg"></p>
<p>重新执行&nbsp;react-native run-*&nbsp;后,报错没了,但是页面上一片空白。</p>
<p>这是什么原因呢?在查看了一下文档之后,发现 WebView 默认是不会自动设置其高度,所以这个时候高度是0,我们才无法在页面中找到它。需要注意的是,如果 WebView 的父级组件是 View, 直接使用&nbsp;style&nbsp;给 WebView 组件设置高度是无效的,需要给这个 View 组件设置高度才能正常显示。然而在 ScrollView 中,则是需要给 WebView 本身设置 height。其它几个组件,例如&nbsp;SafeAreaView&nbsp;我没有去尝试,需要你自己亲自去检验。</p>
<p>知道原因后,我们将 WebView 父组件设置 style 为&nbsp;flex: 1&nbsp;,让其铺满整个屏幕,在 reload 一次看看效果:</p>
<p><img src="http://api.fly63.com/vue_blog/public/Uploads/20191023/5db04b31dcbae.jpg"></p>
<p>大功高程,我们已经成功的把百度展现到我们的 App 中了。</p>
<p>&nbsp;</p>
<h2>渲染 HTML 字符串</h2>
<p>有时候我们需要将 API 中返回的 HTML 字符串解析出来。渲染 HTML 字符串的时候,我们需要将 source 中的 uri 替换为 html,它的值就是我们的 HTML 字符串。与 uri 不同的是,渲染 HTML 字符串的时候,我们需要设置originWhitelist,比如可以设为["*"]来允许运行本地代码。</p>
<pre><code class="hljs javascript">{<span class="hljs-comment">/* ... */}
&lt;WebView
originWhitelist={[<span class="hljs-string">'*']}
source={{ <span class="hljs-attr">html: <span class="hljs-string">`&lt;h1&gt;这里是一个标题&lt;/h1&gt;` }}
/&gt;
{<span class="hljs-comment">/* ... */}</span></span></span></span></span></code></pre>
<p>到这里我们就成功的把标题给渲染出来了。</p>
<p>&nbsp;</p>
<h2>根据内容自动计算高度</h2>
<p>往往我们无法提前预知 HTML 内容的高度,所以我们无法给其设置一个固定的高度,而是需要根据内容来设置其高度。</p>
<p>为了达到这个目的,我们需要用到&nbsp;injectedJavaScript&nbsp;和&nbsp;onMessage&nbsp;,</p>
<h3>injectedJavaScript</h3>
<p>这个属性的作用是设置一个在网页加载之前执行的&nbsp;js&nbsp;代码。</p>
<h3>onMessage</h3>
<p>在 webview 内部的网页中调用 window.postMessage 方法时可以触发此属性对应的函数,从而实现网页和 RN 之间的数据交换。 设置此属性的同时会在 webview 中注入一个 postMessage 的全局函数并覆盖可能已经存在的同名实现。</p>
<p>网页端的 window.postMessage 只发送一个参数 data,此参数封装在 RN 端的 event 对象中,即 event.nativeEvent.data。data 只能是一个字符串。</p>
<pre><code class="hljs javascript"><span class="hljs-keyword">import React, { Component } <span class="hljs-keyword">from <span class="hljs-string">'react';
<span class="hljs-keyword">import { View, ScrollView, SafeAreaView } <span class="hljs-keyword">from <span class="hljs-string">'react-native';
<span class="hljs-keyword">import { WebView } <span class="hljs-keyword">from <span class="hljs-string">'react-native-webview';

<span class="hljs-keyword">export <span class="hljs-keyword">default <span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">App <span class="hljs-keyword">extends <span class="hljs-title">Component {
<span class="hljs-keyword">const</span><span class="hljs-keyword">ructor(props) {
    <span class="hljs-keyword">super(props);

    <span class="hljs-keyword">this.state = { <span class="hljs-attr">webViewHeight: <span class="hljs-number">0 };
}

{<span class="hljs-comment">/* 根据内容计算 WebView 高度 */}
onWebViewMessage = <span class="hljs-function">(<span class="hljs-params">event) =&gt; {
    <span class="hljs-keyword">this.setState({ <span class="hljs-attr">webViewHeight: <span class="hljs-built_in">Number(event.nativeEvent.data) });
}

render() {
    <span class="hljs-keyword">return (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View <span class="hljs-attr">style=<span class="hljs-string">{{ <span class="hljs-attr">flex: <span class="hljs-attr">1 }}&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">View <span class="hljs-attr">style=<span class="hljs-string">{{ <span class="hljs-attr">height: <span class="hljs-attr">100, <span class="hljs-attr">backgroundColor: '<span class="hljs-attr">yellow' }}&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">View&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">View <span class="hljs-attr">style=<span class="hljs-string">{{ <span class="hljs-attr">height: <span class="hljs-attr">this.state.webViewHeight }}&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">WebView
            <span class="hljs-attr">originWhitelist=<span class="hljs-string">{['*']}
            <span class="hljs-attr">source=<span class="hljs-string">{{ <span class="hljs-attr">html: `&lt;<span class="hljs-attr">p&gt;这里是一个标题<span class="hljs-tag">&lt;/<span class="hljs-name">p&gt;` }}
            injectedJavaScript='window.ReactNativeWebView.postMessage(document.documentElement.scrollHeight)'
            onMessage={this.onWebViewMessage}
          /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">View&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">View <span class="hljs-attr">style=<span class="hljs-string">{{ <span class="hljs-attr">height: <span class="hljs-attr">100, <span class="hljs-attr">backgroundColor: '<span class="hljs-attr">green' }}&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">View&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">View&gt;
    )
}
}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
<p><img src="http://api.fly63.com/vue_blog/public/Uploads/20191023/5db04b3960144.jpg"></p>
<p>从上图可以看出我们的 WebView 已经根据其中内容动态的计算了其高度。但是还是有一个问题,这里的文字太小了,要解决这个问题我们需要用到&nbsp;meta - viewport&nbsp;。</p>
<p><span style="position: relative; left: -100000px">广州品牌设计公司https://www.houdianzi.com</span></p>
<h3>采用响应式布局</h3>
<p>这个其实很简单,只需要在 header 中设置 meta 标签即可。</p>
<pre><code class="hljs php">&lt;WebView
originWhitelist={[<span class="hljs-string">'*']}
source={{ html: `
&lt;html&gt;
    &lt;head&gt;
      &lt;meta name=<span class="hljs-string">"viewport" content=<span class="hljs-string">"width=device-width, initial-scale=1.0"&gt;
    &lt;/head&gt;

    &lt;body&gt;
      &lt;p&gt;这里是一个标题&lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;
` }}
injectedJavaScript=<span class="hljs-string">'window.ReactNativeWebView.postMessage(document.documentElement.scrollHeight)'
onMessage={this.onWebViewMessage}
/&gt;</span></span></span></span></code></pre><br><br>
来源:https://www.cnblogs.com/qianxiaox/p/14020584.html
頁: [1]
查看完整版本: React Native 使用 react-native-webview 渲染 HTML