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

更新日期: 2019-10-19阅读: 5.9k标签: 渲染

在 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 。


采用响应式布局

这个其实很简单,只需要在 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}
/>


总结

到此,关于 React Native 的基础使用我们已经讲完了,更多细节请参考以下链接:


链接: https://fly63.com/article/detial/6078

vue中数据更新变化,而页面视图未渲染的解决方案

在使用vue的时候,我们都知道它是双向数据绑定的,但是在使用不熟的情况下,经常会遇到:data中的数据变化了,但是并没有触发页面渲染。下面就整理一些出现这种情况的场景以及解决办法。

服务端渲染和客户端渲染的对比

这里结合art-template模板引擎说明。首先了解下前端页面中如何使用art-template。当不需要对SEO友好的时候,推荐使用客户端渲染;当需要对 SEO友好的时候,推荐使用服务器端渲染

解决使用vue.js未渲染前代码显示问题

在使用vue的时候,偶然发现多次刷新或者网络加载缓慢的时候,会一瞬间出现设置的模板的情况。实在很影响美观,可以使用vue现成的指令来解决这个问题:v-cloak

在微信小程序中渲染html内容的实现

大部分Web应用的富文本内容都是以HTML字符串的形式存储的,通过HTML文档去展示HTML内容自然没有问题。但是,在微信小程序(下文简称为「小程序」)中,应当如何渲染这部分内容呢?

原来 CSS 与 JS 是这样阻塞 DOM 解析和渲染的

估计大家都听过,尽量将 CSS 放头部,JS 放底部,这样可以提高页面的性能。然而,为什么呢?大家有考虑过么?很长一段时间,我都是知其然而不知其所以然,强行背下来应付考核当然可以,但实际应用中必然一塌糊涂

Vue渲染数据理解以及Vue指令

原生JS改变页面数据,必须要获取页面节点,也即是进行DOM操作,jQuery之类的框架只是简化DOM操作的写法,实质并没有改变操作页面数据的底层原理,DOM操作影响性能(导致浏览器的重绘和回流),Vue是一个mvvm框架(库),大幅度减少了DOM操作

Web渲染那些事儿

在决定渲染方式时,需要测量和理解真正的瓶颈在哪里。静态渲染或服务器渲染在多数情况都比较适用,尤其是可交互性对JS依赖较低的场景。下面是一张便捷的信息图,显示了服务器到客户端的技术频谱:

vue从后台获取数据赋值给data,如何渲染更细视图

如果从服务端返回的数据量较少,或者只有几个字段,可以用vue的set方法,如果数据量较大,请直接看第二种情况。官网API是这样介绍的:Vue.set(target,key,value)

react 异步加载数据时的渲染问题

当数据需要异步加载时render获取不到数据可能会报一些错误,此时需要在render函数中加一个判断.行到render时,state对象的haveData为false, 所以此时页面展示 loading,当异步获取数据成功时

Vue.js中v-html渲染的dom添加scoped的样式

在vue.js中,要将一段字符串渲染成html,可以使用v-html指令。但是 官方文档 中的v-html部分也提醒了

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!