React Native(iOS)新手小白零基础自学(九)常用API及其实践一

1.AppRegistry

/*
      AppRegistry负责注册运行React Native应用程序的入口。通过AppRegistry.registerComponent来注册,当注册完成后,
      Native系统(Objective-C)就会加载jsbundle文件并且触发AppRegistry.runApplication运行应用。有以下方法:
      1.registerConfig(config: Array<AppConfig>):静态方法,注册配置。
      2.registerComponent(appKey: string, getComponentFunc: ComponentProvider):注册入口组件。
      3.registerRunnable(appKey: string, func: Function):注册函数监听。
      4.getAppKeys():获取registerRunnable注册的监听键。
      5.runApplication(appKey: string, appParameters: any):运行App。
 */
启动应用时,x-code日志输出如下:
2016-05-19 13:48:28.777 [info][tid:com.facebook.react.JavaScript] Running application 
"InformationServicesRN" with appParams: {"rootTag":1,"initialProps":{}}.
 __DEV__ === true, development-level warning are ON, 
performance optimizations are OFF
其实,上面的日志是由runApplication打印出来的,添加如下代码:
alert(AppRegistry.runApplication);
AppRegistry.registerComponent('InformationServicesRN', () => app);

效果图如下:


7074268D-FFDA-4E98-BCA8-29F8D11287EE.png

runApplication函数中的console.log()打印的正是我们启动时的日志。
也可以使用registerRunnable注册一些AppKey:

 AppRegistry.registerRunnable('vczero', function(){
   console.log('vczero');
 });
 AppRegistry.registerRunnable('react-native', function(){
   console.log('react-native');
 });
 alert(AppRegistry.getAppKeys());

效果如下:


83B2201B-825E-41A8-8C92-D3F915237659.png

2.AsyncStorage

/*
    AsyncStorage是一个简单的、具有异步特性的键值对的存储系统。相对整个App而言,它是全局的,应该用于替代LocalStorage。
    AsyncStorage提供了比较安全的方法供我们使用。每个方法都有一个回调函数,而回调函数的第一个参数都是错误对象。如果发生错误该对象就会展示错误信息,否则为null。所有的方法执行后,都会返回一个Promise对象。具体的方法如下所示:
      1.static getItem(key: string, callback:(error, result)): 根据键来获取值,获取的结果会在回调函数中。
      2.static setItem(key: string, value: string, callback:(error)):设置键值对。
      3.static removeItem(key: string, callback:(error)):根据键移除一项。
      4.static mergeItem(key: string, value: string, callback:(error)):合并现有值和输入值。
      5.static clear(callback:(error)):清除所有的项目。
      6.static getAllKeys(callback:(error)):获取所有的键。
      7.static multiGet(keys, callback:(error, result)):获取多项,其中keys是字符串数组。
      8.static multiSet(keyValuePairs, callback:(error)):设置多项,其中keyValuePairs是字符串的二维数组。
      9.static multiRemove(keys, callback:(error)):删除多项,其中keys是字符串数组。
      10.static multiMerge(keyValuePairs, callback:(error)):多个键值对合并,其中keyValuePairs是字符串的二维数组。
 */

以购物车为例,来看看效果:

2.1 数据模型构建
这里以购买水果为例定义一个静态的商品数组。

var Model = [
  {
    id: '1',
    title: '佳沛新西兰进口猕猴桃',
    desc: '12个装',
    price: 99,
    url: 'http://vczero.github.io/ctrip/guo_1.jpg'
  },
  {
    id:'2',
    title: '墨西哥进口牛油果',
    desc: '6个装',
    price: 59,
    url: 'http://vczero.github.io/ctrip/guo_2.jpg'
  },
  {
    id:'3',
    title: '美国加州进口车厘子',
    desc: '1000g',
    price: 91.5,
    url: 'http://vczero.github.io/ctrip/guo_3.jpg'
  },
  {
    id:'4',
    title: '新疆特产西梅',
    desc: '1000g',
    price: 69,
    url: 'http://vczero.github.io/ctrip/guo_4.jpg'
  },
  {
    id:'5',
    title: '陕西大荔冬枣',
    desc: '2000g',
    price: 59.9,
    url: 'http://vczero.github.io/ctrip/guo_5.jpg'
  },
  {
    id:'6',
    title: '南非红心西柚',
    desc: '2500g',
    price: 29.9,
    url: 'http://vczero.github.io/ctrip/guo_6.jpg'
  }
];

2.2 列表项组件
用于渲染商品的图片和名称

//TouchableOpacity:透明触摸。用户点击时,点击的组件会出现透明效果。
//resizeMode="contain" : 图片缩放模型,"contain"自适应所在容器模式
//这里press点击事件、url、title都由父组件List传递过来

var Item = React.createClass({
  render: function(){
    return(
      <View style={styles.item}>
        <TouchableOpacity onPress={this.props.press}>
          <Image 
              resizeMode="contain" 
              style={styles.img}
              source={{uri:this.props.url}}>
            <Text numberOfLines={1} style={styles.item_text}>{this.props.title}</Text>
          </Image>
        </TouchableOpacity>
      </View>
    );
  }
});

2.3 列表组件

