首发于公众号 前端混合开发,欢迎关注。

假设你想使用React Native将你的网站或Web应用程序转换为移动应用程序,或者你有静态HTML代码要在应用程序的特定页面上显示。你会怎么做?你会重写一大堆代码吗?

当然不需要这样做。你可以直接在React Native中渲染HTML。因此,在本文中,我们将学习如何使用 react-native-render-html 库将HTML渲染到React Native中。

设置我们的React Native项目

要开始这个教程,我们需要设置一个React Native项目。我们将通过运行以下命令来实现:

npx react-native init MyTestApp

现在让我们继续前进。创建项目后,我们将运行一次,使用以下任一命令检查一切是否按预期工作:

npm run android 
//or 
npm run ios

该应用将根据您选择的配置进行构建并开始运行,无论您是使用虚拟设备还是Android或iOS设备。

你可以修改 App.js 文件,以在你的主页上看到变化 —— 这是你应用程序的入口页面。我修改了几行代码,以检查它是否运行正常。如果一切顺利,你可以看到一个像下面显示的主页:

image.png

使用 react-native-render-html 将HTML渲染到React Native中

在这个教程中,我们将使用 react-native-render-html 包在我们的React Native应用程序中渲染HTML。保留一些样本HTML代码,以便稍后在React Native应用程序中使用。

react-native-render-html 库是一个拥有超过三千个GitHub星标和46位贡献者的开源组件。它可以将你的HTML渲染为iOS或Android应用中的100%原生视图。

这个库支持我们在开发网络应用时通常使用的所有文本CSS方法。除了文本,它还支持图像、锚标签和列表。

如何将HTML解析为React Native

react-native-render-html 文档使用以下数据流图来演示这个工具如何将HTML解析为React Native:

image.png

总的来说,首先,我们传递的HTML标记将被解析成DOM。然后,基于输入组装瞬时渲染树(Transient Render Tree)。之后,TTree被渲染成虚拟DOM。

将样式应用于元素

对于样式设置,你可以使用内联样式,像这样:

<p style= "color: purple; font-size: 2rem;">

还有另一种处理样式的方式,即使用 mixedStyle 记录。本质上, mixedStyle 是一个包含所有CSS的对象;样式将从那里应用。请参见下面的示例:

//JavaScript
const mixedStyle = {
  body: {
    whiteSpace: 'normal',
    color: '#aaa'
  },
  p: {
    color: '#fff'
  }
}

要在HTML渲染到React Native时使用你的自定义样式, react-native-render-html 库支持 tagsStyles 属性。你可以在该属性中传递你声明的样式,如下所示:

//JavaScript
<RenderHtml
  source={source}
  tagsStyles={mixedStyle}
/>

请记住,当在React Native应用程序中渲染HTML和自定义样式时,React Native样式将在构建时被忽略,不会被应用或反映。

使用 react-native-render-html 库,你可以玩转 htmlparser2 生态系统,该系统用于DOM篡改。你可以在任何时间点处理DOM。例如:

import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
import { removeElement, isTag } from 'domutils';

function onElement(element) {
  // Remove the first p from div which has class "parentDiv"
  if (element.attribs['class'] == 'parentDiv') {
    let i = 0;
    for (const p of element.children) {
      if (isTag(p) && i < 1) {
        removeElement(p);
        i++;
      }
    }
  }
}

const source = {
  html: `
    <div class="parentDiv">
      <p>para-1</p>
      <p>para-2</p>
      <p>para-3</p>
    </div>
  `
};

const domVisitors = {
  onElement: onElement
};

export default function App() {
  const { width } = useWindowDimensions();
  return (
    <RenderHtml
      contentWidth={width}
      source={source}
      domVisitors={domVisitors}
    />
  );
}

现在让我们在应用程序中使用外部库来渲染HTML代码。为此,你需要按照下面的方式修改 App.js 文件:

//JavaScript - JSX
import type {Node} from 'react';
import {
  ScrollView,
  Text,
  View,
} from 'react-native';
import RenderHtml from 'react-native-render-html';

