React Native真的是越来越流行,没使用React Native开发项目都不好意思说自己是搞客户端开发的。对于纯Native开发者来说,刚上手React Native有一定的适应期,如果JavaScript也不熟练的话那就更悲催了。React Native涉及ES6,React语法,JSX,前端调试,Native客户端等知识,本文简单总结了React Native开发中一些知识点。算是在学习中的积累。
Component Component:组件,使用React.createClass
或者extends React.Component
创建的类为组件。 Element:元素或者可以说是组件的实例,使用<Label />
或者let label = new Label()
创建的为实例。
对于定义组件,React以前版本的写法(ES5):1 2 3 4 5 6 var Lable = React.createClass({ render(){ } });
React最新的写法(ES6):1 2 3 4 class Label extends React .Component { render(){ } }
props与state props属性:组件可以定义初始值,自己不可更改props属性值,只允许从父组件中传递过来:1 2 3 4 5 6 7 8 9 10 11 12 13 class MainComponent extends React .Component { render(){ return (<Label name ="标题栏" > ) ; } } class Label extends React .Component { render(){ return (<Text > {this.props.name}</Text > ) ; } }
父组件向Label传递name=”标题栏”的props属性,在Label中使用this.props.name引用此属性。
state属性:组件用来改变自己状态的属性,通常使用setState({key:value})
来改变属性值,不能使用this.state.xxx
来直接改变,setState({key:value})
方法会触发界面刷新。
对于经常改变的数据且需要刷新界面显示,可以使用state。对于不需要改变的属性值可以使用props。React Native建议由顶层的父组件定义state值,并将state值作为子组件的props属性值传递给子组件,这样可以保持单一的数据传递。
在以前版本的React中定义state,props可以使用生命周期方法 getInitialState()
和getInitialState()
:1 2 3 4 5 6 7 8 9 10 11 12 13 var Label = React.createClass({ getInitialState(){ key:value, ... }, getInitialProps(){ key:value, ... }, render:funation(){ } });
在最新版本的React可以使用构造函数替代getInitialState(),getInitialState()方法定义初始值: 1 2 3 4 5 6 7 8 9 10 11 12 class Label extends React .Component { constructor(props) { super (props); this .state = { time: '2016' , city: '上海' , }; this .props = { name:'标题' , }; } }
默认props与props校验 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Label extends React .Component { constructor(props) { super (props); } static defaultProps = { city: '南京' , index: 12 , } static propTypes = { city: React.PropTypes.string.isRequired, index: React.PropTypes.number.isRequired, } state = { city: this .props.city, index:this .props.index, } } class Label extends React .Component { constructor(props) { super (props); } } Label.defaultProps = { city: '南京' , index: 12 , } Label.propTypes = { city: React.PropTypes.string.isRequired, index: React.PropTypes.number.isRequired, }
生命周期 我们把组件从装载
,到渲染
,再到卸载
当做一次生命周期,也就是组件的生存状态从装载
开始到卸载
为止,期间可以根据属性的变化进行多次渲染。
生命周期的三种状态:
Mounting:装载,
Updating:渲染
Unmounting:卸载
1 2 3 4 5 componentWillMount () ,组件开始装载之前调用,在一次生命周期中只会执行一次。componentDidMount () ,组件完成装载之后调用,在一次生命周期中只会执行一次,从这里开始就可以对组件进行各种操作了,比如在组件装载完成后要显示的时候执行动画。componentWillUpdate (object nextProps, object nextState) ,组件属性更新之前调用,每一次属性更新都会调用componentDidUpdate (object prevProps, object prevState) ,组件属性更新之后调用,每次属性更新都会调用componentWillUnmount () ,组件卸载之前调用
组件属性更改时会调用以下方法,在一次生命周期中可以执行多次:1 2 componentWillReceiveProps (object nextProps) ,已加载组件收到新的参数时调用shouldComponentUpdate (object nextProps, object nextState) ,组件判断是否重新渲染时调用
页面跳转 初始化第一个页面:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import SeatPageComponent from './SeatPageComponent ';import MainPageComponent from './MainPageComponent ';import TrainListComponent from './TrainListComponent ';class MainPage extends React .Component { render() { let defaultName = 'MainPageComponen t'; let defaultComponent = MainPageComponent ; return ( <Navigator initialRoute={{ name: defaultName, component: defaultComponent }} configureScene={(route) => { return Navigator .SceneConfigs .VerticalDownSwipeJump ; }} renderScene={(route, navigator) => { let Component = route.component; return <Component {...route.params} navigator={navigator} /> }} /> ); } }
跳转到下一页面:1 2 3 4 5 6 7 8 9 jumpToNext(){ const { navigator } = this .props; if (navigator) { navigator.push({ name: 'SeatPageComponent' , component: SeatPageComponent, }); } }
返回上一个页面:1 2 3 4 5 6 _back(){ const { navigator } = this .props; if (navigator) { navigator.pop(); } }
页面间通信 例如:从A页面打开B页面 A通过route.params将参数传递给B:1 2 3 4 5 6 7 8 9 10 11 12 13 jumpToNext(){ const { navigator } = this .props; if (navigator) { navigator.push({ name: 'SeatPageComponent' , component: SeatPageComponent, params : { id: 123 , title: this .state.title, }, }); } }
A通过route.params传递回调方法或者A的引用来让B将数据传回给A:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 jumpToNext(){ const { navigator } = this .props; if (navigator) { let that = this ; navigator.push({ name: 'SeatPageComponent' , component: SeatPageComponent, params: { title: '测试' , getName: function (name ) {that.setState({ name: name })} }, }); } } _back(){ const { navigator } = this .props; if (this .props.getName){ this .props.getName('测试' ); } if (navigator) { navigator.pop(); } }
组件间通信 父组件–>子组件, 使用props,父组件向子组件传递props
1 2 3 4 5 6 7 8 9 10 11 12 13 class MainComponent extends React .Component { render(){ return (<Label name ="标题栏" > ) ; } } class Label extends React .Component { render(){ return (<Text > {this.props.name}</Text > ) ; } }
子组件–>父组件, 父组件在创建子组件时传递回调方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class MainComponent extends React .Component { constructor(props) { super (props); this .state = { name: '测试' , }; } getName(str){ this .setState({name:str}); } render(){ return (<Label name ="标题栏" getName ={getName} /> ) ; } } class Label extends React .Component { render(){ return ( <View > <TouchableOpacity onPress ={()= > this._onPress()}> <Text > 点我,{this.props.name}</Text > </TouchableOpacity > </View > ) ; } _onPress(){ if (this .props.getName){ this .props.getName('测试' ) } } }
非父子关系的组件,即没有任何嵌套关系的组件, 可以引入订阅源(js-signals , PubSubJS ),监听订阅事件。例如,在生命周期方法中addEventListener(),removeEventListener(),在合适时机setState()。
ECMAScript ES6中函数的写法:1 2 3 4 5 class Label extends React .Component { doSomething(){ } }
key:value形式定义函数的写法:1 2 3 4 5 6 7 8 var Label = React.createClass({ doSomething:funation(){ }, doSomething2:function ( ) { }, });
函数绑定1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Label extends React .Component { sayHello(str){ console .log(str) } render(){ return ( <View > <TouchableOpacity onPress ={() => this.sayHello('Hello')}> <Text > 点我</Text > </TouchableOpacity > </View > ) } function print (str,this ) { let that = this ; function say (str ) { that.sayHello(str) } say(str); } }
Tips require,import:javascript的模块管理工具,管理各个模块之间的引用,解决javascript异步加载的问题,解决js写成多个文件后浏览器加载缓慢的问题。
JavaScript中没有private,public的概念 使用_开头的方法代表private方法,不适用则表示public方法1 2 3 4 5 6 7 8 9 10 11 class Label extends Component { _doSomething(){ } doSomething(){ } }
参考资料Reactjs中文教程 极客学院React教程 ECMAScript语法 JavaScript模块系统 require.js Navigator 结合ES6+开发React React组件通信