RN 经验

每天一点点
RN 经验_第1张图片
1
1. 创建指定版本

react-native init demo --version 0.55.4 指定版本

2. 跨页面传值
  • DeviceEventEmitter事件传值 <类似通知>
// 引入
import {
    ...
     DeviceEventEmitter
 } form 'react-native';
//发送事件的页面
 DeviceEventEmitter.emit('userNameDidChange', '传值');
//需要接收事件的页面 
componentDidMount() {
     this.subscription = DeviceEventEmitter.addListener('userNameDidChange',(userName) =>{
          alert(userName);
     })
}

//页面卸载  移除事件
componentWillUnmount() {
    this.subscription.remove();
}
3. import 导入的几种方式
  1. import Home from './src/Home';
    导入‘src/Home’文件里export的带default关键字的组件,即默认组件

2.import { Home,Me } from './src/Home';
导入‘src/Home’文件里export的叫Home和Me的非默认组件,可以导入多个组件,用逗号隔开即可

3.import * as Home from'./src/Home';
意思是将./src/Home'文件里的所有非默认组件,全部集结成一个Home模型组件,命名可以自定义,然后可以通过点语法,来使用组件里面的所有export的组件, 如 Home.A 、Home.B

4. 调用打电话功能

Linking提供了一个通用的接口来与传入和传出的App链接进行交互,比如跳转外部链接,打电话,发邮件,打开某个浏览器链接等

//导入Linking
import {
  ...
  Linking
} from "react-native";

...
call(){
  let url = 'tel: ' + '电话号码';
  //let url = "mqqwpa://im/chat?chat_type=wpa&uin=QQ号";//调用QQ
  Linking.canOpenURL(url).then(supported => {
      if (!supported) {
        console.log('Can\'t handle url: ' + url);
      } else {
        Linking.openURL(url);
      }
  }).catch(err => console.error('An error occurred', err));
}
5. 复制到剪贴板
//导入Clipboard
import {
  ...
  Clipboard
} from "react-native";

//复制电话号码到剪贴板
    async _setClipboardContent(tel){
        Clipboard.setString(tel);
        try {
            var content = await Clipboard.getString();
            console.log('复制的手机号:');
            this.clearClose();
            console.log(content);
            
        } catch (e) {
            console.log(e.message)
        }
    }

6. react-navigation 隐藏/显示tabBar
const Tab = TabNavigator(
    {
        Home: {
            screen: HomeScreen,
             /*  TabBar是否显示/隐藏    */
             navigationOptions: ({ navigation }) => {
                // console.log('nav state:', navigation.state);
                 const homeRoute = navigation.state.params;
                 return {
                     /**
                      * 控制tabBar是否显示/隐藏 
                      * 在HomeScreen 页面通过 this.props.navigation.setParams({ tabBarVisible: false/true })控制--
                      */
                     tabBarVisible: homeRoute && homeRoute.tabBarVisible, 
                 }
             }
        },
        ....
    },
    {
        ....
    }
7. 获取Navigator的层级
var currentRoute = this.props.navigator.getCurrentRoutes(); 
for(var i = 0 ; i 
8. ImageBackground 的圆角在 style 里设置没用 需要用imageStyle

9. 使得任何一个React组件支持动画。

Animated.createAnimatedComponent(Component: any)可以使任何一个React组件支持动画。 默认支持的Animated.Image,Animated.ScrollView,Animated.Text,Animated.View。

Animated FlatList需使用ref属性时 加入以下代码:

    { this._listRef = ref}}
       ...
   /> 

   //使用方法
   this._listRef.getNode().scrollToOffset({y:0})
10. view 三角冒泡框
        // 设置上下越小,三角就越尖
          
11. android环境下gif没有动画,不支持gif图

解决:
在android/app/build.gradle中的dependencies字段中添加:
compile 'com.facebook.fresco:fresco:1.5.0'
compile 'com.facebook.fresco:animated-gif:1.5.0'

12. 性能调试及优化

开发模式 (dev=true)

有个小技巧可以在发布时屏蔽掉所有的console.*调用。React Native中有一个全局变量__DEV__用于指示当前运行环境是否是开发环境。我们可以据此在正式环境中替换掉系统原先的console实现。

  if(!__DEV__ ){
      global.console={
         log:() => {},
         info:() => {},
         assert: () => {},
         warn:() => {},
         debug:() => {},
         error:() => {}
      }
  }

_DEV_=true即开发模式下,JavaScript线程的性能是很糟糕的,因为有许多工作需要在运行的时候去做,譬如使你获得良好的警告和错误信息,又比如验证属性类型(propTypes)以及产生各种其他的警告。

13. 使用webview加载html乱码问题
  
14. 字体不随系统字体设置改变而改变

方法一:

  const {fontScale} = Dimensions.get('screen');
  fontSize: 20*(1.0/fontScale)

方法二:

import { Text, TextInput } from 'react-native'

TextInput.defaultProps = Object.assign({}, TextInput.defaultProps, {defaultProps: false});
Text.defaultProps = Object.assign({}, Text.defaultProps, {allowFontScaling: false});
15. xcode10.1 0.55.4-0.56 'config.h' file not found

error:Build input file cannot be found: '/Users/taocong/Desktop/RNProject/AppDemo/node_modules/react-native/third-party/

cd node_modules/react-native/third-party/glog-0.3.4
../../scripts/ios-configure-glog.sh
16.通过findNodeHandle和UIManager来获取组件的尺寸:
import {
    findNodeHandle,
    UIManager
} from 'react-native';
 
layout(ref) {
        const handle = findNodeHandle(ref);
         
        return new Promise((resolve) => {
            UIManager.measure(handle, (x, y, width, height, pageX, pageY) => {
                resolve({
                    x,
                    y,
                    width,
                    height,
                    pageX,
                    pageY
                });
            });
        });
 }

layout这个函数接受一个ref参数,这个参数表示组件的实例。传入组件的实例后,然后通过findNodeHandle方法获取组件节点。
UIManager.measure接受两个参数,第一个参数是通过findNodeHandle获取的组件节点,第二个参数是获取成功的回调,回调有6个参数:x,y表示组件的相对位置,width,height表示组件的宽度和高度,pageX,pageY表示组件相对于屏幕的绝对位置。

17.PanResponder

onPanResponderMoveAnimated.event() 的结合使用

利用 PanResponder 做了一个拖动调节图标位置的功能,网上找的方法是在 onPanResponderMove 中使用 Animated.event() 来对 View 进行移动。实现效果不错,但是发现一旦在 onPanResponderMove 中使用了 lambda 表达式后,就不起作用了。后来网上找到这个 issue,发现原来 Animated.event() 会返回一个方法,并且接收 event 和 gestureState 作为参数,所以我们只要去调用一下这个方法即可:

onPanResponderMove: (evt, gestureState) => {
  return Animated.event([null, {
    dx: this.state.pan.x,
    dy: this.state.pan.y,
  }])(evt, gestureState)
}
18.TextInput Android 文字对齐问题

当 TextInput multiline为true,发现文字显示在 iOS 上是顶端对齐,而在 Android 上则文本默认会垂直居中,可设置textAlignVertical: 'top'样式来使其居顶显示。
解决方法 TextInput 设置 textAlignVertical: "top" 属性,相关 issue 见:Render Multiline Text at start instead of center

Android 上 TextInput 失去焦点之后键盘无法自动收起
这时候我们可以给根布局设置接收触摸事件:

onStartShouldSetResponder={() => true}
onResponderRelease={() => Keyboard.dismiss()}

19.KeyboardAvoidingView behavior 相关

该组件在 Android 和 iOS 上的表现有区别,所以我们会区分平台使用不同的 behavior,比如下面这样:


    ...

padding 模式下,当键盘弹起的时候,你的 view 会向上弹起并被压缩。使用 padding 作为 behavior 的时候,在 iOS 上表现比较好,而在 Android 上则不设置 behavior 比较好。
position 模式下,view 整体会向上滑动。这种模式 Android 和 iOS 上表现一致,但是前提是此时 KeyboardAvoidingView 是根 view。同时这也会造成一个问题,那就是键盘弹出后,输入组件会一直占有焦点,这在安卓上还好,可以通过返回键关闭键盘,而在 iOS 设备上就会造成键盘无法被关闭的尴尬。解决这一问题的方法是通过在 KeyboardAvoidingView 设置接收触摸事件,当在输入焦点之外获得点击时收起键盘:

 true}
  onResponderRelease={() => Keyboard.dismiss()}
