React Native 总结(一)

React Native总结

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

一、注意点

1.关于style

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

内连形式一:


抽象形式二:

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

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

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

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


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

2.关于ref

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

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

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

3.关于image

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

4.关于onLayout和NativeMethodsMixin

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

{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还有一点疑问,如果调用如下代码

log}>
    log}>
        log}>
        
    

即对一个多层级的组件都设置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的判断。其他用法详见文档和链接
http://facebook.github.io/immutable-js/docs/#/
https://zhuanlan.zhihu.com/p/20295971

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地址:https://pan.baidu.com/s/1eS81cXG(非原创,但是原地址找不到了。。。)

你可能感兴趣的:(React Native 总结(一))