美文网首页
3.写一个页面

3.写一个页面

作者: 炒鸡范 | 来源:发表于2016-10-29 22:58 被阅读101次

前言

我的天终于接到一个面试通知,内牛满面。

一、今日计划

我觉得光看不练可不行。今天我们就用前两天学到的知识实操一个页面出来。加油!

二、开始!

1.目标:写一个简单的RN页面,接到原生的iOS项目中,并使用原生的某个类完成某些操作。

我在网上找到一个免费的api微信热门精选,我们就来写一个获取微信热门精选的页面,具备网络请求,下拉刷新的列表页面。

2.封装网络类!

我寻思什么类能用原生写,然后RN用,想来想去这个小项目也就网络类放在原生写比较靠谱,技术不达标的情况下贸然使用JS的Fetch来写我是慌慌的下不了手。
新建一个NetWork

#import <Foundation/Foundation.h>

@interface Network : NSObject

@end
//
//  Network.m
//  RNTest
//
//  Created by fanfangliang on 16/10/29.
//  Copyright © 2016年 fanfangliang. All rights reserved.
//

#import "Network.h"
#import <AFNetworking/AFNetworking.h>//这里我们用AFN
#import "RCTBridgeModule.h"//记得import这个

//然后遵循RCTBridgeModule协议
@interface Network ()<RCTBridgeModule>

@end

@implementation Network

//加上这个宏
RCT_EXPORT_MODULE();

#pragma mark - RN method
//获取微信热门精选 暴露给RN的接口 接受一个param{@"num":@(1),@"page":@(10)} 然后回调callback
RCT_EXPORT_METHOD(wxListWithParam:(NSDictionary *)param Callback:(RCTResponseSenderBlock)callback)
{
    [[Network sharedInstance] getFromUrl:@"http://apis.baidu.com/txapi/weixin/wxhot" params:param callback:^(NSDictionary *dicResponse, NSError *error) {
        //这里我们先直接返回dicResponse(假装接口没有问题,有需要的同学加上错误处理)
        callback(@[dicResponse]);
    }];
    
}

//以下是对AFN最基础的调用
#pragma mark - common method

+ (instancetype)sharedInstance
{
    static Network *worker = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        worker = [[Network alloc] init];
    });
    return worker;
}

- (AFHTTPSessionManager *)mgr
{
    static AFHTTPSessionManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [AFHTTPSessionManager manager];
        manager.responseSerializer = [AFJSONResponseSerializer serializer];
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];
        manager.requestSerializer.timeoutInterval = 30.0;
        
        //这里,因为api要求将apikey放在header里,所以需要设置以下,你们可以改成自己的key
        [manager.requestSerializer setValue:@"4ff218a1fd6*********984497d8" forHTTPHeaderField:@"apikey"];
    });
    return manager;
}

- (NSURLSessionDataTask *)getFromUrl:(NSString *)url params:(NSDictionary *)params callback:(void (^)(NSDictionary* dicResponse, NSError* error))callback
{
    
    return [self.mgr GET:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        callback(responseObject,nil);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        callback(nil,error);
    }];
}

- (NSURLSessionDataTask *)postFromUrl:(NSString *)url params:(NSDictionary *)params callback:(void (^)(NSDictionary* dicResponse, NSError* error))callback
{
    return [self.mgr POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        callback(responseObject,nil);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        callback(nil,error);
    }];
}

@end

3.viewcontroller其实和昨天一样,我就改了个模块名称

//
//  ViewController.m
//  RNTest
//
//  Created by fanfangliang on 16/10/28.
//  Copyright © 2016年 fanfangliang. All rights reserved.
//

#import "ViewController.h"
#import "RCTRootView.h"
#import "Network.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (IBAction)highScoreButtonPressed:(id)sender {
    NSLog(@"High Score Button Pressed");
    //这里设置了主入口文件的请求路径
    NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios"];
    //RCTRootView是一个UIView
    //传入请求路径、模块名称、初始属性(是一个字典)
    RCTRootView *rootView =
    [[RCTRootView alloc] initWithBundleURL : jsCodeLocation
                         moduleName        : @"Index"
                         initialProperties :nil
                          launchOptions    : nil];
    UIViewController *vc = [[UIViewController alloc] init];
    //然后创建一个控制器,将rootView赋给控制器的view,就能看到
    vc.view = rootView;
    [self presentViewController:vc animated:YES completion:nil];
    
    
    
}

@end

4.Podfile增加这次需要引入的库

 pod 'React', :path => 'node_modules/react-native', :subspecs => [
    'Core',
    'RCTText',
    'RCTNetwork',
    'RCTImage',# 天坑,我以为<Image>标签应该在Core库里,再不济也应该在'RCTImageView'里,结果他叫'RCTImage',浪费我感情
    'RCTWebSocket', # needed for debugging
  ]
  
  pod 'AFNetworking'

end

5.重点来了,index.ios.js

'use strict'

import React from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
  ListView,
  RefreshControl,
  NativeModules,//这里需要引入NativeModules模块
} from 'react-native';

//把一些公有的属性定义下
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});  
var page = 1;
var datas = [];

class Index extends React.Component {