/>
20. FlatList onEndReached 刷新次数频繁问题
onEndReached={()=>{
  // 等待页面布局完成以后,在让加载更多
   if (this.isCanLoadMore){
      this.loadMore();
      this.isCanLoadMore = false // 加载更多时,不让再次的加载更多
  }
}}
onContentSizeChange={()=>{
  this.isCanLoadMore = true // flatview内部组件布局完成以后会调用这个方法
}}
onEndReachedThreshold={0.01}
21 view阴影
shadowColor: "#000",
shadowOffset: {
    width: 0,
    height: 4,
},
shadowOpacity: 0.30,
shadowRadius: 4.65,
elevation: 8,
22 .解决Modal无法有效隐藏状态栏

编辑android/app/src/main/resvalues/styles/styles.xml


    

23 .RN离线包准备
  • android
    react-native bundle --entry-file index.js --bundle-output ./android/app/src/main/assets/index.android.bundle --platform android --assets-dest ./android/app/src/main/assets --dev false

  • iOS:
    react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ./ios/bundle/index.ios.jsbundle --assets-dest ./ios/bundle

  • Duplicate resources报错的话
    在 /node_modules/react-native/react.gradle 这个文件里加上以下代码

doFirst { ... }
doLast {
    def moveFunc = { resSuffix ->
        File originalDir = file("$buildDir/generated/res/react/release/drawable-${resSuffix}");
        if (originalDir.exists()) {
            File destDir = file("$buildDir/../src/main/res/drawable-${resSuffix}");
            ant.move(file: originalDir, tofile: destDir);
        }
    }
    moveFunc.curry("ldpi").call()
    moveFunc.curry("mdpi").call()
    moveFunc.curry("hdpi").call()
    moveFunc.curry("xhdpi").call()
    moveFunc.curry("xxhdpi").call()
    moveFunc.curry("xxxhdpi").call()
}
24. xcode11 0.61.5 react-native-fast-image pod fatal: unable to access 'https://chromium.googlesource.com/webm/libwebp/'
RN 经验_第2张图片
image.png
  • 解决
    Finder -> 前往文件夹 (⇧⌘G) -> ~/.cocoapods/repos/master/Specs/1/9/2/libwebp点击最新版本
    把https://chromium.googlesource.com/webm/libwebp 替换为 https://github.com/webmproject/libwebp.git 并保存重新pod即可

你可能感兴趣的:(RN 经验)