1. 程式人生 > >react native 實現ListView的區域性更新

react native 實現ListView的區域性更新

在ReactNative中UI的重新整理大多數情況依賴於state的變更,通過呼叫元件的setState方法來更新state以達到通知元件重新渲染UI的目的。當然這種做法是官方提供的標準解決方案,在進行簡單UI設計時足以滿足大多數需求。
但是當遇到結構複雜並存在資料互動的介面設計時,手動管理state這種做法則會把程式碼邏輯變得非常混亂,元件內不但要負責UI的渲染,還要兼顧state的變更以及不同元件間資料的傳遞和同步。當專案遇到這種時,引入一個狀態管理框架則顯得尤為重要。
本篇則著重以一個List的資料展示及更新的例子來展開,記錄如何在ReactNative中使用MobX框架來代替手動管理state更新Ui,以及如何實現最小粒度的介面渲染。
下面兩圖分別是不做任何處理的全域性更新列表資料和使用MobX

框架區域性更新列表資料的執行效果,可以看到在使用MobX框架在更新行資料時只會重新渲染當前行的元件,而全域性更新則會將ListView中的所有ItemView全部渲染一次,同時在實際操作中也會感到細微的卡頓。
image image

介紹

MobX是一個經久考驗的庫,使得狀態管理簡單而且透明、可伸縮的應用功能反應性程式設計(TFRP)。MobX背後的哲學很簡單:

任何可以由應用程式狀態,應該是自動派生的。

包括使用者介面、資料序列化、伺服器通訊,等等

image

React和MobX在一起是一個強大的組合,React呈現應用程式狀態通過提供機制,把它翻譯成可渲染的樹元件,React使用MobX提供的機制來儲存和更新應用程式。

React和MobX提供非常優和獨特的在應用程式開發中常見問題的解決方案。React提供了機制優化渲染UI使用虛擬DOM,減少高代價的DOM突變的數量。MobX提供機制優化同步應用程式狀態和React元件通過使用活性虛擬依賴狀態圖,只有當嚴格需要更新,永遠不會過期。

核心概念

  1. Observable state
    可用於訂閱的狀態
  2. Computed values
    可用於訂閱的計算結果
  3. Reactions
    觸發事件並通知訂閱者
  4. Actions
    用於粒度更新state

在ReactNative中配置環境

安裝依賴

12 npm install mobx --savenpm install mobx-react --save


1 npm i mob mobx-react --save

安裝babel外掛,以支援ES7的decorator特性

1 npm i babel-plugin-transform-decorators-legacy babel-preset-react-native-stage-0 --save-dev

建立或編輯babel配置檔案
.babelrc:

1234 { 'presets': ['react-native'], 'plugins': ['transform-decorators-legacy']}

在ReactNative中使用

下面以一個代辦事件的列表為例,來展示如何使用MobX

12 import {observable, computed, action} from 'mobx'import {observer} from 'mobx-react/native'

使用訂閱物件代替state

12345678910111213 //待辦事項行資料class TodoListItem { @observable title; @observable finished = false; @action toggleFinish() { this.finished = !this.finished; }}

@observable是一個裝飾器(Decorator),標註了@observable的類屬性將作為一個可訂閱的欄位存在,任何修該欄位的行為都會發送一個事件給所有訂閱了這個欄位的訂閱者。
@action裝飾器會把裝飾的方法作為一個原子性操作,在方法完成後才會將最終執行結果與所關聯的訂閱欄位進行比較,然後針對發生變更的訂閱欄位進行事件推送。

12345678910 //待辦事項列表資料class TodoListHolder { @observable dataList = []; @computed get taskLeft() { return this.dataList.filter((it) => !it.finished).length }}

@computed標記的get方法會把方法的返回值作為訂閱物件,方法中使用到的@observable欄位變更時都會造成此方法被重新執行,但是隻有在方法返回值變更時,才會對訂閱此方法的訂閱者進行通知。

