React Native 总结(一)

React Native总结

不过多描述原理和优缺点,可自行查阅官方手册

一、注意点

1.关于style

style用于标注组件的布局属性,一般情况下有两种写法形式:

内连形式一:

<View style={{flex:1,backgroundColor:'red'}}/>

抽象形式二:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  })
  <View style={styles.container}/>

两种形式都可以用于添加组件布局属性,但一般情况下,在组件所属目录下,创建名为styles.js的文件夹,使用第二种形式在文件内统一创建style,并对外export。

这样做的好处一方面是使代码清晰整洁,不冗余,方便复用和修改,另一方面是防止每次组件render时,频繁的进行style创建。

还有一种情况是内连和抽象形式连用形成包裹形式:

<View style={[styles.container,this.props.style]}/>

这种形式在进行自定义组件的时候十分常见,为style赋值一个数组,第一个数组对象一般设置为组件的固有布局属性或默认布局属性,第二个数组对象为组件使用时,外部对组件布局属性的自定义。如果两个布局属性存在同样的关键字时,以第二的布局属性为准。

2.关于ref

组件的ref字段一般被用来获取组件的对象,一般书写形式如下:

    compoentDidMount(){
    this.refs.view // 获取到view组件对象
    this._scroll.scrollTo({y:10,x:10})//获取到ScrollView对象,并执行scrollTo()
    }
    ....
    <View ref='view'></View>
    <TextInput ref={(input)=>{
        //此处可以对TextInput组件进行操作,比如focus()
    }}/>
    <ScrollView ref={(scroll)=>this._scroll = scroll}/>

可以尝试打印一下通过ref获取到的组件对象,例如打印scrollview的组件对象,可以找到组件对象可以调用的方法、组件的属性和其子组件与父组件信息。
ref仅可以在组件被render到界面后,才可以调用,否则会返回undefined;

3.关于image

关于Image组件,目前版本,在iOS和Android平台上行为略微不一致,当不给Image设置source或source不可用时,仅设置布局属性时,iOS端会显示根据布局属性生成无图组件,进行占位;Android端则不会生成无图组件进行占位,即便设置了明确的长高属性。

4.关于onLayout和NativeMethodsMixin

每个组件都可以设置onLayout属性来获取组件的位置信息

<View onLayout={(e)=>{e.nativeEvent即是组件的位置信息}/>

但通过onLayout获取到的位置信息只是相对于父组件的位置坐标,而不是相对于屏幕位置的绝对坐标。
通过对NativeMethodsMixin方法的调用,可以帮助我们直接对组件进行操作,其中一方面功能就是获取组件在最底层视图上显示的尺寸。

this.refs.view.measure((x,y,width,height,pageX,pageY)=>{
        console.log(x,y,width,pageX,pageY,height);
    })

但是,这个方法需要预留反应时间,目前版本中,在componentDidMount中不可以调用此方法,虽然不会报错,但返回结果全部为0;正如官方文档所说,如果想更快的获取组件尺寸,请使用onLayout;
NativeMethodsMixin还有两个比较常用的方法:measureInWindow和measureLayout。当设计模式为在原生应用中嵌入React Native窗口时,可以使用measureInWindow获得组件相对于屏幕的坐标信息,参数是一个callBack,用法参照measure;measureLayout可以用来获取组件和目标组件之间的相对坐标。参数有三个:第一个为目标视图的节点,第二个参数为成功时的回调,第三个参数为失败时的回调。获取组件节点使用findNodeHandle,从0.27版本后,该方法引用方式变为

import {findNodeHandle} from 'react-native';

对于onLayout还有一点疑问,如果调用如下代码

<View onLayout={()=>log}>
    <View onLayout={()=>log}>
        <View onLayout={()=>log}>
        </View>
    </View>
</View>

即对一个多层级的组件都设置onLayout属性时,Android端外层onLayout的触发会比内层快一点,而iOS端onLayout的触发则是不固定的,同时触发时快时慢。虽然相差时间都是毫秒级别,目前没有发现影响,但不排除特定状态下会产生bug。

5.关于Immuatble.js

Immutable.js 是facebook的一个js库,目的就是为JavaScript添加不可变的数据类型。React Native中在使用state控制视图时,可以通过使用Immutable.js来进行state判断,确定是否刷新视图。
Immutable的语法不过多介绍,此处只介绍Immutable的is方法。

is方法用来比较两个Immutable类型的数据是否相等,此处的比较为值比较。与之对应的Object.is和 === 则是进行地址比较。

 let test1 = Immutable.fromJS({a:{b:1}});
 let test2 = Immutable.fromJS({a:{b:2}});
 let temp = test2.setIn(['a','b'],1);//将键b的值改为1
 console.log(Immutable.is(test1,temp));//打印结果为true
 let test3 = {a:1,b:2};
 let test4 = {a:1,b:2};
 console.log(Object.is(test3,test4));//打印结果为false
 console.log(test3===test4);//打印结果为false

通过使用Immutable.js,可以在shouldComponentUpdate中,完成对states和props的判断。其他用法详见文档和链接
<a>http://facebook.github.io/immutable-js/docs/#/<a/>
<a>https://zhuanlan.zhihu.com/p/20295971</a>

6.关于视图渲染刷新

6.1 过度渲染

React Native组件的渲染都在render函数中执行并return,即每触发一次render函数都要重新渲染一次组件。而每次对state的修改则会触发一次render,将整个组件重新渲染。这就将导致一个问题,即过度渲染。有时候我们频繁的进行state操作时,频繁的触发render,导致页面卡顿,性能下降,动画掉帧等一系列问题。

6.2 setNativeProps

setNativeProps其实是对组件底层进行操作,而不是在RN框架层面进行组件的设置,所以调用setNativeProps方法可以规避render等组件相关方法的触发,但是官方建议,能用state和shouldcomponentUpdate解决时就不用setNativeProps,因为使用setNativeProps可能会导致代码结构不是很清晰或state混乱。所以setNaiveprops一般被用于进行动画设置和增强视觉效果方面。用法如下:

this.refs.view.setNativeProps({backgroundColor:'red'})
//将view背景改为红色

6.3 shouldComponentUpdate

在shouldComponentUpdate方法中我们可以判断组件下一组props和state的变化来决定是否触发render,重新渲染组件。此处可以使用上面所提到的Immuatble.js库。
具体写法

shouldComponentUpdate(nextProps,nextState){
const thisProps = this.props || {}, thisState = this.state || {};
if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
    Object.keys(thisState).length !== Object.keys(nextState).length) {
  return true;
}
for (const key in nextProps) {
  if ((thisProps[key] !== nextProps[key] || !is(Immutable.fromJS(thisProps[key]), Immutable.fromJS(nextProps[key])))&&typeof(thisProps[key])!="function") {
    return true;
  }
}
for (const key in nextState) {
  if (thisState[key] !== nextState[key] || !is(thisState[key], nextState[key])) {
    return true;
  }
}
return false;
}

