首頁完成效果展示: 一、開發占點陣圖組件 在沒有數據的時候使用占點陣圖替代 items 的位置。 在 components 目錄里創建 moviesItemPlaceholder.js 二、首頁數據請求 使用 postman 之類的工具可以看到,首頁介面返回的數據欄位大致一樣,數據均在 subject_ ...
首頁完成效果展示:
一、開發占點陣圖組件
在沒有數據的時候使用占點陣圖替代 items 的位置。
在 components 目錄里創建 moviesItemPlaceholder.js
import React, { Component } from 'react';
import { View, StyleSheet } from 'react-native';
import { px } from '../utils/device';
export default class MoviesItemPlaceholder extends Component {
render() {
const arr = [1, 2, 3, 4];
return (
<View style={styles.page}>
{arr.map((index) => (
<View style={styles.placeholder} key={index}>
<View style={styles.img} />
<View style={styles.title} />
<View style={styles.rate} />
</View>
))}
</View>
)
}
}
const styles = StyleSheet.create({
page: {
flexDirection: 'row',
paddingLeft: px(30)
},
placeholder: {
width: px(160),
marginRight: px(16)
},
img: {
width: px(160),
height: px(224),
overflow: 'hidden',
borderRadius: px(8),
backgroundColor: '#f8f8f8'
},
title: {
marginTop: px(20),
backgroundColor: '#f8f8f8',
height: px(30),
width: px(130),
overflow: 'hidden',
borderRadius: px(8)
},
rate: {
marginTop: px(16),
backgroundColor: '#f8f8f8',
height: px(24),
width: px(130),
overflow: 'hidden',
borderRadius: px(8)
}
});
二、首頁數據請求
使用 postman 之類的工具可以看到,首頁介面返回的數據欄位大致一樣,數據均在 subject_collection_items 欄位里,可以瘋轉一個方法量來請求數據。
var items = ['showing', 'hot', 'tv', 'variety', 'book', 'music'];
items.forEach(type => {
this.getList(type);
});
getList = (type) => {
ajax(type, {
start: 0,
count: 9
}).then(value => {
let state = {}
state[type] = value.subject_collection_items;
this.setState(state);
})
}
首頁頁面展示
縱向滑動,使用 ScrollView 組件;橫向滑動,使用 FlatList 組件,FlatList 組件的 ListEmptyComponent 表示沒有數據時顯示的組件,在這裡放置占點陣圖組件;
import React from "react";
import { View, Text, StatusBar, StyleSheet, ScrollView, FlatList, TouchableWithoutFeedback } from "react-native";
import { connect } from 'react-redux';
import ajax from "../utils/ajax";
import Header from '../components/header';
import ItemsHeader from '../components/itemsHeader';
import MoviesItem from '../components/moviesItem';
import MoviesItemPlaceholder from '../components/moviesItemPlaceholder';
import Icon from 'react-native-vector-icons/AntDesign';
import { px } from "../utils/device";
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
showing: [],
hot: [],
tv: [],
variety: [],
book: [],
music: [],
}
var items = ['showing', 'hot', 'tv', 'variety', 'book', 'music'];
items.forEach(type => {
this.getList(type);
});
}
getList = (type) => {
ajax(type, {
start: 0,
count: 9
}).then(value => {
let state = {}
state[type] = value.subject_collection_items;
this.setState(state);
})
}
render() {
const { dispatch, value, navigation } = this.props;
const { showing, hot, tv, variety, book, music } = this.state;
const sections = [
{ title: '影院熱映', data: showing, type: 'showing' },
{ title: '豆瓣熱門', data: hot, type: 'hot' },
{ title: '近期熱門劇集', data: tv, type: 'tv' },
{ title: '近期熱門綜藝節目', data: variety, type: 'variety' },
{ title: '暢銷圖書', data: book, type: 'book' },
{ title: '熱門單曲榜', data: music, type: 'music' }
]
return (
<View style={styles.page}>
<Header showBack={false} title='豆瓣評分' backgroundColor='#00b600' color='#fff' />
<ScrollView>
<View style={styles.search}>
<TouchableWithoutFeedback onPress={() => alert('search')}>
<View style={styles.searchView}>
<Icon name='search1' size={px(30)} color='#ccc' />
<Text style={styles.searchText}>搜索</Text>
</View>
</TouchableWithoutFeedback>
</View>
{sections.map((list, index) => (
<View key={index} style={styles.list}>
<ItemsHeader title={list.title} onPress={() => navigation.push('List', { data: list })} />
<FlatList
horizontal={true}
data={list.data}
keyExtractor={(item, index) => 'item' + index}
ListEmptyComponent={() => <MoviesItemPlaceholder />}
renderItem={({ item, index }) => (
<View style={{ marginRight: index !== showing.length - 1 ? px(16) : px(30), marginLeft: index === 0 ? px(30) : 0 }}>
<MoviesItem data={item} />
</View>
)}
/>
</View>
))}
</ScrollView>
</View>
);
}
}
const select = (store) => {
return {
value: store.num.value,
}
}
export default connect(select)(Home);
const styles = StyleSheet.create({
page: {
flex: 1,
backgroundColor: '#fff'
},
search: {
backgroundColor: '#00b600',
height: px(80),
alignItems: 'center',
justifyContent: 'center'
},
searchView: {
height: px(50),
width: px(710),
borderRadius: px(8),
backgroundColor: '#fff',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center'
},
searchText: {
fontSize: px(26),
color: '#ccc',
marginLeft: px(6)
},
list: {
marginBottom: px(30)
}
});
四、緩存列表數據
當處於弱網環境時,打開應用,可能會顯示很久的占點陣圖,此時我們可以將列表數據緩存至本地,每次進入應用先展示本地緩存的數據,然後請求數據,替換本地數據。
此時,就可以使用 redux 了。
編譯 reducer
為了目錄整清晰點(讓 redux 相關的代碼文件都存儲於 store 目錄下),將 src 目錄下的 reducer 目錄移動到 store 目錄下,併在 reducer 目錄創建 list.js。
const initList = {
showing: [],
hot: [],
tv: [],
variety: [],
book: [],
music: []
}
const setListState = (state = initList, action) => {
switch (action.type) {
case 'showing':
return {
...state,
showing: action.data
}
case 'hot':
return {
...state,
hot: action.data
}
case 'tv':
return {
...state,
tv: action.data
}
case 'variety':
return {
...state,
showing: action.data
}
case 'book':
return {
...state,
book: action.data
}
case 'music':
return {
...state,
music: action.data
}
default:
return state;
}
}
export default setListState;
在 reducer 的 index.js 中導入 setListState;
...
import setListState from './list';
...
export default combineReducers({
...
list: setListState
...
});
修改 store/index.js 的路徑引入
import reducer from './reducer';
編輯 action
將之前src下的 action 目錄刪除,在 store 目錄下創建 action.js。
export function login(data) {
return {
type: 'login',
data
}
}
export function logout(data) {
return {
type: 'logout',
data
}
}
// set 首頁列表數據
export function setShowing(data) {
return {
type: 'showing',
data
}
}
export function setHot(data) {
return {
type: 'hot',
data
}
}
export function setTv(data) {
return {
type: 'tv',
data
}
}
export function setVariety(data) {
return {
type: 'variety',
data
}
}
export function setBook(data) {
return {
type: 'book',
data
}
}
export function setMusic(data) {
return {
type: 'music',
data
}
}
編輯首頁
導入修改 store 的方法:
import { setShowing, setHot, setTv, setVariety, setBook, setMusic } from '../store/action';
頁面獲取 store 存儲的數據:
const select = (store) => {
return {
showing: store.list.showing,
hot: store.list.hot,
tv: store.list.tv,
variety: store.list.variety,
book: store.list.book,
music: store.list.music
}
}
export default connect(select)(Home);
頁面獲取數據時,改變 store 里的數據
由於需要 save 數據,所以前面創建的 getList 和傳入的 items 需要做一些改變:
...
var items = [
{ type: 'showing', save: setShowing },
{ type: 'hot', save: setHot },
{ type: 'tv', save: setTv },
{ type: 'variety', save: setVariety },
{ type: 'book', save: setBook },
{ type: 'music', save: setmusic },
]
items.forEach(item => {
this.getList(item);
});
...
getList = (item) => {
ajax(item.type, {
start: 0,
count: 9
}).then(value => {
this.props.dispatch(item.save(value.subject_collection_items));
})
}
修改 render 里的獲取數據方式:
render(){
const { dispatch, value, navigation, showing, hot, tv, variety, book, music } = this.props;
...
}
至此,首頁算是開發完了。