將元件作為訂閱者來進行註冊,並繫結訂閱物件的屬性來渲染UI

接下來定義三個元件,分別代表父容器,列表元件,和數量統計元件

TodoList.js

12345678910111213141516171819 class TodoList extends Component { todoList = new TodoListHolder(); constructor(props) { super(props); for (let i = 1; i < 30; i++) { let listItem = new TodoListItem(); listItem.title = `待辦事項${i}`; this.todoList.dataList.push(listItem) } } render() { return <View {...this.props}> <TodoListView todoListHolder={this.todoList}/> <TodoSumView todoListHolder={this.todoList}/> </View> }}

建立一個TodoListHolder物件作為元件的成員變數用於資料的訂閱,初始化一些測試資料,並將可訂閱的資料物件傳入列表元件和統計元件

TodoListView.js

1234567891011121314151617181920 //列表展示元件@observerclass TodoListView extends Component { ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => { return r1 !== r2 } }); render() { return <ListView style={{flex:1}} enableEmptySections={true} dataSource={this.ds.cloneWithRows(this.props.todoListHolder.dataList.slice())} renderRow={this.renderRow} /> } renderRow = (rowData) => { return <TodoListItemView rowData={rowData}/> }}
123456789101112131415 //列表行元件@observerclass TodoListItemView extends Component { renderCount = 0; render() { this.renderCount++; return <TouchableOpacity style={{height:50,flexDirection:'row'}} onPress={()=>this.props.rowData.toggleFinish()}> <Text style={{flex: 1}}> {this.props.rowData.title} {this.props.rowData.finished && '√'}</Text> <Text> {this.renderCount}次渲染</Text> </TouchableOpacity> }}export default TodoListView

使用@observer來標註列表元件可以接收訂閱通知,並在render方法中使用訂閱物件的資料。
同樣ListView的ItemVie也使用@observer來進行標註,並在render方法中使用訂閱物件的資料渲染UI。
在UI的觸發事件回撥函式中呼叫訂閱物件的@action方法來變更訂閱物件的資料,之後MobX框架則會根據變更的資料來通知使用了這些資料的observer元件重新呼叫render方法來更新UI

TodoSumView.js

1234567891011 //統計元件@observerclass TodoSumView extends Component { render() { return <View style={{height:30,backgroundColor:'#e4d3ff'}}>

相關推薦

react native 實現ListView區域性更新

在ReactNative中UI的重新整理大多數情況依賴於state的變更,通過呼叫元件的setState方法來更新state以達到通知元件重新渲染UI的目的。當然這種做法是官方提供的標準解決方案,在進行簡單UI設計時足以滿足大多數需求。 但是當遇到結構複雜並存在資料互動的介面設計時,手動管理state這種

React NativeListView實現九宮格效果

概述在安卓原生開發中,ListView是很常用的一個列表控制元件,那麼React Native(RN)如何實現該功能呢?我們來看一下ListView的原始碼ListView是基於ScrollView擴充套件得來的,所以具有ScrollView的相關屬性:dataSource:

React Native 實現熱部署、差異化增量熱更新

React Native 微信公眾號,歡迎微信掃描關注訂閱號,每天定期會分享react native 技術文章,移動技術乾貨,精彩文章技術推送。同時可以掃描我的微信加入react-native技術交流微信群。歡迎各位大牛,React Native技術愛好者加入交流!

react-native-page-listview使用方法(自定義FlatList/ListView下拉重新整理,上拉載入更多,方便的實現分頁)

react-native-page-listview 對ListView/FlatList的封裝,可以很方便的分頁載入網路資料,還支援自定義下拉重新整理View和上拉載入更多的View.相容高版本FlatList和低版本ListVIew.元件會根據你使用的re

react native 實現動態高度Listview 和圖文混排

