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


在 App 中,渲染 html 是一個非常常見的功能,有可能是直接渲染 html 字符串或者是通過 URL 渲染遠程 HTML頁面。react Native 提供了一個 WebView 組件以供我們實現 HTML 的渲染。

早先 WebView 是在 react Native 核心包中,后來為了減小 React Native 核心包的體積,便將其單獨提出到react-native-webview 組件中。

話不多說,讓我們來試試這個組件吧。

 

渲染遠程 HTML 內容

在開始之前,你需要使用 yarn/npm 來安裝它:

yarn add react-native-webview

安裝完成后,我們就可以在代碼中使用它:

import React, { Component } from 'react'; import { View } from 'react-native'; import { WebView } from 'react-native-webview'; export default class App extends Component { render() { return ( <View> <WebView source={{ uri: 'https://www.baidu.com' }} /> </View> ) } }

需要注意的是:第一次安裝完成后,需要重新執行一次 react-native run-* 讓 rn 幫我們自動 link 一次,否則會拋出以下錯誤:

重新執行 react-native run-* 后,報錯沒了,但是頁面上一片空白。

這是什么原因呢?在查看了一下文檔之后,發現 WebView 默認是不會自動設置其高度,所以這個時候高度是0,我們才無法在頁面中找到它。需要注意的是,如果 WebView 的父級組件是 View, 直接使用 style 給 WebView 組件設置高度是無效的,需要給這個 View 組件設置高度才能正常顯示。然而在 ScrollView 中,則是需要給 WebView 本身設置 height。其它幾個組件,例如 SafeAreaView 我沒有去嘗試,需要你自己親自去檢驗。

知道原因后,我們將 WebView 父組件設置 style 為 flex: 1 ,讓其鋪滿整個屏幕,在 reload 一次看看效果:

大功高程,我們已經成功的把百度展現到我們的 App 中了。

 

渲染 HTML 字符串

有時候我們需要將 API 中返回的 HTML 字符串解析出來。渲染 HTML 字符串的時候,我們需要將 source 中的 uri 替換為 html,它的值就是我們的 HTML 字符串。與 uri 不同的是,渲染 HTML 字符串的時候,我們需要設置originWhitelist,比如可以設為["*"]來允許運行本地代碼。

{/* ... */} <WebView originWhitelist={['*']} source={{ html: `<h1>這里是一個標題</h1>` }} /> {/* ... */}

到這里我們就成功的把標題給渲染出來了。

 

根據內容自動計算高度

往往我們無法提前預知 HTML 內容的高度,所以我們無法給其設置一個固定的高度,而是需要根據內容來設置其高度。

為了達到這個目的,我們需要用到 injectedJavaScript 和 onMessage ,

injectedJavaScript

這個屬性的作用是設置一個在網頁加載之前執行的 js 代碼。

onMessage

在 webview 內部的網頁中調用 window.postMessage 方法時可以觸發此屬性對應的函數,從而實現網頁和 RN 之間的數據交換。 設置此屬性的同時會在 webview 中注入一個 postMessage 的全局函數並覆蓋可能已經存在的同名實現。

網頁端的 window.postMessage 只發送一個參數 data,此參數封裝在 RN 端的 event 對象中,即 event.nativeEvent.data。data 只能是一個字符串。

import React, { Component } from 'react'; import { View, ScrollView, SafeAreaView } from 'react-native'; import { WebView } from 'react-native-webview'; export default class App extends Component { constructor(props) { super(props); this.state = { webViewHeight: 0 }; } {/* 根據內容計算 WebView 高度 */} onWebViewMessage = (event) => { this.setState({ webViewHeight: Number(event.nativeEvent.data) }); } render() { return ( <View style={{ flex: 1 }}> <View style={{ height: 100, backgroundColor: 'yellow' }}></View> <View style={{ height: this.state.webViewHeight }}> <WebView originWhitelist={['*']} source={{ html: `<p>這里是一個標題</p>` }} injectedJavaScript='window.ReactNativeWebView.postMessage(document.documentElement.scrollHeight)' onMessage={this.onWebViewMessage} /> </View> <View style={{ height: 100, backgroundColor: 'green' }}></View> </View> ) } }

從上圖可以看出我們的 WebView 已經根據其中內容動態的計算了其高度。但是還是有一個問題,這里的文字太小了,要解決這個問題我們需要用到 meta - viewport 。

廣州品牌設計公司https://www.houdianzi.com

采用響應式布局

這個其實很簡單,只需要在 header 中設置 meta 標簽即可。

<WebView
  originWhitelist={['*']} source={{ html: ` <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <p>這里是一個標題</p> </body> </html> ` }} injectedJavaScript='window.ReactNativeWebView.postMessage(document.documentElement.scrollHeight)' onMessage={this.onWebViewMessage} />


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM