React Native 初尝试之 CNode 社区客户端开发
发布于 7 个月前 作者 monster1935 1418 次浏览 来自 分享

前言

最近踏上了学习使用 React Native 进行客户端开发的征途,因为之前的技术栈一直是 Vue, 在大致看了一下React Native 的相关介绍后,感觉有必要首先学习一下ReactJS。再看过相关文档后,以 CNode 社区的 API 上手体验了一下 React 的组件化开发方式,见 cnode-react-App。之后在边看文档边 Google 的过程中,完成了人生中第一次客户端开发。下文中将给出以 CNode 社区为原型进行React Native 开发过程中遇到的问题以及相关思考。

踩坑之路

实践出真知,虽然官方文档已经给出了详细的API以及教程,没有刻骨铭心的踩坑之旅,对于一些问题的理解可能也并不那么透彻。

Github 开源地址

https://github.com/monster1935/cnode-rn-app

App 预览

以下是 App 的部分截图:

已完成功能

目前在现有 CNode Api 的支持下,已经完成以下功能:

  • 分类的文章显示
  • 文章详情以及文章对应的评论展示,评论包括精彩评论和评论
  • 用户的收藏列表、消息列表页面
  • 设置、关于、github登录页面(部分页面仅提供了导航占位,后期逐步完善)
  • App 内部连接跳转至webview进行访问,点击更多可以刷新、跳转至浏览器访问
  • 搜索功能,鉴于目前未提供搜索的接口,目前实现为前端按照检索词进行搜索
  • 点击用户头像,跳转到用户信息详情页,展示该用户的最近发布以及最近回复
  • 部分操作的权限控制,比如点赞、收藏、收藏列表、信息列表
  • 扫码登录流程
  • 登录后的个人信息展示以及退出功能

尚未完成以及待优化功能

  • IOS 下的调试,目前仅仅测试了在 Android 下的表现
  • 回复、发帖功能
  • 添加代码区域的友好展示
  • 导航的跳转,比如点赞或者收藏时,未登录状态下用户需要跳转至登录页面,登录完成后应定位至点赞、收藏
  • 添加 App 启动页面
  • 用户详情页的动画存在一定问题
  • 异步接口请求的相关控制,组件销毁后,abort相关未完成的请求

技术栈

在开发过程中,用到了社区内较为优秀的一些开源贡献者提供的工具或者包,如下:

导航的实现 react-navigation

react-navigation 是 FaceBook 官方推荐使用的导航组件库,据称有着原生般的性能体验效果。使用起来也确实方便,在笔者进行开发的这段时间,react-navigation 的官方文档也进行了更新。官方文档还算详细,还有其他很多功能等待发掘。

图标 react-native-vector-icons

第三方的图标库,使用起来比较方便,项目中使用了 Ionicons 的风格。

全局状态管理 react-redux & redux

使用了 react-redux 进行全局状态管理,主要涉及到登录后token, 用户信息以及文章列表的存储。相关需要登录才能使用的模块也需要获取到全局状态中的token,进行相应的判断。

html 转 view react-native-htmlview

涉及到 web 端 html 在 React Native 上的复用问题,因为两端在 布局、组件以及样式上的机制差异,html 完全的转换 view 不是很现实,但是在一定范围内实现转换还是可以的。react-native-htmlview 是目前做的较为优秀的,不过在笔者的使用过程中发现了一些问题,最终还是clone了其代码,又在本地修改才解决的,下文会详细解释。

持久化存储 react-native-storage

用于登录的token的持久化存储,每次启动 App 后,如果之前曾经登录不必重复登录。其不仅支持 React Native, 也提供了浏览器端的支持。

ActionSheet, 用于 webview 中的更多弹出面板 react-native-actionsheet

目前 app 中的链接均采用 app 内部的 webview 进行显示,显示的过程中添加了progress 进度条,并添加了刷新以及在浏览器中打开功能。

二维码扫描组件, 基于 react-native-camera 的封装

基于 react-native-camera 封装的二维码扫码组件,思路借鉴了 react-native-qrcode的实现方法。

WebView 中的进度条显示 react-native-progress

一个更加友好的展示,在网页请求的过程中添加了顶部进度条

遇到的问题

1. react-navigation 中使用可滑动的tab view, 滑动不生效

初次使用react-navigation 后,在首页添加了react-native-scrollable-tab-view, 发现滚动根本不起作用,查阅了相关资料,设置 TabNavigator的 swipeEnabled: false 即可。

2. 使用 react-native-htmlview 转换 html 字符串至 react native View 的过程,发现图片显示较小

在使用的过程中发现图片显示异常,查看其 issue,发现有同样的开发者遇到这样的问题。查阅相关资料,React Native Text Inline Image, 这篇文章中解释了为什么内嵌于 Text 中的 Image 在 Android 上显示过小的问题。原因在于 React Native 的内部的处理问题,React Native 在这种情况下直接以 图片的原始尺寸进行显示,并未再该尺寸的基础上乘以 图片的 PixelRatio。作者给出了一种解决办法就是封装一个InlineImage 组件,在传入的尺寸属性上手动乘以 PixelRatio

3. Android 上 Inline Image 通过 Image.getSize() 后无法更新图片大小

一波未平,一波又起。刚弄明白 Inline Image 显示过小的问题,发现还是无法更加优雅的设置图片的尺寸。原始思路是通过 Image.getSize()后更新图片的尺寸。遗憾的是发现,图片不会更新大小,至今未发现原因。(持续跟进)

4. 动手修改 react-native-htmlview,完美解决 Image 显示问题

为了更加优雅的显示文章的图片,阅读了 react-native-htmlview 的源码,发现之所以会出现 Inline Image 的问题,主要原因是因为其 Image 是内嵌于 Text 节点,虽然其暴露了 NodeComponent 的 props, 不传的话默认为 Text。问题出现的原因,在于含有 img 标签的父标签被渲染为了 Text。因此在源码中添加了以下内容:

// 节点 后代中如果含有 img ,则该节点渲染为 View
function _contains(children) {
  for(let i = 0, len = children.length; i < len; i++) {
    if (children[i].type === 'tag' && children[i].name === 'img' || _contains(children[i].children || [])) {
      return true;
    }
  }
  return false;
}
...
// 标签如果是div 或者 含有img标签的父标签均渲染为View
if (node.type === 'tag') {
  if (node.name === 'div' || _contains(node.children)) {
    opts.NodeComponent = View;
  } else {
    opts.NodeComponent = Text;
  }
}

完美解决了 Image 的显示问题。

总结

React Native 的开发如果有 React 的开发经验,上手还是比较快的。主要是熟悉其组件的使用方式以及不同组件之间的区别。目前仅仅实现了一个 Demo 版本,渲染效率以及内存消耗等问题还未优化。后期对React Native 有深入的理解后,会进行相关方面的优化。

最后

技术学习的路上已经使用 CNodejs 的 Api 做过了好几个 demo,包括:

感谢 CNode 社区提供的 Api,给广大开发者提供了学习练手的机会。

4 回复

这两天我也做了一个,不过是用的vue ~From Frank.Cnode

你接口扒的吗

@liwend219 接口是官方提供的API

回到顶部