當考慮這個動態高度和圖文混排的問題,想必你已經知道如何載入ListView和分組listview,這裡不再贅述... 這裡簡介實現的動態的高度的cell的思路 寫一個ListView,準好資料來源在renderRow中渲染自定義的item在item 中佈局text 和ima

react-native setState無法保持更新

ive native 我們 index () tst stat ons ole 常用的數據更新賦值在this.state.xxx= xxx 如果保持數據更新放置與 this.setState({ xxx:xxx }) 有時我們需要setState之後立馬要用state更新的

react-native-page-listview使用方法

自適應 分頁顯示 ... sep 展示 index list 技術分享 沒有 react-native-page-listview 對ListView/FlatList的封裝,可以很方便的分頁加載網絡數據,還支持自定義下拉刷新View和上拉加載更多的View.兼容高版本Fl

react nativeListview從列表頁跳到詳情頁

只寫了下功能,樣式沒有寫,大神勿笑。一些需要改進 的地方請大神指點。qq:274501366 話不多說直接上程式碼 index.android.js 'use strict'; import React, {Component} from 'react'; import { A

react nativelistview加下拉重新整理上拉分頁

直接上程式碼 var REQUEST_URL = 'xxxx&page='; import React, { Component } from 'react'; import { AppRegistry, Image, StyleSheet, Text, Vie

基於React Native實現的介面載入元件react-native-loadview

react-native-loadview 基於React Native實現的介面載入元件, Installation npm install react-native-loadview --save Import into your project import

React Native實現再按一次退出應用程式功能

解決點選兩次手機back鍵退出程式 程式碼及註釋如下: //雙擊返回鍵退出程式

react-native實現多張圖片上傳

最近在搞這個圖片上傳功能,,剛開始的時候iOS用的是 react-native-image-crop-picker這個外掛,,iOS那邊完美執行沒有毛病,,,但是到android這邊之後就開始報各種資源

React-Native實現熱門標籤功能

廢話少說,先上效果圖 Android原生有很多,react-native寫的,貌似沒有。貼程式碼: import React, {Component} from 'react'; import { StyleSheet, Text, View, Toucha

react-native 實現漸變色背景

1、需要藉助外掛react-native-linear-gradient外掛    安裝:        yarn add react-native-linear-gradient        react-native link react-native-linear-gr

react-native實現新建頁面+路由跳轉

步驟: 1.新建一個新頁面,即自己所需要的檔案(拜訪新訊息) 配置: static navigationOptions = ({ navigation, navigationOptions }) => { const { params } = navigation.stat

React Native中整合熱更新

最近,在專案DYTT集成了熱更新,簡單來說,就是不用重新下載安裝包即可達到更新應用的目的,也不算教程吧,這裡記錄一下。 1.熱更新方案 目前網上大概有兩個比較廣泛的方式,分別是 react-native-pushy react-native-code-push

react native搭建私有熱更新伺服器

公司要求要有自己的私有熱更新伺服器,本人表示不擅長後臺,只好去網上找相關的文章,與技術部落格: 本文簡歷在已經成功執行 微軟 codepush熱更新,並且瞭解codepush 相關指令的基礎上。 簡介 code-push-server是一個開源專案,基於 nodej

React-Native實現登入頁面,並顯示和清除使用者的輸入

/** * Sample React Native App * https://github.com/facebook/react-native * ES6實現程式碼 */ import Re

一起學react native實現簡單購物車

前言 實現比較簡單的購物車例項http://www.jianshu.com/p/c581c48a601f 這裡寫圖片描述 程式碼 程式碼結構 這裡寫圖片描述 紅色部分儲存了listitem的資料跟檢視 黃色部分是對於其的引用 主體實現部分 這裡

react native實現可展開Text控制元件

原理:元件初始化時不設定Text控制元件的numberOfLines屬性,測量一下元件高度(最大高度),然後在設定numberOfLines屬性,再次測量一下元件高度(最小高度),若最大高度大與最小高度,表示需要顯示“展開”。/* eslint new-cap: ["err