🤔🌐 面向 Web 开发者的 React Native
问题
React Native 的学习曲线
问题 002
解决方案
更智能的布局
入门
最后的想法
👋 感谢阅读
在 Web 开发的世界里,一切都是精简的。React Native 的概念对 React 开发者来说确实很有吸引力,但放弃现有的 HTML 和 CSS 知识,转而使用 View、Image、Text 等原生元素,可能会很费劲。但如果不需要,情况会怎样?如果你真的能够利用现有的网站构建知识来构建原生应用,那会怎样?
TL;DR: 你现在可以
问题
本文假设您了解 React Native 可用于创建 iOS、Android 和 Web 应用。如果您不看这篇文章!
React Native 非常棒……对于原生开发者来说(以及整个人类😁)。无需使用 Objective-C 或 Java,你只需使用以下代码即可构建跨平台原生应用:
JavaScriptTypeScript!即使考虑到谷歌和苹果各自原创的 Flutter 和 SwiftUI,React Native 也毫不犹豫地被选中。JavaScript 的灵活性、OTA 更新的便捷性,以及Expo 的整体功能。React Native 拥有这一切。
……除非你是个 Web 开发者。不然它就缺了一些东西。
React Native 的学习曲线
React Native 默认对所有平台一视同仁,这意味着你使用的 API 没有任何特定于平台的引用。链接就是一个很好的例子。
假设我们要创建一个文本链接来打开另一个网站。
在浏览器中,您只需创建一个链接:
<a href="https://dev.to">Link</a>
您可以在本机创建一个通用Text
元素并使用Linking
API 打开 URL:
import { Text, Linking } from 'react-native';
function openLink() {
Linking.openURL('https://dev.to')
}
export default () => (
<Text onPress={openLink}>Link</Text>
)
现在,通过 Expo(iOS、Android 和 Web),您可以执行以下操作:
import { Text, Platform, Linking } from 'react-native';
const Link = ({ href, ...props }) => (
<Text
{...props}
accessibilityRole="link"
href={href}
onPress={() => {
if (Platform.OS !== 'web')
Linking.openURL(href);
}}
/>
);
export default () => (
<Link href="https://dev.to">Link</Link>
)
如果您有 Web 开发背景,这非常不直观。为了简洁起见,我不会详细讨论在 TypeScript 中使用它会有多么麻烦。href
不在 TypeScript 的定义中,<Text />
因为 Web 支持是一个树外解决方案。如果您想添加 TypeScript 支持,您必须重新映射 Text 元素的类型,这需要大量的挖掘才能正确完成。
问题 002
每个前端开发者都会谈论原生应用如何拥有浏览器无法提供的功能。但是,原生应用无法提供网页独有的功能呢?或许,最重要的功能就是 SEO。对于许多网站来说,索引是成功的关键。SEO
在 React Native 中是一个尚未开发且难以实现的领域(除了我写的这篇关于结合使用 Expo 和 Next.js 的文章)。
解决方案
考虑到我刚才列出的问题,解决方案显而易见。React 开发者不需要“React Native”,他们需要的是“原生渲染的 React DOM”。
因此,我创建了一个库来帮助你实现这一点,这个库叫做@expo/html-elements
。
它包含一组(目前新增了40 个)轻量级、通用的组件,这些组件以 HTML 元素命名,可以帮助你轻松进入 React Native 世界,而不会给你的原生项目带来任何额外开销。
@expo/html-elements
还可以帮助您实现:
- 为所有 React Native 用户提供更简便的途径,让他们能够在通用应用中实现常见的 Web 功能。
- 尽可能使用正确的 DOM 元素来优化 SEO。
- 在您的 iOS、Android 和 Web 项目中围绕 A11Y 实现更多自动化。
现在,如果您想建立一个简单的链接,您可以!
import { A } from '@expo/html-elements';
return <A href="#" target="_blank" />
然后,此链接转换为以下符合 A11Y 的链接元素,同时剥离未使用的道具:
平台 | 输出 |
---|---|
网络 | <a dir="auto" href="#" role="link" target="_blank" /> |
本国的 | <Text accessibilityRole="link" onPress={() => Linking.openURL('#')} /> |
拥有一个<a>
元素有几个好处。你可以获得“复制链接地址”功能、悬停预览、iOS 上的预览和弹出功能,以及其他一些用户期望从 Web 上获得的功能。
更智能的布局
使用标题和其他布局元素不会影响你的原生应用,但不使用它们可能会影响你的网页搜索结果。请考虑我的应用中的以下页面:
import { View, Text, Button } from 'react-native';
export default () => (
<>
<Text>My Story</Text>
<View>
<Text>I did a thing with Lego now I code</Text>
</View>
<View>
<Button title="follow me" />
</View>
</>
)
网络爬虫和屏幕阅读器会看到一堆这样的原始数据:
<div>My Story</div>
<div>
<div>I did a thing with Lego now I code</div>
</div>
<div>
<div role="button" />
</div>
如果您使用 HTML 创建一个基本网站(而不是创建应用程序),您可能会使用各种元素来确保屏幕阅读器和爬虫能够以最佳方式工作:
<h1>My Story</h1>
<main role="main">
<p>I did a thing with Lego now I code</p>
</main>
<footer>
<div role="button" />
</footer>
这让爬虫能够获取我们页面的大量信息,但如何在不损害原生应用的情况下获取这些信息呢?说实话,这确实相当困难,需要对 React Native Web 有深入的理解才能搞清楚……但现在有了@expo/html-elements
(!!),你只需:
import { H1, Main, P, Footer } from '@expo/html-elements';
import { Button } from 'react-native';
export default () => (
<>
<H1>My Story</H1>
<Main>
<P>I did a thing with Lego now I code</P>
</Main>
<Footer>
<Button title="follow me" />
</Footer>
</>
)
现在我的页面拥有了通用的 A11Y 功能,并且在浏览器中使用了更多正确的 DOM 元素!😎
平台 | 输出 |
---|---|
网络 | <h1>My Story</h1><main role="main"><div>I did a thing with Lego now I code</div></main><footer><div role="button" /></footer> |
本国的 | <Text>My Story</Text><View><Text>I did a thing with Lego now I code</Text></View><View><Button title="follow me" /></View> |
由于文本样式继承的工作方式,我们仍然使用 a
div
来表示 p、b、strong 等,除非该文本是子项,否则它会使用 aspan
。
入门
您可以立即使用小吃开始:https://snack.expo.io/@bacon/blank-elements
- 或者 -
创建一个通用项目并开始在本地使用它:
- 安装 CLI
npm i -g expo-cli
- 创建新项目
expo init my-project
- 安装包
yarn add @expo/html-elements
-
使用以下方式启动项目
expo start
- 按下
w
即可在浏览器中打开 - 按下
i
即可在模拟器中打开 iOS - 按下
a
即可在 Android 模拟器上启动项目
- 按下
-
可选:您也可以将此包与任何 React Native 工具一起使用
- 点燃CLI:
ignite-cli
- 社区 CLI:
@react-native-community/cli
- 点燃CLI:
最后的想法
也许您还没有遇到任何需要解决的问题@expo/html-elements
,或者您认为这些问题可以通过不同的方式解决,我很乐意听到您的反馈。
我想有些人看到这个包可能会以为他们的原生应用只是在 Cordova 这样的 Web 视图中运行。事实绝非如此。你的视图仍然会以原生视图的形式进行最佳渲染。如果你对此有任何误解,请引导他们阅读这篇文章!
👋 感谢阅读
希望这能让你从 Web 开发过渡到 Web + 原生开发更加轻松!如果你喜欢,欢迎关注我的代码库:@expo/html-elements
!