var List = React.createClass({
  getInitialState: function(){
    return{
      count:0
    };
  },
  //在组件第一次绘制之后,会调用 componentDidMount() ,通知组件已经加载完成。
  componentDidMount: function(){
    var _that = this;
    AsyncStorage.getAllKeys(function(err, keys){
      if(err){
        //TODO:存储取数据出错
      }
      //将存储的商品条数反应到按钮上
      _that.setState({
        count: keys.length
      });
    });
  },
  render: function() {
    var list = [];
    for(var i in Model){
      if(i % 2 === 0){
        var row = (
          <View style={styles.row}>
            <Item url={Model[i].url} 
              title={Model[i].title} 
              press={this.press.bind(this, Model[i])}></Item>
            <Item 
              url={Model[parseInt(i)+1].url} 
              title={Model[parseInt(i)+1].title} 
              press={this.press.bind(this, Model[parseInt(i)+1])}></Item>
          </View>);
        list.push(row); //类似OC的数组addObject
      }
    }

    var count = this.state.count;
    var str = null;
    if(count){
      str = ',共'+ count + '件商品';
    }
    return (
      <ScrollView style={{marginTop:10}}>
        {list}
        <Text onPress={this.goGouWu} style={styles.btn}>去结算{str}</Text>
      </ScrollView>
    );
  },
  goGouWu: function(){
    this.props.navigator.push({
      component: GouWu,
      title:'购物车'
    });
  },
  press:function(data){
    var count = this.state.count;
    count ++;
    //改变数字状态
    this.setState({
      count: count
    });
    //AsyncStorage存储
    AsyncStorage.setItem('SP-' + this.genId() + '-SP', JSON.stringify(data), function(err){
      if(err){
        //TODO:存储出错
      }
    });
  },
  //生成随机ID:GUID
  genId:function(){
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random() * 16 | 0,
          v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
      }).toUpperCase();
  }
});

2.4 购物车组件
购物车页面

var GouWu = React.createClass({
  getInitialState: function(){
    return {
      data: [],
      price: 0
    };
  },
  render: function(){
    var data = this.state.data;
    var price = this.state.price;
    var list = [];
    for(var i in data){
      price += parseFloat(data[i].price);
      list.push(
        <View style={[styles.row, styles.list_item]}>
          <Text style={styles.list_item_desc}>
            {data[i].title}
            {data[i].desc}
          </Text>
          <Text style={styles.list_item_price}>¥{data[i].price}</Text>
        </View>
      );
    }
    var str = null;
    if(price){
      str = ',共' + price.toFixed(1) + '元';
    }
    return(
      <ScrollView style={{marginTop:10}}>
        {list}
        <Text style={styles.btn}>支付{str}</Text>
        <Text style={styles.clear} onPress={this.clearStorage}>清空购物车</Text>
      </ScrollView>
    );
  },
  componentDidMount: function(){
    var _that = this;
    AsyncStorage.getAllKeys(function(err, keys){
      if(err){
        //TODO:存储取数据出错
        //如果发生错误,这里直接返回(return)防止进入下面的逻辑
      }
      AsyncStorage.multiGet(keys, function(errs, result){
        //TODO:错误处理
        //得到的结果是二维数组
        //result[i][0]表示我们存储的键,result[i][1]表示我们存储的值
        var arr = [];
        for(var i in result){
          arr.push(JSON.parse(result[i][1]));
        }
        _that.setState({
          data: arr
        });
      });
      
    });
  },
  clearStorage: function(){
    var _that = this;
    AsyncStorage.clear(function(err){
      if(!err){
        _that.setState({
          data:[],
          price: 0
        });
        alert('购物车已经清空');
      }
      //TODO:ERR
    });
  }
});

2.5 完整的功能

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
  NavigatorIOS,
  ScrollView,
  AsyncStorage,
  TouchableOpacity,
} = React;

var Model = [...];
var Item = React.createClass({...});
var List = React.createClass({...});
var GouWu = React.createClass({...});

var App = React.createClass({
  render: function() {
    return (
      <NavigatorIOS
        style={styles.container}
        initialRoute={
          {
            component: List,
            title: '水果列表'
          }
        }/>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  row:{
    flexDirection: 'row',
    marginBottom: 10,
  },
  item:{
    flex:1,
    marginLeft:5,
    borderWidth:1,
    borderColor:'#ddd',
    marginRight:5,
    height:100,
  }, 
  img:{
    flex:1,
    backgroundColor: 'transparent'
  },
  item_text:{
    backgroundColor: '#000',
    opacity: 0.7,
    color:'#fff',
    height:25,
    lineHeight:18,
    textAlign:'center',
    marginTop:74
  },
  btn:{
    backgroundColor:'#FF7200',
    height:33,
    textAlign:'center',
    color:'#fff',
    marginLeft:10,
    marginRight:10,
    lineHeight:24,
    marginTop:40,
    fontSize:18,
  },
  list_item:{
    marginLeft:5,
    marginRight:5,
    padding:5,
    borderWidth:1,
    height:30,
    borderRadius:3,
    borderColor:'#ddd'
  },
  list_item_desc:{
    flex:2,
    fontSize:15
  },
  list_item_price:{
    flex:1, 
    textAlign:'right',
    fontSize:15
  },
  clear:{
    marginTop:10,
    backgroundColor:'#FFF',
    color:'#000',
    borderWidth:1,
    borderColor:'#ddd',
    marginLeft:10,
    marginRight:10,
    lineHeight:24,
    height:33,
    fontSize:18,
    textAlign:'center',
  }
});

AppRegistry.registerComponent('App', () => App);

效果如下:

40678F6D-64FD-4F56-B96A-F7827CB78053.png

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

推荐阅读更多精彩内容