更新:
目前增加了豆瓣電影和[one]一個功能模塊赠潦,具體可參考效果圖,其中[one]一個的api可參考One API分析草冈。
React Native 進(jìn)階請戳:React native 項(xiàng)目進(jìn)階(redux, redux saga, redux logger)
React Native 項(xiàng)目2(One 【一個】客戶端)
趁著中秋假期無事她奥,使用react native做了一個練手項(xiàng)目。首先看下效果圖:
這里重點(diǎn)說一下用到的api和一些第三方庫怎棱。這里貼一下代碼的地址react-native-simple-zhihu.
知乎日報(bào)api
已經(jīng)有大神對知乎日報(bào)的api進(jìn)行了分析哩俭,很詳細(xì)知乎日報(bào)api.
之前練習(xí)android項(xiàng)目的時候也用到了,表示非常感謝拳恋。
lib
這里主要使用了react-native-drawer凡资,react-native-router-flux。
react-native-router-flux
react-native-router-flux是一個界面導(dǎo)航庫诅岩,目前已經(jīng)實(shí)現(xiàn)了redux讳苦,擴(kuò)展很方便,同時使用也非常簡單吩谦。
基本使用步驟:
- 注冊
首先需要在App入口處對每個scene進(jìn)行注冊鸳谜,scene類似于android中的Activity。
<Router>
<Scene key="root">
<Scene key="pageOne" component={PageOne} title="PageOne" initial={true} />
<Scene key="pageTwo" component={PageTwo} title="PageTwo" />
</Scene>
</Router>
其中key是required式廷,key是scene的唯一標(biāo)識咐扭,在進(jìn)行界面跳轉(zhuǎn)時使用Action.key即可完成跳轉(zhuǎn)。一般來說component也是必須設(shè)置的,是跳轉(zhuǎn)后的界面渲染蝗肪。
當(dāng)scene設(shè)置initial={true}時袜爪,為app的第一個界面
- 界面操作
- 跳轉(zhuǎn)
Actions.Scene_Key(params)
在界面跳轉(zhuǎn)時,可以傳遞一些參數(shù)薛闪,類似于Android中的intent辛馆。
- 退出
Actions.pop()
或者直接按返回鍵,這里返回鍵是被監(jiān)聽到的豁延。
- 強(qiáng)制重現(xiàn)渲染
Action.refresh(params)
react-native-drawer
這是使用react實(shí)現(xiàn)的抽屜式菜單昙篙,與android中的抽屜式菜單很類似。
部分屬性說明
captureGestures true時可以截獲手勢操作
acceptDoubleTab true 雙擊打開或關(guān)閉drawer
acceptTab true 打擊打開或者關(guān)閉drawer诱咏,響應(yīng)區(qū)域受到panOpenMask, panCloseMask限制
negotiaPan true 只接受橫向手勢操作苔可,配合scrollview使用
panthreshold 打開drawer必須滑動的寬度比例
panOpenMask 打開drawer的可操作區(qū)域 從左向右計(jì)算比例
panCloseMask 關(guān)閉drawer的可操作區(qū)域,從右向左計(jì)算比例
initializationOpen 定義初始化時打開還是關(guān)閉
side drawer的位置:left or right
以下是文檔中的示例:
import Drawer from 'react-native-drawer'
class Application extends Component {
closeControlPanel = () = >{
this._drawer.close()
};
openControlPanel = () = >{
this._drawer.open()
};
render() {
return ( < Drawer ref = { (ref) = >this._drawer = ref
}
content = { < ControlPanel / >
} > <MainView / ></Drawer>
)
}
})
項(xiàng)目實(shí)戰(zhàn)
- scene注冊
render() {
return (
<Router>
<Scene key="tabbar" component={Drawer}>
<Scene
key="main"
tabs
tabBarStyle={styles.tabBarStyle}
tabBarSelectedItemStyle={styles.tabBarSelectedItemStyle}>
<Scene key="ZhiHuPage" component={ZhiHuPage} title="知乎日報(bào)" initial icon={TabIcon}/>
<Scene key='StoryDetail' component={StoryDetailPage} hideNavBar={false}
navigationBarStyle={styles.playerTab}/>
</Scene>
</Scene>
</Router>
)
}
- 抽屜式菜單
return (
<Drawer
ref="navigation"
type="displace"
onOpen={() => Actions.refresh({ key: state.key, open: true })}
onClose={() => Actions.refresh({ key: state.key, open: false })}
content={<TabView />}
tapToClose
openDrawerOffset={0.2}
panCloseMask={0.2}
negotiatePan
tweenHandler={(ratio) => ({
main: { opacity: Math.max(0.54, 1 - ratio) },
})}
>
<DefaultRenderer navigationState={children[0]} onNavigate={this.props.onNavigate} />
</Drawer>
);
- 數(shù)據(jù)列表頁
數(shù)據(jù)列表頁使用ListView來展示日報(bào)的簡明數(shù)據(jù)
<View style={{flex: 1}}>
<ListView
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this.fetchDaily.bind(this)}
/>
}
style={styles.listview}
dataSource={this.state.dataSource}
renderRow={(rowData, sectionID, rowID)=>
<StoryCell
story={rowData}
/>
}
/>
</View>
在Storycell中定義每個cell的界面袋狞。
- 數(shù)據(jù)請求
使用fetch進(jìn)行數(shù)據(jù)請求
fetchDaily() {
this.state.date = STORE.date;
var url = "http://news.at.zhihu.com/api/4/news/before/" + STORE.date;
fetch(url)
.then((response)=>response.json())
.then((jsonResponse) => {
if (jsonResponse["stories"]) {
var stories = jsonResponse["stories"];
this.setState({
db: stories,
dataSource: this.state.dataSource.cloneWithRows(stories),
loaded: true,
})
}
}).catch((error) => {
if (error instanceof SyntaxError) {
this.setState({
db: [],
loaded: true,
});
}
})
}
- 詳情頁展示
這里需要注意的是焚辅,日報(bào)api返回的是json數(shù)據(jù),給出了相應(yīng)的圖片地址苟鸯,html格式的data同蜻,share-url等數(shù)據(jù),我們這里直接使用Webview加載起share-url指向的地址倔毙。
- 獲取json數(shù)據(jù)
fetchDaily() {
var url = "http://news-at.zhihu.com/api/4/news/" + this.props.id;
fetch(url)
.then((response)=>response.json())
.then((jsonResponse) => {
if (jsonResponse["share_url"]) {
var shareUrl = jsonResponse["share_url"];
this.setState({
detailUrl: shareUrl
})
}
}).catch((error) => {
if (error instanceof SyntaxError) {
this.setState({});
}
})
}
- Webview渲染
render() {
return (
<View style={{flex: 1}}>
<WebView style={styles.webview_style}
url={this.state.detailUrl}
startInLoadingState={true}
domStorageEnabled={true}
javaScriptEnabled={true}
>
</WebView>
</View>
)
}
源碼地址
react-native-zhihu
https://github.com/wutongke/react-native-zhihu
推薦閱讀:
React-native項(xiàng)目入門與思考
React native 項(xiàng)目入門(知乎日報(bào)埃仪,豆瓣電影,[one]一個)
React native 項(xiàng)目進(jìn)階(redux, redux saga, redux logger)
React Native 項(xiàng)目2(One 【一個】客戶端)