react native社區項目知識點

前言

原本想的上一個React項目作完,從容過完1月迎接新年,IT行業的快節奏真是不允許有這種想法;公司把3月上線的react native項目,時間週期活生生壓縮到1月底,真是啼笑皆非。這樣只能加加班並且保質保量地完成,仍是在接口各類報錯的前提下利用Mock數據。 言歸正傳,回到react native項目中來javascript

xcode配置篇css

1、iOS APP圖標配置

2、iOS啓動頁配置、各類尺寸封面大小

TabBar配置篇html

1、iPhone X 適配小技巧

  • 應對iphone劉海屏statusbar顏色處理,利用SafeAreaView包裹整個render
<SafeAreaView style={{backgroundColor:'red'}}></SafeAreaView>
複製代碼
  • 上面方法雖然能達到效果,但除了statusbar,整個背景都會被color覆蓋,解決辦法以下。(附上stackoverflow參考連接
<Fragment>
      <SafeAreaView style={{ flex:0, backgroundColor: 'red' }} /> <SafeAreaView style={{ flex:1, backgroundColor: 'gray' }}> <View style={{ flex: 1, backgroundColor: 'white' }} /> </SafeAreaView> </Fragment> 複製代碼

2、createBottomTabNavigator 個性化圖標

一、所須要顯現的效果,中間「檢測」圖標比較難定位

二、代碼
import { createBottomTabNavigator, createAppContainer, createStackNavigator } from 'react-navigation' // 引入依賴
    
    const TabNavigator = createBottomTabNavigator({
      Home: {
        screen: Home,
        navigationOptions:()=>({
          title:'首頁',
          tabBarIcon: ({tintColor,focused}) => (
            focused ?
              <Image source={require('...')} style={style.nav_icon}/> :
              <Image source={require('...')} style={style.nav_icon}/>
          )
        }),
      },
      Community: {
        screen: Community,
        navigationOptions:()=>({
          title:'社區',
          tabBarIcon: ({tintColor,focused}) => (
            focused ?
              <Image source={require('...')} style={style.nav_icon}/> :
              <Image source={require('...')} style={style.nav_icon}/>
          ),
          tabBarOnPress: ({ navigation, defaultHandler }) => {
            /** 觸發器
             * defaultHandler()、navigation.navigate('Community')
             * 兩個方法都能實現相同效果,跳轉至 Community Component
             */
            defaultHandler()
            navigation.state.params.triggerAvatar()
          }
        })
      },
      Detection: {
        screen: Detection,
        navigationOptions:()=>({
          title:'檢測',
          tabBarLabel: ({tintColor,focused}) => (
            focused ?
              <ImageBackground
                resizeMode="cover"
                source={require('...')}
                imageStyle={styles.midIcon_img_wrap}
                style={styles.midIcon_wrap}>
                <Image source={require('...')} style={styles.midIcon}/>
                <Text style={styles.midIcon_word}>檢測</Text>
              </ImageBackground>
              :
              <ImageBackground
                resizeMode="cover"
                source={require('...')}
                imageStyle={styles.midIcon_img_wrap}
                style={styles.midIcon_wrap}>
                <Image source={require('...')} style={styles.midIcon}/>
                <Text style={styles.midIcon_word}>檢測</Text>
              </ImageBackground>
          )
        }),
      },
      Recover: {
        screen: Recover,
        navigationOptions:()=>({
          title:'康復',
          tabBarIcon: ({tintColor,focused}) => (
            focused ?
              <Image source={require('...')} style={style.nav_icon}/> :
              <Image source={require('...')} style={style.nav_icon}/>
          )
        }),
      },
      Me: {
        screen: Me,
        navigationOptions:()=>({
          title:'個人',
          tabBarIcon: ({tintColor,focused}) => (
            focused ?
              <View style={style.nav_icon_wrap}>
                <Image source={require('...')} style={style.nav_icon}/>
                <MsgSpot/>
              </View>
              :
              <View style={style.nav_icon_wrap}>
                <Image source={require('...')} style={style.nav_icon}/>
                <MsgSpot/>
              </View>
          )
        })
      }
    },{
      initialRouteName:'Home', // 路由最開始訪問
      lazy:true,               // 是否懶加載
      tabBarOptions:{
        activeTintColor:'#0168F5',
        style:{
          borderTopWidth:0,
          shadowOpacity: 0.1,
          shadowRadius: 5,
          shadowColor: '#8B8B8B',
          shadowOffset:{ width:0,height:-4 },
          paddingHorizontal:16
        },
        labelStyle:{fontSize:10,position:'relative',top:-2},
        tabStyle:{paddingTop:2}
      }
    })
    
    //StackNavigator
    const App = createStackNavigator({
      TabNavigator: {screen: TabNavigator, navigationOptions: () => ({gesturesEnabled: true,header: null})},
      HomeDetail: {screen: HomeDetail, navigationOptions: () => ({gesturesEnabled: true,header: null})}
    })
    
    console.disableYellowBox = true // 屏蔽warning彈窗
    export default createAppContainer(App)
複製代碼

3、TabNavigator站內消息提示小紅點

思路:這種跨組件間事件操做,能夠利用Redux實現,但官方給出的是最新版本不會默認集成,那麼就本身找方法怎麼簡單怎麼來,首先考慮到的是DeviceEventEmitterjava

import { DeviceEventEmitter } from 'react-native' // 引入
複製代碼
// spot紅點事件註冊
class MsgSpot extends Component<Props> {
  state = { spotShow:false }
  componentDidMount(){  // tabbar首次渲染訂閱事件
    DeviceEventEmitter.addListener('message',param => {
      this.setState({spotShow:param.spotShow})
      console.log(param)
    })
  }
  render() {
    const {spotShow} = this.state
    return (
      <Fragment> {spotShow?<View style={[style.redSpot,style.redSpot_nav]}></View>:null} </Fragment>
    )
  }
}
複製代碼
DeviceEventEmitter.emit('message', {spotShow:true/false}) // 觸發事件
複製代碼

4、TabNavigator點擊觸發事情

// 詳情看上面tabbar
tabBarOnPress: ({ navigation, defaultHandler }) => {
/** 觸發器 * defaultHandler()、navigation.navigate('Community') * 兩個方法都能實現相同效果,跳轉至 Community Component */
defaultHandler()
navigation.state.params.triggerAvatar()
}
複製代碼

5、頁面訂閱事件

componentDidMount(){
    // 訂閱生命週期
    this._listeners = this.props.navigation.addListener('willFocus', ()=>this.xxx())
}
componentWillUnmount(){
    this._listeners.remove() // 移除事件訂閱
}
複製代碼

react-navigation連接參考react

6、導航callback與導航事件註冊

// 跳轉前頁面
startScan = (param) => {}     // 一、註冊回調
navigate('xxx',{ startScan:this.startScan ,callback:()=>{}})

// 跳轉後 xxx 頁面
state.params.startScan(param) // 一、觸發回調
state.params.callback({})     // 二、觸發callback 
複製代碼

滾動事件、佈局篇ios

1、底部按鈕與ScrollView樣式

<SafeAreaView style={{flex:1}}>
    <ScrollView></ScrollView>
    <Text>Button</Text>
</SafeAreaView>
複製代碼

2、FlatList 上拉、下拉實現

import {
  FlatList,
  RefreshControl
} from 'react-native'   // 引入

constructor(props){
super(props)
this.dataListFake = []  // 列表數據
this.page     = 1       // 頁碼
this.state = {
  dataList : [],        // 渲染數據
  refresh : true,
  pullDown: false,
  isLast:   false,
  loading:  false       // 正在加載
}
}
componentDidMount() {
    this._onRefresh()
}
renderItem = ({item}) => { return () }
renderFooter = () => {
// 顯示時機
// 一、剛開始加載、以後,不顯示
// 二、下刷新,消失
// 三、上拉加載,動畫出現
// 加載完,動畫消失;沒有數據,顯示"暫無更多"
const { pullDown, isLast } = this.state
return (
      <View style={[style.footLoad,{paddingBottom:200}]}> {pullDown?<Image source={require('../../assets/loading.gif')} style={style.footImg}/>:null} {isLast?<Text style={style.footWord}>暫無更多~</Text>:null} </View> ) } renderEmpty = () => { return ( <View style={style.renderEmpty}> <Text>暫無數據</Text> </View> ) } // 下拉刷新 _onRefresh = () => { const {loading} = this.state // 是否正在loading if (!loading){ this.page = 1 this.dataListFake = [] this.setState({refresh:true,isLast:false}) this.dataList(dataListCallBack) } function dataListCallBack(){ // Toast.success('刷新成功',800) } } // 上拉加載 _onEndReached = () => { return false // 沒有分頁 const {isLast,loading} = this.state if (!loading){// 是否正在loading if (isLast){ // Toast.sad('暫無更多數據~') }else{ this.page++ this.setState({pullDown:true}) this.dataList(dataListCallBack) } } function dataListCallBack(){ // Toast.message(`第${_this.page}頁`,null,'center') } } // 網絡請求 async dataList(callBack) { try { this.setState({loading:true}) ... let data = { ..., page:this.page, r:10 } let data_string = queryString.stringify(data) let url = ...+'?'+data_string const response = await axios.get(url) setTimeout(()=>{this.setState({loading:false})},800) // complete let code = Number(response.data.code) let info = response.data.info if (code===0){ let dataList = response.data.data this.dataListFake = this.dataListFake.concat(dataList) this.setState({dataList:this.dataListFake}) }else if (code===9000){ // 根據接口狀況而定 setTimeout(()=>{this.setState({isLast:true})},800) }else{ Toast.sad(info) } setTimeout(()=>{ this.setState({ refresh:false, pullDown:false }) // 無論數據請求如何,狀態歸位 },800) console.log(response.data) console.log(this.page) callBack() // 假回調 } catch (error) { this.setState({refresh:false,pullDown:false,loading:false}) Toast.fail('網絡請求異常') } } 複製代碼
render() {
    const { dataList, refresh } = this.state
    return (
      <SafeAreaView style={[style.container,{flex:1}]}>
        <StatusBar barStyle="dark-content"/>
        <FlatList
          contentContainerStyle={styles.introduction}
          data={ dataList }
          renderItem={this.renderItem}
          ListFooterComponent={this.renderFooter}
          ListEmptyComponent={this.renderEmpty}
          keyExtractor={this._keyExtractor}
          onEndReached={ this._onEndReached }
          onEndReachedThreshold={0}
          refreshing={refresh}
          refreshControl={
            <RefreshControl
              refreshing={ refresh }
              colors={['#ff0000', '#00ff00', '#0000ff']}
              progressBackgroundColor={"#ffffff"}
              onRefresh={ this._onRefresh }
            />
          }
        />
      </SafeAreaView>
    )
  }

複製代碼

loading.gif

雜文篇git

1、條形碼掃描 iOS版本

react-native-smart-barcode能夠解決大部分問題,集成時由於propTypes的引入沒有兼容高版本致使報錯,能夠去Barcode.js註釋掉static propTypes github

// 同時利用頁面訂閱,達到每次顯示頁面從新掃描的目的
this._listeners = this.props.navigation.addListener('didFocus', ()=> this._startScan())
複製代碼

2、富文本解析顯示 react-native-htmlview

import HTMLView from 'react-native-htmlview' // 引入
複製代碼
<HTMLView
    value={htmlContent}
    addLineBreaks={false} // 去掉每行之間的空格
    stylesheet={styles}/>
複製代碼
p:{
    color:'#666666',
    fontSize:15,
    fontWeight:'400',
    lineHeight:20,
    paddingHorizontal: 0,
    marginTop:5,
    marginBottom:5
  }
複製代碼

3、swiper滑動應用 react-native-swiper

4、上傳多圖

要注意的是傳多圖時axios須要配置的地方axios

let config = {headers:{'Content-Type':'multipart/form-data'}}
let formData=new FormData()
xxx.forEach((val,key)=>{
  let file = {uri:val.path,type:val.mime,name:val.filename?val.filename:'CAMERA_PHOTO.JPG'}
  formData.append(`img${key}`,file)
})
await axios.post(url,formData,config)
複製代碼

5、調起打電話

Linking.openURL(`tel:110`)
複製代碼

6、react-native-image-crop-picker圖片上傳遇到的iOS原生問題

一、cd /guyu/ios/podfile
二、cocoapods 安裝配置
	sudo gem install cocoapods
	pod setup
	cd ios
	pod init
# 三、配置下面文件
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
# 添加至pod文件裏面的配置
target 'guyu' do
    pod 'RSKImageCropper'
    pod 'QBImagePickerController'
end
複製代碼

7、axios處理GET時,URL拼接 query-string

query-string更方便拼接url進行Get請求,也方便從url裏面解析出鍵值對來react-native

NPM庫

  1. teaset yarn add teaset
  2. react-native-actionsheet yarn add react-native-actionsheet
  3. react-native-fit-image yarn add react-native-fit-image
相關文章
相關標籤/搜索