本篇資源:連接: https://pan.baidu.com/s/1pKActHh 密碼: n6eephp
源碼託管到 github 上,須要源碼的 點我下載,喜歡的話記得 Star,謝謝!node
數據持久化是移動端的一個重要部分,剛發現 Realm
原來已經支持 React-Native
了,那麼這邊另起一篇專門介紹兩種經常使用的存儲方式 ———— React-Native 之 數據持久化react
這邊沒有發現 官方
有將 商品數據
作本地緩存的功能,爲了讓你們知道怎麼作,咱們就簡單地來實驗一下,具體邏輯在每一個產品中都或多或少有些差別,這個朋友們就根據所學的靈活變通一下就能夠了!ios
首先,在爲了方便使用,也爲了減小第三方框架對工程的 「污染」,咱們須要對框架進行一次 基礎
的封裝。git
var RealmBase = {}; import Realm from 'realm'; const HomeSchame = { name:'HomeData', properties:{ id:'int', title:'string', image:'string', mall:'string', pubtime:'string', fromsite:'string', } }; const HTSchame = { name:'HTData', properties:{ id:'int', title:'string', image:'string', mall:'string', pubtime:'string', fromsite:'string', } }; // 初始化realm let realm = new Realm({schema:[HomeSchame, HTSchame]}); // 增長 RealmBase.create = function (schame, data) { realm.write(() => { for (let i = 0; i<data.length; i++) { let temp = data[i]; realm.create(schame, {id:temp.id, title:temp.title, image:temp.image, mall:temp.mall, pubtime:temp.pubtime, fromsite:temp.fromsite}); } }) } // 查詢所有數據 RealmBase.loadAll = function (schame) { return realm.objects(schame); } // 條件查詢 RealmBase.filtered = function (schame, filtered) { // 獲取對象 let objects = realm.objects(schame); // 篩選 let object = objects.filtered(filtered); if (object) { // 有對象 return object; }else { return '未找到數據'; } } // 刪除全部數據 RealmBase.removeAllData = function (schame) { realm.write(() => { // 獲取對象 let objects = realm.objects(schame); // 刪除表 realm.delete(objects); }) } global.RealmBase = RealmBase;
通過簡單封裝後,咱們還須要引用一下框架,引用框架,咱們就放到 main
文件內,這樣咱們就能夠確保 全局變量
是在咱們使用它以前就被調用過,避免找不到對象的錯誤(咱們也同時將 HTTPBase
修改成全局,方便使用)。github
import RealmStorage from '../storage/realmStorage';
如今咱們就來作下 本地持久化
實驗,這邊咱們的邏輯就是,當網絡出現問題的時候,每次都會進到 catch 中返回錯誤 code 告訴咱們,出現了什麼問題(既然進到這裏了,是否是數據不管如何都不會加載成功?),那麼咱們就能夠在這裏 取出
本地數據,而後展現出來,那麼數據的應該在哪裏保存呢?這個咱們只須要在每次 刷新
完成而且渲染完成後,保存一下數據就能夠了。npm
// 加載最新數據網絡請求 loadData(resolve) { let params = {"count" : 10 }; HTTPBase.get('https://guangdiu.com/api/getlist.php', params) .then((responseData) => { // 清空數組 this.data = []; // 拼接數據 this.data = this.data.concat(responseData.data); // 從新渲染 this.setState({ dataSource: this.state.dataSource.cloneWithRows(this.data), loaded:true, }); // 關閉刷新動畫 if (resolve !== undefined){ setTimeout(() => { resolve(); }, 1000); } // 存儲數組中最後一個元素的id let cnlastID = responseData.data[responseData.data.length - 1].id; AsyncStorage.setItem('cnlastID', cnlastID.toString()); // 存儲數組中第一個元素的id let cnfirstID = responseData.data[0].id; AsyncStorage.setItem('cnfirstID', cnfirstID.toString()); // 清楚本地存儲的數據 RealmBase.removeAllData('HomeData'); // 存儲數據到本地 RealmBase.create('HomeData', responseData.data); }) .catch((error) => { // 拿到本地存儲的數據,展現出來,若是沒有存儲,那就顯示無數據頁面 this.data = RealmBase.loadAll('HomeData'); // 從新渲染 this.setState({ dataSource: this.state.dataSource.cloneWithRows(this.data), loaded:true, }); }) }
到這裏,咱們就完成了 數據本地持久化
而且成功將數據取出,這邊數據持久化的實驗就完成了。react-native
譯註:api
有關
realm
的配置,可轉到 React-Native 之 數據持久化 查看,這邊很少贅述。數組當咱們徹底配置完
realm
後,會發現整個工程多出將近500M+
,不用擔憂,這些只不過是realm
的依賴庫,等咱們後面打包
後就不會有這麼多東西了。咱們已經使用了
git
進行對代碼進行託管,那麼,若是從倉庫拉取最新數據時,是否是仍是要從新配置node_modules
文件夾,這個就很麻煩了,咱們能夠備份一下node_modules
文件夾,將它拷貝
進工程就可使用了。
gitignore
文件內包含了須要忽略或保留的文件的一些配置,靈活使用能夠減小咱們的工做量,可是裏面的內容是什麼意思呢?這邊也給你們說下:
知道語法後,咱們是否是就能看懂 工程中 gitignore
文件的內容了,舉個栗子:
# Xcode // 註釋,說明這是 Xcode 配置 # build/ // 忽略 build 文件夾下全部內容 *.pbxuser // 忽略以 .pbxuser 爲後綴的文件 !default.pbxuser // 除 default.pbxuser 文件外 *.mode1v3 // 忽略以 .mode1v3 爲後綴的文件 !default.mode1v3 // 除 default.mode1v3 文件外 # node.js // 註釋,說明這是 node 配置 # node_modules/ // 忽略 node_modules 文件夾內全部內容 npm-debug.log // 忽略 npm-debug.log yarn-error.log // 忽略 yarn-error.log
好了,就介紹到這裏,但願能夠幫到有須要的朋友,須要學習更多關於 git
的內容,能夠到 git介紹與使用 查看學習。
cell
了,爲何不直接在前面自定義的 cell
裏面再添加一些操做,使全部的 cell
共用同一套組件?其實考慮到下面幾點緣由:
能夠看到 半小時熱門的cell
和 三大模塊的cell
區別在於少了 優惠平臺和數據提供平臺
這一欄的2個控件,其餘地方是同樣的,若是咱們作到一塊兒那也是能夠的,可是這樣會形成一個組件裏面擔負過多業務邏輯,在 數據量少
是不要緊,可是 數據量一多
那麼須要渲染的成本就會增長,也就會嚴重影響到性能。
若是咱們分開使用,那麼只是增長了組件,並且組件內部處理的業務邏輯變少了,這樣也減小了咱們後期的維護成本。
從結構上來講,這樣也更爲的清晰,減小開發人員之間的溝通成本。
首先,仍是同樣,咱們先來建立 GDCommunalCell
文件,而且咱們將前面 自定義cell
裏面的內容 copy
一下,放到這個文件中,並進行相應修改:
export default class GDCommunalCell extends Component { static propTypes = { image:PropTypes.string, title:PropTypes.string, mall:PropTypes.string, pubTime:PropTypes.string, fromSite:PropTypes.string, }; renderDate(pubTime, fromSite) { // 時間差的計算 let minute = 1000 * 60; // 1分鐘 let hour = minute * 60; // 1小時 let day = hour * 24; // 1天 let week = day * 7; // 1周 let month = day * 30; // 1個月 // 計算時間差 let now = new Date().getTime(); // 獲取當前時間 let diffValue = now - Date.parse(pubTime.replace(/-/gi, "/")); if (diffValue < 0) return; let monthC = diffValue/month; // 相差了幾個月 let weekC = diffValue/week; // 相差幾周 let dayC = diffValue/day; // 相差幾天 let hourC = diffValue/hour // 相差幾小時 let minuteC = diffValue/minute; // 相差幾分鐘 let result; if (monthC >= 1) { result = parseInt(monthC) + "月前"; }else if (weekC >= 1) { result = parseInt(weekC) + "周前"; }else if (dayC >= 1) { result = parseInt(dayC) + "天前"; }else if (hourC >= 1) { result = parseInt(hourC) + "小時前"; }else if (minuteC >= 1) { result = parseInt(minuteC) + "分鐘前"; }else result = "剛剛"; return result + ' · ' + fromSite; } render() { return ( <View style={styles.container}> {/* 左邊圖片 */} <Image source={{uri:this.props.image === '' ? 'defaullt_thumb_83x83' : this.props.image}} style={styles.imageStyle} /> {/* 中間 */} <View style={styles.centerViewStyle}> {/* 標題 */} <View> <Text numberOfLines={3} style={styles.titleStyle}>{this.props.title}</Text> </View> {/* 詳情 */} <View style={styles.detailViewStyle}> {/* 平臺 */} <Text style={styles.detailMallStyle}>{this.props.mall}</Text> {/* 時間 + 來源 */} <Text style={styles.timeStyle}>{this.renderDate(this.props.pubTime, this.props.fromSite)}</Text> </View> </View> {/* 右邊的箭頭 */} <Image source={{uri:'icon_cell_rightArrow'}} style={styles.arrowStyle} /> </View> ); } } const styles = StyleSheet.create({ container: { flexDirection:'row', alignItems:'center', justifyContent:'space-between', backgroundColor:'white', height:100, width:width, borderBottomWidth:0.5, borderBottomColor:'gray', marginLeft:15 }, imageStyle: { width:70, height:70, }, centerViewStyle: { height:70, justifyContent:'space-around', }, titleStyle: { width:width * 0.65, }, detailViewStyle: { flexDirection:'row', justifyContent:'space-between', alignItems:'center' }, detailMallStyle: { fontSize:12, color:'green', }, timeStyle: { fontSize:12, color:'gray', }, arrowStyle: { width:10, height:10, marginRight:30, } });
OK,這邊完成了,咱們到首頁中試一下是否是好使的。
譯註:
這邊須要注意的是時間的轉化,方式有不少,這邊就以最直接的方式來計算。
還有須要注意的是在
JAVA
中,獲取到的月份是和咱們如今的月份少1個月的
,這是由於JAVA
的月份是從0
開始,Javascript
也是同樣的。
這個模塊和首頁、海淘請求數據方面是相似的,不一樣在於這裏須要咱們根據不一樣的時間段來進行相對應的請求,這邊參考視頻吧,直接上完整代碼。
仍是 copy
首頁或者海淘的代碼,修改請求這部分代碼:
export default class GDHourList extends Component { // 構造 constructor(props) { super(props); // 初始狀態 this.state = { dataSource: new ListView.DataSource({rowHasChanged:(r1, r2) => r1 !== r2}), loaded:false, prompt:'', }; this.nexthourhour = ''; this.nexthourdate = ''; this.lasthourhour = ''; this.lasthourdate = ''; this.loadData = this.loadData.bind(this); } // 加載最新數據網絡請求 loadData(resolve, date, hour) { let params = {}; if (date) { params = { "date" : date, "hour" : hour } } HTTPBase.get('http://guangdiu.com/api/getranklist.php', params) .then((responseData) => { // 從新渲染 this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.data), loaded:true, prompt:responseData.displaydate + responseData.rankhour + '點檔' + '(' + responseData.rankduring + ')' }); // 關閉刷新動畫 if (resolve !== undefined){ setTimeout(() => { resolve(); }, 1000); } // 暫時保留一些數據 this.nexthourhour = responseData.nexthourhour; this.nexthourdate = responseData.nexthourdate; this.lasthourhour = responseData.lasthourhour; this.lasthourdate = responseData.lasthourdate; }) .catch((error) => { }) } // 跳轉到設置 pushToSettings() { this.props.navigator.push({ component:Settings, }) } // 返回中間標題 renderTitleItem() { return( <Image source={{uri:'navtitle_rank_106x20'}} style={styles.navbarTitleItemStyle} /> ); } // 返回右邊按鈕 renderRightItem() { return( <TouchableOpacity onPress={()=>{this.pushToSettings()}} > <Text style={styles.navbarRightItemStyle}>設置</Text> </TouchableOpacity> ); } // 根據網絡狀態決定是否渲染 listview renderListView() { if (this.state.loaded === false) { return( <NoDataView /> ); }else { return( <PullList onPullRelease={(resolve) => this.loadData(resolve)} dataSource={this.state.dataSource} renderRow={this.renderRow.bind(this)} showsHorizontalScrollIndicator={false} style={styles.listViewStyle} initialListSize={5} /> ); } } // 跳轉到詳情頁 pushToDetail(value) { this.props.navigator.push({ component:CommunalDetail, params: { url: 'https://guangdiu.com/api/showdetail.php' + '?' + 'id=' + value } }) } // 返回每一行cell的樣式 renderRow(rowData) { return( <TouchableOpacity onPress={() => this.pushToDetail(rowData.id)} > <CommunalCell image={rowData.image} title={rowData.title} mall={rowData.mall} pubTime={rowData.pubtime} fromSite={rowData.fromsite} /> </TouchableOpacity> ); } componentDidMount() { this.loadData(); } lastHour() { this.loadData(undefined, this.lasthourdate, this.lasthourhour); } nextHour() { this.loadData(undefined, this.nexthourdate, this.nexthourhour); } render() { return ( <View style={styles.container}> {/* 導航欄樣式 */} <CommunalNavBar titleItem = {() => this.renderTitleItem()} rightItem = {() => this.renderRightItem()} /> {/* 提醒欄 */} <View style={styles.promptViewStyle}> <Text>{this.state.prompt}</Text> </View> {/* 根據網絡狀態決定是否渲染 listview */} {this.renderListView()} {/* 操做欄 */} <View style={styles.operationViewStyle}> <TouchableOpacity onPress={() => this.lastHour()} > <Text style={{marginRight:10, fontSize:17, color:'green'}}>{"< " + "上1小時"}</Text> </TouchableOpacity> <TouchableOpacity onPress={() => this.nextHour()} > <Text style={{marginLeft:10, fontSize:17, color:'green'}}>{"下1小時" + " >"}</Text> </TouchableOpacity> </View> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', backgroundColor: 'white', }, navbarTitleItemStyle: { width:106, height:20, marginLeft:50 }, navbarRightItemStyle: { fontSize:17, color:'rgba(123,178,114,1.0)', marginRight:15, }, promptViewStyle: { width:width, height:44, alignItems:'center', justifyContent:'center', backgroundColor:'rgba(251,251,251,1.0)', }, operationViewStyle: { width:width, height:44, flexDirection:'row', justifyContent:'center', alignItems:'center', }, });
從圖中,咱們能夠看出篩選的下拉菜單相似 九宮格
,這個咱們在 React-Native 之 ListView使用 中有這樣的案例,不清楚的能夠再回去看一下,因此這邊咱們也使用 ListView
實現。
在作以前,咱們須要先配置一下,將壓縮包內的 HomeSiftData文件
和 HTSiftData
文件放到工程內。
接着咱們就要來完成這個篩選組件,代碼以下:
export default class GDCommunalSiftMenu extends Component { static defaultProps = { removeModal:{}, loadSiftData:{} }; static propTypes = { data:PropTypes.array, }; // 構造 constructor(props) { super(props); // 初始狀態 this.state = { dataSource: new ListView.DataSource({rowHasChanged:(r1, r2) => r1 !== r2}) }; } // 退出 popToHome(data) { this.props.removeModal(data); } // 點擊事件 siftData(mall, cate) { this.props.loadSiftData(mall, cate); this.popToHome(false); } // 處理數據 loadData() { let data = []; for (let i = 0; i<this.props.data.length; i++) { data.push(this.props.data[i]); } // 從新渲染 this.setState({ dataSource: this.state.dataSource.cloneWithRows(data), }) } renderRow(rowData) { return( <View style={styles.itemViewStyle}> <TouchableOpacity onPress={() => this.siftData(rowData.mall, rowData.cate)} > <View style={styles.itemViewStyle}> <Image source={{uri:rowData.image}} style={styles.itemImageStyle} /> <Text>{rowData.title}</Text> </View> </TouchableOpacity> </View> ) } componentDidMount() { this.loadData(); } render() { return( <TouchableOpacity onPress={() => this.popToHome(false)} activeOpacity={1} > <View style={styles.container}> {/* 菜單內容 */} <ListView dataSource={this.state.dataSource} renderRow={this.renderRow.bind(this)} contentContainerStyle={styles.contentViewStyle} initialListSize={16} /> </View> </TouchableOpacity> ) } } const styles = StyleSheet.create({ container: { width:width, height:height }, contentViewStyle: { flexDirection:'row', flexWrap:'wrap', width: width, top:Platform.OS === 'ios' ? 64 : 44, }, itemViewStyle: { width:width * 0.25, height:70, backgroundColor:'rgba(249,249,249,1.0)', justifyContent:'center', alignItems:'center' }, itemImageStyle: { width:40, height:40 } });
// 加載最新數據網絡請求 loadSiftData(mall, cate) { let params = {}; if (mall === "" && cate === "") { // 所有 this.loadData(undefined); return; } if (mall === "") { // cate 有值 params = { "cate" : cate }; }else { params = { "mall" : mall }; } HTTPBase.get('https://guangdiu.com/api/getlist.php', params) .then((responseData) => { // 清空數組 this.data = []; // 拼接數據 this.data = this.data.concat(responseData.data); // 從新渲染 this.setState({ dataSource: this.state.dataSource.cloneWithRows(this.data), loaded:true, }); // 存儲數組中最後一個元素的id let cnlastID = responseData.data[responseData.data.length - 1].id; AsyncStorage.setItem('cnlastID', cnlastID.toString()); }) .catch((error) => { }) }
海淘模塊
內也使用一下就能夠了。點擊 首頁或者海淘 右側按鈕,咱們跳轉到搜索模塊,解析圖奉上:
根據解析圖咱們添加相應子組件。
export default class GDHome extends Component { // 構造 constructor(props) { super(props); // 初始狀態 this.state = { dataSource: new ListView.DataSource({rowHasChanged:(r1, r2) => r1 !== r2}), loaded:false, isModal:false }; this.data = []; this.changeText = ''; this.loadData = this.loadData.bind(this); this.loadMore = this.loadMore.bind(this); } // 加載最新數據網絡請求 loadData(resolve) { if (!this.changeText) return; let params = { "q" : this.changeText }; HTTPBase.get('http://guangdiu.com/api/getresult.php', params) .then((responseData) => { // 清空數組 this.data = []; // 拼接數據 this.data = this.data.concat(responseData.data); // 從新渲染 this.setState({ dataSource: this.state.dataSource.cloneWithRows(this.data), loaded:true, }); // 關閉刷新動畫 if (resolve !== undefined){ setTimeout(() => { resolve(); }, 1000); } // 存儲數組中最後一個元素的id let searchLastID = responseData.data[responseData.data.length - 1].id; AsyncStorage.setItem('searchLastID', searchLastID.toString()); }) .catch((error) => { }) } // 加載更多數據的網絡請求 loadMoreData(value) { let params = { "q" : this.changeText, "sinceid" : value }; HTTPBase.get('http://guangdiu.com/api/getresult.php', params) .then((responseData) => { // 拼接數據 this.data = this.data.concat(responseData.data); this.setState({ dataSource: this.state.dataSource.cloneWithRows(this.data), loaded:true, }); // 存儲數組中最後一個元素的id let searchLastID = responseData.data[responseData.data.length - 1].id; AsyncStorage.setItem('searchLastID', searchLastID.toString()); }) .catch((error) => { }) } // 加載更多數據操做 loadMore() { // 讀取id AsyncStorage.getItem('searchLastID') .then((value) => { // 數據加載操做 this.loadMoreData(value); }) } // 返回 pop() { // 回收鍵盤 dismissKeyboard(); this.props.navigator.pop(); } // 返回左邊按鈕 renderLeftItem() { return( <TouchableOpacity onPress={() => {this.pop()}} > <View style={{flexDirection:'row', alignItems:'center'}}> <Image source={{uri:'back'}} style={styles.navbarLeftItemStyle} /> <Text>返回</Text> </View> </TouchableOpacity> ); } // 返回中間按鈕 renderTitleItem() { return( <Text style={styles.navbarTitleItemStyle}>搜索全網折扣</Text> ); } // ListView尾部 renderFooter() { return ( <View style={{height: 100}}> <ActivityIndicator /> </View> ); } // 根據網絡狀態決定是否渲染 listview renderListView() { if (this.state.loaded === false) { return( <NoDataView /> ); }else { return( <PullList onPullRelease={(resolve) => this.loadData(resolve)} dataSource={this.state.dataSource} renderRow={this.renderRow.bind(this)} showsHorizontalScrollIndicator={false} style={styles.listViewStyle} initialListSize={5} renderHeader={this.renderHeader} onEndReached={this.loadMore} onEndReachedThreshold={60} renderFooter={this.renderFooter} /> ); } } // 跳轉到詳情頁 pushToDetail(value) { this.props.navigator.push({ component:CommunalDetail, params: { url: 'https://guangdiu.com/api/showdetail.php' + '?' + 'id=' + value } }) } // 返回每一行cell的樣式 renderRow(rowData) { return( <TouchableOpacity onPress={() => this.pushToDetail(rowData.id)} > <CommunalCell image={rowData.image} title={rowData.title} mall={rowData.mall} pubTime={rowData.pubtime} fromSite={rowData.fromsite} /> </TouchableOpacity> ); } render() { return ( <View style={styles.container}> {/* 導航欄樣式 */} <CommunalNavBar leftItem = {() => this.renderLeftItem()} titleItem = {() => this.renderTitleItem()} /> {/* 頂部工具欄 */} <View style={styles.toolsViewStyle} > {/* 左邊 */} <View style={styles.inputViewStyle} > <Image source={{uri:'search_icon_20x20'}} style={styles.searchImageStyle} /> <TextInput style={styles.textInputStyle} keyboardType="default" placeholder="請輸入搜索商品關鍵字" placeholderTextColor='gray' autoFocus={true} clearButtonMode="while-editing" onChangeText={(text) => {this.changeText = text}} onEndEditing={() => this.loadData()} /> </View> {/* 右邊 */} <View style={{marginRight:10}}> <TouchableOpacity onPress={() => this.pop()} > <Text style={{color:'green'}}>取消</Text> </TouchableOpacity> </View> </View> {/* 根據網絡狀態決定是否渲染 listview */} {this.renderListView()} </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', backgroundColor: 'white', }, navbarLeftItemStyle: { width:20, height:20, marginLeft:15, }, navbarTitleItemStyle: { fontSize:17, color:'black', marginRight:50 }, navbarRightItemStyle: { width:20, height:20, marginRight:15, }, toolsViewStyle: { width:width, height:44, flexDirection:'row', alignItems:'center', justifyContent:'space-between', }, inputViewStyle: { height:35, flexDirection:'row', alignItems:'center', justifyContent:'center', backgroundColor:'rgba(239,239,241,1.0)', marginLeft:10, borderRadius:5 }, searchImageStyle: { width:15, height:15, marginLeft:8 }, textInputStyle: { width:width * 0.75, height:35, marginLeft:8 }, listViewStyle: { width:width, }, });
在 小時風雲榜 模塊,咱們還有設置模塊沒有作,這邊也快速來作一下
從圖中能夠看出,這又是不同的 cell樣式 ,不過經過前面的經驗,知道怎麼來自定義了吧:
export default class GDSettingsCell extends Component { static propTypes = { leftTitle:PropTypes.string, isShowSwitch:PropTypes.bool, }; // 構造 constructor(props) { super(props); // 初始狀態 this.state = { isOn:false, }; } // 返回須要的組件 renderRightContent() { let component; if (this.props.isShowSwitch) { // 顯示 Switch 按鈕 component = <Switch value={this.state.isOn} onValueChange={() => {this.setState({isOn: !this.state.isOn})}} /> }else { component = <Image source={{uri:'icon_cell_rightArrow'}} style={styles.arrowStyle} /> } return( component ) } render() { return( <View style={styles.container}> {/* 左邊 */} <View> <Text>{this.props.leftTitle}</Text> </View> {/* 右邊 */} <View style={styles.rightViewStyle}> {this.renderRightContent()} </View> </View> ) } } const styles = StyleSheet.create({ container: { flex:1, flexDirection:'row', height:Platform.OS === 'ios' ? 44 : 36, justifyContent:'space-between', alignItems:'center', borderBottomColor:'gray', borderBottomWidth:0.5, marginLeft:15, }, rightViewStyle:{ marginRight:15, }, arrowStyle: { width:10, height:10, } });
自定義完成,來試下好很差用:
export default class GDSettings extends Component { // 返回 pop() { this.props.navigator.pop(); } // 返回左邊按鈕 renderLeftItem() { return( <TouchableOpacity onPress={() => {this.pop()}} > <View style={{flexDirection:'row', alignItems:'center'}}> <Image source={{uri:'back'}} style={styles.navbarLeftItemStyle} /> <Text>返回</Text> </View> </TouchableOpacity> ); } // 返回中間按鈕 renderTitleItem() { return( <Text style={styles.navbarTitleItemStyle}>設置</Text> ); } render() { return( <View style={styles.container}> {/* 導航欄樣式 */} <CommunalNavBar leftItem = {() => this.renderLeftItem()} titleItem = {() => this.renderTitleItem()} /> {/* 內容 */} <ScrollView style={styles.scollViewStyle} > {/* 第一個cell */} <SettingsCell leftTitle="淘寶天貓快捷下單" isShowSwitch={true} /> {/* 第二個cell */} <SettingsCell leftTitle="清理圖片緩存" isShowSwitch={false} /> </ScrollView> </View> ) } } const styles = StyleSheet.create({ container: { flex:1 }, navbarLeftItemStyle: { width:20, height:20, marginLeft:15, }, navbarTitleItemStyle: { fontSize:17, color:'black', marginRight:50 }, scollViewStyle: { backgroundColor:'white', }, });