基本的shouldComponentUpdate的写法如上所示,根据组件需求进行微调即可。但需要注意的是,当state或者props中存在function时,此时比较state和props,总会返回false,即previousState(props)和nextState(props)始终不相等,所以一般情况下比较两者时,屏蔽function类型。

6.4 组件化

组件化的好处一方面是为了进行组件的复用,还有一方面是进行组件是否重新渲染的判断。例如一个组件有7个层级,当组件重新渲染时,就要把7个层级都渲染一遍,而且因为7个层级组件都写在了一个render里,不仅代码臃肿,而且无法进行区别判断是否渲染。所以尽量将代码抽离,实现组件化。

7.关于Promise、async和await

Promise对象是ES6新增的,常作为异步结果的返回值,例如:本地数据存储或fetch网络请求。async函数同样是ES6新增的,需要同await联合使用。所以一般情况下同时使用两者去进行异步处理,以网络请求为例

async someHandle(url){
    try{
    let result = await fetch(url);
    
    console.log(result)
    
    return result;
    }catch(err){
    console.log(err);
    }
}

但是aysnc函数有一个特点是假如fetch等异步操作返回reject,那么async函数将直接返回reject状态,而不会往下继续执行。即假如fetch若返回reject,将不会执行下面的打印。
可以在async函数内加上try...catch,来收集异步操作的错误信息。

8.关于Redux

Redux是一个state管理框架,只存在一个store来存储所有的state,只可以通过触发action,action触发reducer,去修改store里的state,来确保state的状态改变行为可控。

8.0 必备框架

react-redux 、redux 、redux-thunk即可,全部可以通过

npm install --save 框架名 

安装

8.1 action

action相当于一个触发动作,告诉reducer去修改state。
一般的action形式:

someHandle(value){
    
    return{
        type:someType,
        value,
    }
}

action函数必须返回一个包含type的对象,其他字段和对象结构可以自行设计,返回type的目的是为了在reducer进行响应的时候进行判断,具体如何哪个state。

8.2 reducer

reducer函数是通过action触发的,state的修改是在该函数内进行的。
一般的reducer形式:

const initialState = Map({
    number:1,
    opacity:0,
    offset:0
})
export default function someHandle (state= initialState, action={}){
    switch (action.type) {
        case SOMETYPE:
        return   //此处返回操作过的state
        default:
        return state;
        }
}

注意reducer中,不可以直接修改state,需要根据操作,生成新state,并返回,reducer需要保证数据的唯一和不可变,所以此处的state可以使用Immutable.js进行数据类型的定义。

8.3 redux-thunk

redux-thunk是一个redux的中间件,可以使某一action可以出发另一个action,目的是为了可以在action函数中进行异步操作,例如进行网络请求获取json数据并处理。

someHandle(){
    return (dispatch,getState){
        
        //一些异步处理
        
        dispatch({       
            type:someType,
            ...
        })//触发reducer
    }
}

该框架不是实现redux的必须框架,中间件可以自行定义。

8.4 其他

使用redux结构管理state不一定总是有益的,在项目需求简单时,接入该结构完全没有必要。而且在自定义组件是也不需要引入该结构,具体情况还需要按照项目需求进行处理。
redux在React Native中的工作其实是控制每个组件的props,通过改变组件的props,达到组件渲染和状态的可控,所以redux的state并不代表RN框架的state,也不是对state的取代,而是另一种形式的状态机。两者各有利弊,结合使用效果更佳。
demo地址:<a>https://pan.baidu.com/s/1eS81cXG<a/>(非原创,但是原地址找不到了。。。)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容