  constructor(props){
    super(props);


    this.state = {
      isRefreshing:false,//这里RefreshControl需要用到isRefreshing,不然会黄条提示,虽然我还不知道它有卵用现在
      dataSource: ds.cloneWithRows([])//这里,是listview的数据源
    };

    
  }

  //当模块被加载的时候,我们请求一把数据
  componentWillMount(){
    this.loadData();
  }


  loadData(){
    console.log('调用Loaddata');
    this.setState({isRefreshing: true});
    //获取到Native的Network类,就是我们上面写的网络请求类
    var Network = NativeModules.Network;
    //调用微信数据接口,传过去{'num':'10','page':String(page)}和回调方法
     Network.wxListWithParam({'num':'10','page':String(page)},(response) => {
        //当获取到数据,page+1
        page = page + 1;
        //把老数据和新数据合并成一个新的数组并存起来
        var newslist = response['newslist'];
        datas = newslist.concat(datas);
        //设置state,主要是改datasource.
        this.setState({isRefreshing: false,dataSource:ds.cloneWithRows(datas)});
    });
  }

  render() {
    return (
      <View style = {styles.main}>

        <View style = {styles.navBar}>
          <Text style = {styles.titleView} onPress={this.loadData}>微信热门精选</Text>
        </View>

        <ListView
          enableEmptySections = {true}
          style={styles.listView}
          dataSource={this.state.dataSource}
          renderRow={this.renderRow.bind(this)}
          refreshControl={
            //RefreshControl是一个新控件
            <RefreshControl
              refreshing={this.state.isRefreshing}
              onRefresh={this._onrefresh.bind(this)}//当下拉刷新的时候,去调用_onrefresh方法。这里需要bind(this)坑了我半天,具体原因我觉得我要再回去看看JS语法,先不误导你们了
              tintColor="#ff0000"
              title="Loading..."
              titleColor="#00ff00"
              colors={['#ff0000', '#00ff00', '#0000ff']}
              progressBackgroundColor="#ffff00"
            />
          }
        />

      </View>
    );
  }

  //这里去刷新
  _onrefresh(){
    console.log('下拉');
    this.loadData();
  }

  //这里是把数据赋给视图,就像我们把数据赋给cell一样
  renderRow(rowData){
    return(
      <View style={styles.cell}>
        <Image source={{uri: rowData['picUrl']}}
                style={styles.imageview} />

        <View style={styles.textArea}>
          <Text style={styles.titleText}>{rowData['title']}</Text>
          <Text style={styles.timeText}>{rowData['ctime']}</Text>
        </View>
        
      </View>
      );
  }
}

const styles = StyleSheet.create({
  main:{
    flex:1,
    backgroundColor:'white'
  },
  navBar:{
    backgroundColor:'gray',
    height:64,
  },
  titleView:{
    marginTop:32,
    textAlign:'center',
    fontSize:20,
    color:'white'
  },
  listView:{
    backgroundColor:'green',
  },
  cell:{
    height:60,
    backgroundColor:'white',
    marginBottom:0.5,
    flexDirection:'row'
  },
  imageview:{
      marginTop:10,
      marginLeft:10,
      width:40,
      height:40,
      backgroundColor:'yellow'
  },
  textArea:{
    marginTop:10,
    marginLeft:10,
    height:40,
    flexDirection:'column',
    justifyContent:'space-between',
  },
  titleText:{
    fontWeight:'bold'
  },
  timeText:{
    color:'darkgray'
  }

});


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

最后秀下成果:

Simulator Screen Shot 2016年10月29日 下午10.57.45.png

丑是丑点,勿喷勿喷啦

相关文章

  • 3.写一个页面

    前言 我的天终于接到一个面试通知,内牛满面。 一、今日计划 我觉得光看不练可不行。今天我们就用前两天学到的知识实操...

  • VUE重复

    1.写一个index.html页面 2.改变页面内容 3.实现todolist 4.MVVM模式 5.TodoLi...

  • 新建项目的流程

    1.在app-router.js中配置页面路由2.在frontend-conpents里面写页面3.在fronte...

  • jQuery弹出层插件--lightbox

    1.: 在页面引入如下文件: 2.编写页面html代码,在body中写入如下代码: 3.: 开始写jquery代...

  • 鸿蒙第9课动画效果(2)

    1.在主页面上设置一个照片得id 高宽,大小缩放模板 2.在效果栏里写入照片路径和显示秒数 3.在切片页面写代码 ...

  • ios-委托代理详细步骤

    【第二个页面】1在第二个页面写协议,写在interface 上面 2.在第二个页面 实例化协议的变量 3.让协议变...

  • 2020-06-09面试名锐讯动

    前言:(外包)需要机试,写静态页面。一个官网面试官选取一个模块写。我写的类似下面页面 问题1:vue和小程序页面传...

  • Flutter 3. 页面布局

    Flutter中布局组件众多,大致有: Align: 对齐布局组件,指定child的对齐方式 AspectRati...

  • 微信小程序写简单登录界面

    1.页面布局 2.页面样式 3.页面JS 4.效果图

  • php写数据进入数据库操作实例

    1.先在数据库里面建表 确定字段 2.可以输入几个数据 3.写页面 4.拿到数据 写入数据库 5.页面显示

网友评论

      本文标题:3.写一个页面

      本文链接:https://www.haomeiwen.com/subject/mgcyuttx.html