[react] RN 积累

使用相关

css

pixel point(PT)代表的是逻辑像素而不是实际像素.

可以通过Dimensions 来获取宽高,PixelRatio 获取密度。

React Native中的Flexbox的工作原理和web上的CSS基本一致,当然也存在少许差异。
首先是默认值不同:flexDirection的默认值是column而不是row,alignItems的默认值是stretch而不是flex-start。

justifyContent可以决定其子元素沿着主轴的排列方式。
alignItems可以决定其子元素沿着次轴(与主轴垂直的轴,比如若主轴方向为row,则次轴方向为column)的排列方式。

position没有fixed,定位相对于父元素,父元素不用设置position也行?
padding 设置在Text元素上的时候会存在bug。所有padding变成了marginBottom?
position:relative 不可以使用bottom和right?

只有Text和TextInput会继承父组件的background-color

transform:[{scale:2},{skew:'45deg'}]

props.style 可能为 object,number,array

样式的box-sizing似乎是默认border-box的.

Text

元素在布局上不同于其它组件:在Text内部的元素不再使用flexbox布局,而是采用文本布局。这意味着内部的元素不再是一个个矩形,而可能会在行末进行折叠。
也就是如果Text元素在Text里边,可以考虑为inline, 如果单独在View里边,那就是Block。

在React Native中,必须把文本节点放在Text组件内。不能直接在下放置一段文本。
也不能直接设置一整颗子树的默认样式。

numberOfLines用来当文本过长的时候裁剪文本。包括折叠产生的换行在内,总的行数不会超过这个属性的限制。 通常和 ellipsizeMode配合使用。
numberOfLines 需要放在最外层的Text元素上,且虽然截取了文字但是还是会占用空间.

allowFontScaling控制字体是否要根据iOS的“文本大小”辅助选项来进行缩放

React Native实际上还是有一部分样式继承的实现,不过仅限于文本标签的子树。
Text不会继承上层View的color,font-size,但是会继承父Text的样式

TextInput

类似Text元素不再使用flexbox布局,而是采用文本布局。

注意有些属性仅在multiline为true或者为false的时候有效。此外,当multiline=false时,为元素的某一个边添加边框样式(例如:borderBottomColor,borderLeftWidth等)将不会生效。为了能够实现效果可以使用一个View来包裹TextInput.

TextInput在安卓上默认有一个底边框,同时会有一些padding。如果要想使其看起来和iOS上尽量一致,则需要设置padding: 0,同时设置underlineColorAndroid="transparent"来去掉底边框。

在安卓上如果设置multiline = {true},文本默认会垂直居中,可设置textAlignVertical: 'top'样式来使其居顶显示。

在安卓上长按选择文本会导致windowSoftInputMode设置变为adjustResize,这样可能导致绝对定位的元素被键盘给顶起来。要解决这一问题你需要在AndroidManifest.xml中明确指定合适的windowSoftInputMode值,或是自己监听事件来处理布局变化。

可以动态更改高度来实现类似textarea的效果?

StyleSheet

StyleSheet创建一个样式表后,然后利用ID来引用样式,减少频繁创建新的样式对象。

把多个样式对象,聚合成一个聚合对象。

var styles = StyleSheet.create({
  listItem: {
    flex: 1,
    fontSize: 16,
    color: 'white',
  },
  selectedListItem: {
    color: 'green',
  },
});

StyleSheet.flatten([styles.listItem, styles.selectedListItem]);
// returns { flex: 1, fontSize: 16, color: 'green' }

另一种写法

const styles = StyleSheet.create({
  listItem: {
    flex: 1,
    fontSize: 16,
    color: 'white',
  },
  selectedListItem: {
    color: 'green',
  },
});

StyleSheet.flatten(styles.listItem);
// return { flex: 1, fontSize: 16, color: 'white' }
// Simply styles.listItem would return its ID (number)

absoluteFillObject

等价{position: "absolute", left: 0, right: 0, top: 0, bottom: 0}

const styles = StyleSheet.create({
  wrapper: {
    ...StyleSheet.absoluteFillObject,
    top: 10,
    backgroundColor: 'transparent',
  },
});

absoluteFillObject有时不能铺满屏幕,似乎和父元素还是有关系的.

absoluteFill等价StyleSheet.create({test:{...StyleSheet.absoluteFillObject}}).test

hairlineWidth

