React Native 语法指南

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):

var Lable  = React.createClass({

    render(){
    
    }
});

React最新的写法(ES6):

class Label extends React.Component{
    render(){
    }
}

props与state


props属性:组件可以定义初始值,自己不可更改props属性值,只允许从父组件中传递过来:

// 父组件
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():

var Label = React.createClass({
    getInitialState(){
        key:value,
        ...
    },
    getInitialProps(){
        key:value,
        ...
    },// 这种写法需要有,不要使用;
    render:funation(){
        
    }
});

在最新版本的React可以使用构造函数替代getInitialState(),getInitialState()方法定义初始值:

class Label extends React.Component{
   constructor(props) {
       super(props);
       this.state = {
           time: '2016',
           city: '上海',
       };
       this.props = {
           name:'标题',
       };
   }
}

默认props与props校验


class Label extends React.Component{
   constructor(props) {
       super(props);
   }

  // 默认props
  static defaultProps = {
     city: '南京',
     index: 12,
  }
   
  // propTypes用于验证转入的props,当向 props 传入无效数据时,JavaScript 控制台会抛出警告
  static propTypes = {
     city: React.PropTypes.string.isRequired,
     index: React.PropTypes.number.isRequired,
  }

  state = {
     city: this.props.city,
     index:this.props.index,
  }
}

// or

class Label extends React.Component{
   constructor(props) {
       super(props);
   }
}

// 默认props
Label.defaultProps = {
   city: '南京',
   index: 12,
}

// propTypes用于验证转入的props,当向 props 传入无效数据时,JavaScript 控制台会抛出警告
Label.propTypes = {
   city: React.PropTypes.string.isRequired,
   index: React.PropTypes.number.isRequired,
}

生命周期


我们把组件从装载,到渲染,再到卸载当做一次生命周期,也就是组件的生存状态从装载开始到卸载为止,期间可以根据属性的变化进行多次渲染。

生命周期的三种状态:

  • Mounting:装载,
  • Updating:渲染
  • Unmounting:卸载
componentWillMount(),组件开始装载之前调用,在一次生命周期中只会执行一次。
componentDidMount(),组件完成装载之后调用,在一次生命周期中只会执行一次,从这里开始就可以对组件进行各种操作了,比如在组件装载完成后要显示的时候执行动画。
componentWillUpdate(object nextProps, object nextState),组件属性更新之前调用,每一次属性更新都会调用
componentDidUpdate(object prevProps, object prevState),组件属性更新之后调用,每次属性更新都会调用
componentWillUnmount(),组件卸载之前调用

组件属性更改时会调用以下方法,在一次生命周期中可以执行多次:

componentWillReceiveProps(object nextProps),已加载组件收到新的参数时调用
shouldComponentUpdate(object nextProps, object nextState),组件判断是否重新渲染时调用

页面跳转


初始化第一个页面:

import SeatPageComponent from './SeatPageComponent';
import MainPageComponent from './MainPageComponent';
import TrainListComponent from './TrainListComponent';

class MainPage extends React.Component {
    render() {
        let defaultName = 'MainPageComponent';
        let defaultComponent = MainPageComponent;
        return (
            <Navigator
                // 指定默认页面
                initialRoute={{ name: defaultName, component: defaultComponent }}
                // 配置页面间跳转动画
                configureScene={(route) => {
                    return Navigator.SceneConfigs.VerticalDownSwipeJump;
                }}
                // 初始化默认页面
                renderScene={(route, navigator) => {
                    let Component = route.component;
                    // 将navigator作为props传递到下一个页面
                    return <Component {...route.params} navigator={navigator} />
                }} />
        );
    }
}

跳转到下一页面:

jumpToNext(){
      const { navigator } = this.props;// 由上一个页面传递过来
      if(navigator) {
          navigator.push({
              name: 'SeatPageComponent',
              component: SeatPageComponent,// 下一个页面
          });
      }
}

返回上一个页面:

 _back(){
     const { navigator } = this.props;
     if(navigator) {
         navigator.pop();
     }
 }

页面间通信