const source = {
  html: `
    <header style="max-width: 1200px;
      overflow: hidden;
      box-sizing: border-box;
      margin: 20px auto;
      text-align: center;">
      <nav style="padding: 20px 0 0;
          max-width: 400px;
          margin: 0 auto;">
          <a style="display: inline-block;
            color: #666666;
            text-decoration: none;
            font-size: 14px;
            cursor: pointer;" href="#section1">Section 1</a>
          <a style="display: inline-block;
            color: #666666;
            text-decoration: none;
            font-size: 14px;
            cursor: pointer;" href="#section1" href="#section2">Section 2</a>
      </nav>
    </header>
    <header style="display: none;
      position: fixed;
      width:100%,
      top: 0;
      background: #FFFFFF;
      margin: 0 -15px;
      width: 100%;
      border-bottom: 1px solid #CCCCCC;
      box-sizing: border-box;
      box-shadow: 0px 0px 10px 0 rgba(0, 0, 0, 0.5);
      opacity: 0.9;
      z-index: 100;">
      <div style="max-width: 1200px;
          padding: 15px 30px;
          margin: 0 auto;
          overflow: hidden;
          box-sizing: border-box;">
          <nav style="padding: 5px 0;
            max-width: 400px;
            float: right;
            text-align: right;">
            <a style="display: inline-block;
                color: #666666;
                text-decoration: none;
                font-size: 14px;
                cursor: pointer;" href="#section1">Section 1</a>
            <a style="display: inline-block;
                color: #666666;
                text-decoration: none;
                font-size: 14px;
                cursor: pointer;" href="#section2">Section 2</a>
          </nav>
      </div>
    </header>
    <div style="min-width: 300px;
      margin: 0 auto;
      height: 1000px;
      position: relative;
    ">
      <div style="min-height: 100px;position: relative; background: #ffd6cd; width=100vw;" id="section1">
          <h1 style="text-align: center;
            line-height: 500px;
            color: #666666;
            margin: 0;">Section 1</h1>
      </div>
      <div style="min-height: 100px;position: relative; background: #ddebfd; width=100vw;" id="section2">
          <h1 style="text-align: center;
            line-height: 500px;
            color: #666666;
            margin: 0;">Section 2</h1>
      </div>
    </div>
    </div>
  `
};
const App: () => Node = () => {
  return (
    <ScrollView contentInsetAdjustmentBehavior="automatic">
    <View>
      <Text style={{top:"3%", textAlign:"center"}}>
        Render HTML to React Native demo
      </Text>
      <RenderHtml
        source={source}
      />
    </View>
    </ScrollView>
  );
};
export default App;

从第10行开始,在 source 变量中,我们编写了我们的HTML代码。然后,这段代码由名为 RenderHtml 的方法在第94行渲染。我们必须提供我们的HTML作为源属性,然后包会处理剩下的部分。

为了证明来自外部库的渲染HTML将看起来与使用React Native编写的代码相同,第91行使用了默认的React Native <Text> 方法来显示文本。

默认方法渲染的文本和HTML渲染输出的文本应如下所示:

image.png

探索 react-native-render-html 的替代方案

除了 react-native-render-html 库,还有另一种在React Native应用中渲染web组件的选项——React Native WebView。这种现代的跨平台替代品对于嵌入从整个web应用到简单HTML文件的任何内容都有很好的支持。

在这个库中,你可以找到与上述类似的模式。请查看下面的示例:

//Javascript - JSX
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { WebView } from 'react-native-webview';

// ...
class MyWebComponent extends Component {
  render() {
    return <WebView source={{ uri: 'https://reactnative.dev/' }} />;
  }
}

这个库有许多有用的功能 - 如上传和下载文件,自定义cookies,页面导航等等。查看这个完整的React Native WebView指南,看看它是否符合你的需求。

总结

由于React的流行,React Native需求量大。如果你理解React,那么通过React使用React Native的原生支持来制作移动应用就变得非常简单。

此外,你可能已经准备好了HTML,并希望使用现有的代码制作移动应用,而不是重写代码以适应你的目标平台。使用上述讨论的一种方法,可以将HTML原生渲染到React Native。你无需重新发明轮子,就可以让它在Android或IOS应用中工作。

交流

首发于公众号 大迁世界,欢迎关注。📝 每周一篇实用的前端文章 🛠️ 分享值得关注的开发工具 ❓ 有疑问?我来回答

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。


王大冶
68.1k 声望105k 粉丝