const styles = StyleSheet.create({
  separator: {
    borderBottomColor: '#bbb',
    borderBottomWidth: StyleSheet.hairlineWidth,
  },
});

定义当前平台上的最细的宽度。可以用作边框或是两个元素间的分隔线。
这一常量始终是一个整数的像素值(线看起来会像头发丝一样细),并会尽量符合当前平台最细的线的标准。然而,不能把它“视为一个常量”,因为不同的平台和不同的屏幕像素密度会导致不同的结果。

Image

决定当组件尺寸和图片尺寸不成比例的时候如何调整图片的大小:

  • cover: 在保持图片宽高比的前提下缩放图片,直到宽度和高度都大于等于容器视图的尺寸(如果容器有padding内衬的话,则相应减去)。这样图片完全覆盖甚至超出容器,容器中不留任何空白。
  • contain: 在保持图片宽高比的前提下缩放图片,直到宽度和高度都小于等于容器视图的尺寸(如果容器有padding内衬的话,则相应减去)。这样图片完全被包裹在容器中,容器中可能留有空白。
  • stretch:拉伸图片且不维持宽高比,直到宽高都刚好填满容器。
  • repeat: 重复平铺图片直到填满容器。图片会维持原始尺寸。仅iOS可用。
  • center: 居中不拉伸。

ios 图片资源必须是https资源

Touchable

View不能绑定onPress事件,但是可以用这些替代:
TouchableNativeFeedback和TouchableWithoutFeedback不支持style,但支持onLayout
TouchableHighlight,TouchableOpacity支持style的需要当成View来看待??
TouchableHighlight undelayColor的显示颜色会受到子元素的backgroundColor影响,所以backgroundColor应该尽量只设置在TouchableHighlight上.

TouchableHighlight,TouchableNativeFeedback下级有多级子元素都需要把他们包在一个View里.

Touchable 组件上的onPress可能会阻塞FlatList的滚动

只有touchable支持的事件

  1. 按钮按下事件:onPress - 按下并松开按钮,会触发该事件(相当于PC的onclick)
  2. 按钮长按事件:onLongPress - 按住按钮不松开,会触发该事件(长按事件)
  3. 按钮按下事件:onPressIn - 按下按钮不松开,会触发该事件(相当于PC的onkeydown)
  4. 按钮松开事件:onPressOut - 按下按钮后松开,或按下按钮后移动手指到按钮区域外,都会触发该事件(相当于PC的onkeyup)

触摸事件总被传送给最上层的组件.

pointerEvents:
'auto': 视图可以作为触控事件的目标。
'none': 视图不能作为触控事件的目标。
'box-none': 视图自身不能作为触控事件的目标,但其子视图可以。
'box-only': 视图自身可以作为触控事件的目标,但其子视图不能。
?

onLayout

onLayout获取元素宽高
Dimensions获取设备宽高

class Main extends Component {
   //根View的onLayout回调函数
   _onLayout(event) {
     //使用大括号是为了限制let结构赋值得到的变量的作用域,因为接来下还要结构解构赋值一次
     {
       //获取根View的宽高,以及左上角的坐标值
       let {x, y, width, height} = event.nativeEvent.layout;
       console.log('通过onLayout得到的宽度:' + width);
       console.log('通过onLayout得到的高度:' + height);
     }
 
     //通过Dimensions API获取屏幕宽高
     let {width, height} = Dimensions.get('window');
     console.log('通过Dimensions得到的宽度:' + width);
     console.log('通过Dimensions得到的高度:' + height);
   }
   render() {
     return (
       
       
     );
   }
}

元素display为none大部分情况不会触发onLayout,个别组件可能会触发,
display为none与不渲染的区别是什么,未知.

滚动列表

ScrollView会简单粗暴地把所有子元素一次性全部渲染出来。
ScrollView 可以不需要确定父容器高度,只有自容器高度确定也可以
scrollview会影响TextInput的软键盘.

FlatList 会惰性渲染子元素,只在它们将要出现在屏幕中时开始渲染。

SectionList如果列表不需要分组(section),那么可以使用结构更简单的 FlatList。

WebView

创建一个原生的WebView,可以用于访问一个网页。WebView可用于音媒体播放.

开发/调试

adb 连接模拟器

D:\Users\qm\AppData\Local\Android\sdk\platform-tools
adb connect 127.0.0.1:62001