例如:从A页面打开B页面
A通过route.params将参数传递给B:

jumpToNext(){ 
    const { navigator } = this.props;// 由上一个页面传递过来
    if(navigator) { 
        navigator.push({ 
            name: 'SeatPageComponent', 
            component: SeatPageComponent,// 下一个页面 
            params: { // 需要传递个下一个页面的参数,第二个页面使用this.props.xxx获取参数
                id: 123,
                title: this.state.title, 
            },
        });
     }
}

A通过route.params传递回调方法或者A的引用来让B将数据传回给A:


// A页面
jumpToNext(){ 
    const { navigator } = this.props;// 由上一个页面传递过来
    if(navigator) { 
        let that = this;// this作用域,参见下文函数绑定
        navigator.push({ 
            name: 'SeatPageComponent', 
            component: SeatPageComponent,// 下一个页面 
            params: { // 需要传递个下一个页面的参数,第二个页面使用this.props.xxx获取参数
                title: '测试',
                getName: function(name) {that.setState({ name: name })}
            },
        });
     }
}

// B页面
 _back(){
     const { navigator } = this.props;
     if(this.props.getName){
         this.props.getName('测试');
     }
     if(navigator) {
         navigator.pop();
     }
 }

组件间通信


父组件-->子组件, 使用props,父组件向子组件传递props

// 父组件
class MainComponent extends React.Component{
    render(){
        return(<Label name="标题栏">);
    }
}

// 子组件
class Label extends React.Component{
    render(){
        return(<Text>{this.props.name}</Text>);
    }
}

子组件-->父组件, 父组件在创建子组件时传递回调方法

// 父组件
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中函数的写法:

class Label extends React.Component{
    doSomething(){
        //...
    }// 不要使用逗号或者分号作为结尾
}

key:value形式定义函数的写法:

var Label = React.createClass({
    doSomething:funation(){
        //......
    },// 需要使用逗号作为结尾,不能使用分号
    doSomething2:function(){
        //......
    },
});

函数绑定

class Label extends React.Component{

    // 有函数
    sayHello(str){
        console.log(str)
    }

    // 在onPress中使用箭头函数调用
    // onPress={() => this.sayHello('Hello')}
    
    // 等同于
    //onPress={sayHello('hello').bind(this)} 

    // 等同于
    // onPress={print('hello',this)}

    render(){
        return (
              <View>
                   <TouchableOpacity onPress={() => this.sayHello('Hello')}>
                          <Text>点我</Text>
                   </TouchableOpacity>
              </View>
        )
    }

    function print(str,this){
        let that = this;// 注意这里this的生命周期
        function say(str){
            that.sayHello(str)// 此处不能再使用this
        }
        say(str);
    }
}

Tips


require,import:javascript的模块管理工具,管理各个模块之间的引用,解决javascript异步加载的问题,解决js写成多个文件后浏览器加载缓慢的问题。

JavaScript中没有private,public的概念
使用_开头的方法代表private方法,不适用则表示public方法

class Label extends Component{
    // private 函数
    _doSomething(){
        //......
    }
    
    // public 函数
    doSomething(){
        //......
    }
}

参考资料
Reactjs中文教程
极客学院React教程
ECMAScript语法
JavaScript模块系统
require.js
Navigator
结合ES6+开发React
React组件通信

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

推荐阅读更多精彩内容

  • 自己最近的项目是基于react的,于是读了一遍react的文档,做了一些记录(除了REFERENCE部分还没开始读...
    潘逸飞阅读 3,197评论 1 10
  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,771评论 1 18
  • JSX 知识准备 JSX 并不是一门全新的语言,仅仅是一个语法糖,允许开发者在javascript中编写XML语言...
    艾伦先生阅读 4,439评论 4 20
  • <一>编写Hello World React Native看起来很像React,只不过其基础组件是原生组件而非we...
    AFinalStone阅读 992评论 0 2
  • 妹子说自己不喜欢和男生聊天?不可能,不是你心理有问题(或者同性恋),就是身边男生太渣。看一看你身边的同学,你会发现...
    无恙志阅读 5,789评论 4 15