React Native 初嘗試之 CNode 社區客戶端開發

前言

最近踏上了學習使用 React Native 進行客戶端開發的征途,由於以前的技術棧一直是 Vue, 在大體看了一下React Native 的相關介紹後,感受有必要首先學習一下ReactJS。再看過相關文檔後,以 CNode 社區的 API 上手體驗了一下 React 的組件化開發方式,見 cnode-react-App。以後在邊看文檔邊 Google 的過程當中,完成了人生中第一次客戶端開發。下文中將給出以 CNode 社區爲原型進行React Native 開發過程當中遇到的問題以及相關思考。javascript

踩坑之路

實踐出真知,雖然官方文檔已經給出了詳細的API以及教程,沒有刻骨銘心的踩坑之旅,對於一些問題的理解可能也並不那麼透徹。html

Github 開源地址

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

App 預覽

如下是 App 的部分截圖:vue

已完成功能

目前在現有 CNode Api 的支持下,已經完成如下功能:java

  • 分類的文章顯示
  • 文章詳情以及文章對應的評論展現,評論包括精彩評論和評論
  • 用戶的收藏列表、消息列表頁面
  • 設置、關於、github登陸頁面(部分頁面僅提供了導航佔位,後期逐步完善)
  • App 內部鏈接跳轉至webview進行訪問,點擊更多能夠刷新、跳轉至瀏覽器訪問
  • 搜索功能,鑑於目前未提供搜索的接口,目前實現爲前端按照檢索詞進行搜索
  • 點擊用戶頭像,跳轉到用戶信息詳情頁,展現該用戶的最近發佈以及最近回覆
  • 部分操做的權限控制,好比點贊、收藏、收藏列表、信息列表
  • 掃碼登陸流程
  • 登陸後的我的信息展現以及退出功能

還沒有完成以及待優化功能

  • IOS 下的調試,目前僅僅測試了在 Android 下的表現
  • 回覆、發帖功能
  • 添加代碼區域的友好展現
  • 導航的跳轉,好比點贊或者收藏時,未登陸狀態下用戶須要跳轉至登陸頁面,登陸完成後應定位至點贊、收藏
  • 添加 App 啓動頁面
  • 用戶詳情頁的動畫存在必定問題
  • 異步接口請求的相關控制,組件銷燬後,abort相關未完成的請求

技術棧

在開發過程當中,用到了社區內較爲優秀的一些開源貢獻者提供的工具或者包,以下:node

導航的實現 react-navigationreact

react-navigation 是 FaceBook 官方推薦使用的導航組件庫,據稱有着原生般的性能體驗效果。使用起來也確實方便,在筆者進行開發的這段時間,react-navigation 的官方文檔也進行了更新。官方文檔還算詳細,還有其餘不少功能等待發掘。git

圖標 react-native-vector-iconsgithub

第三方的圖標庫,使用起來比較方便,項目中使用了 Ionicons 的風格。web

全局狀態管理 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,給廣大開發者提供了學習練手的機會。

相關文章
相關標籤/搜索