windows设置环境变量

ANDROID_HOME
D:\Users\qm\AppData\Local\Android\sdk;

PATH
D:\Users\qm\AppData\Local\Android\sdk\tools;D:\Users\qm\AppData\Local\Android\sdk\platform-tools;

一般来说reset需要删除node_modules和._temp文件夹.
如果是多人合作有时候可能还需要删除package-lock.json文件.

react相关

this.setState((prevState, props) => ({
      value: this.getRealValue(prevState, props, 'minus')
    }), () => {
      this.props.onChangeText && this.props.onChangeText(this.state.value);
    });

props变更会触发所有组件实例的componentWillReceiveProps,所以要在里面做好判断避免性能问题.

父组件触发render,会触发子组件的render(或者说所有的更新生命周期).
子组件的render不会触发父组件render.

传入的props如果会被子组件回调改变,需要本身是state,不然有可能会不触发.

propTypes可以传递继承

Text.propTypes = {
    ...RNText.propTypes,
    uppercase: PropTypes.bool,
    style: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]),
};

PureComponent相当于在shouldComponentUpdate里做了数据的浅层比较,减少了render次数.
PureComponent可以识别state和props string/number的变化,减少无意义render,但是无法识别array/object的变化.
接入immutable配合使用则可以识别array/object变化,而且可以识别深层变化
但是用immutable的话,需要注意prop-types的类型识别.
例如说默认需要这么写:
oldListTypeChecker: PropTypes.instanceOf(Immutable.List)
也可以使用其他第三方库简化.
Immutable数据不管是set还是merge等操作,都不会变更源数据,需要自己重新赋值.

动画

LayoutAnimation

想做进场动画,可以将动画做在componentDidMount里.

      LayoutAnimation.configureNext({
        duration: 3000,
        create: {
          type: LayoutAnimation.Types.easeInEaseOut,
          property: LayoutAnimation.Properties.opacity,
        },
        update: {
          type: LayoutAnimation.Types.easeInEaseOut,
          //property: LayoutAnimation.Properties.height,
        }
      })

LayoutAnimation就是用于在下一个绘制或者布局周期(render/layout cycle)里处理界面中全部视图的动画的。
例如在更新State之前调用一下LayoutAnimation.sprint().
只会执行一次,无法指定触发属性.
transform+LayoutAnimation,可能会出现渲染混乱的问题,暂不知原因.
安卓需要加UIManager.
没有动画结束回调,不占js线程有时候不好控制.
LayoutAnimation 在下一次渲染周期的动画还没执行完执行了其他的setState在安卓里容易crash.
LayoutAnimation 会影响软键盘/光标之类不可控组件的动画
InteractionManager 似乎并不能处理 LayoutAnimation
LayoutAnimation在安卓里容易出问题

Animated

Animated内部子组件使用了LayoutAnimation在安卓里非常容易crash
Animated在安卓的不是特别流畅可以使用useNativeDriver,但是useNativeDriver在安卓里只支持transform和opacity
Animated与touchableOpacity一起用可能会导致动画异常
Animated旋转borderRadius写出的圆,在安卓里动画异常
Animated使用useNativeDriver在安卓里支持transform和opacity
Animated.createAnimatedComponent不能包裹stateless component,因为不能取到ref

JSX里''&& 会报错,因为字符串必须放在里.

不能在Image里写margin,padding样式,会导致布局混乱.

Text里包裹的Text设置margin,width等属性失效.
Text里包裹View报错.

有的安卓手机会出现Text里字被截断的问题,有可能是系统字体支持的问题,换一种系统字体试试.

iconfont可能形成的不是一个正方形,但是可以通过设置高度调整.

键盘弹起可能会遮罩掉TextInput,可以使用KeyboardAvoidingView 或者 react-native-keyboard-aware-scroll-view解决.

boxShadow在ios和安卓效果不一致,可能需要依赖其他开源组件实现.

安卓里使用 for of 报错
安卓里jsx里没用view包裹元素(如放数组的形式)会报错

自旋转的圆需要写死宽高,否则容易抖动

new Date()在安卓里转换时间的时候很容易crash,因为不支持yyyy-MM-dd (但是支持yyyy\MM\dd)

转载于:https://www.cnblogs.com/qingmingsang/articles/9815368.html

你可能感兴趣的:([react] RN 积累)