架构-reactnative笔记

本文详细介绍了ReactNative的环境搭建步骤,包括iOS和Android的开发环境需求。接着讲解了flex布局的基本概念和注意事项,以及如何获取屏幕尺寸。此外,还探讨了ReactNative中的常用组件如View、TextInput、TouchableOpacity、ScrollView和ListView的使用方法,以及事件处理和导航组件Navigator的基本应用。最后提到了组件state和prop的管理,以及如何进行平台适配和使用第三方库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.React Native环境搭建
    1)下载node和Homebrew
    2)安装watchman和flow
    3)安装React Native
        npm i react-native-cli -g
        react-native init 项目名称
    4)ios开发环境需求
        xcode7以上版本
    5)安卓开发环境需求
        安装最新版本的JDK

2.flex布局
    根标签和view标签默认开启flex布局,主轴方向默认是竖向,html中默认是横向
    flexDirection:主轴方向
        'row':横向
        'column':竖向,默认值
    注意点:
        开启flex:wrap,要去关掉flex:1,否则会出现换行bug,看不见第二行以下的内容
        
3.获取屏幕宽高和屏幕像素
    var Dimensions = require('Dimensions');
    var {width, height, scale} = Dimensions.get('window');
    Dimensions.get('window').width
    Dimensions.get('window').height
    Dimensions.get('window').scale
    
4.组件
    view:内部只能放标签不能放文本,文本必须放在text标签中
    WebView:渲染html代码
        source={{html: this.state.detailData}}:html跟字符串,uri跟链接
    Image:图片
        source={require('./img/icon.png')} //引入资源
        resizeMode:内容展示形式,比如contain、cover等,图片的大小不受宽高影响,需要设置resizeMode才行
    TextInput:输入框
        value:默认值
        keyboardType:键盘类型
        multiline:是否支持多行输入
        password:密码,设置multiline时不起效果
        placeholder:占位符
        clearButtonMode:清除按钮的出现时机
        css属性:
            borderWidth: 边框框
            borderColor: 边框颜色
            textAlign:'center' // 内容居中
    TouchableOpacity:让内部元素可以点击和触摸,并且有视觉效果
        <TouchableOpacity
            activeOpacity={0.5} // 透明度从0.5到1过渡
            onPress={this.activeEvent('点击')} 
            onPressIn={()=>this.activeEvent('按下')}
            onPressOut={()=>this.activeEvent('抬起')}
            onLongPress={()=>this.activeEvent('长按')}
            >
            <View style={styles.innerViewStyle}>
              <Text ref="event">常用的事件</Text>
            </View>
        </TouchableOpacity>
    ScrollView:内部元素可以滚动,ScrollView必须有一定高度才能正常工作,一般不建议直接给ScrollView设置高度,而是给其父级元素设置固定高度
               ScrollView内部其它响应者无法阻止ScrollView本身作为响应者(ScrollView嵌套ScrollView,可能只有外层ScrollView有效果,可以嵌套listView)
        horizontal:设置为true时,内部的元素水平排列
        showsHorizontalScrollIndicator:设置为false时,隐藏水平滚动条
        pagingEnabled:设置为true时,内部元素会有分页效果,每次滚动时会像轮播图一样一次滚动一屏幕
        scrollEnabled:设置为true时,内部元素可以滚动
        onMomentumScrollEnd:滚动结束时触发回调
        scrollResponderScrollTo({x:offsetX, y:0, animated:true}):设置滚动位置,animated开启动画
        onScrollBeginDrag:开始拖拽
        onScrollEndDrag:停止拖拽
        contentInset = {{top: -200}}:渲染是内容相对于ScrollView顶部的偏移位置,ios适用
        contentOffset = {{y:200}}:橡皮筋向下拉长的最大范围,ios适用
        scrollEnabled:是否可以滚动,true可以,false不可以
    ListView:与ScrollView类似,ScrollView的所有属性都可以使用,内部做了一些优化
        contentContainerStyle:放ListView的样式
        1)只渲染一组数据
            // 设置初始值
            getInitialState(){
              // Wine是个数组,Wine的每一项会放到rowHasChanged中,(r1, r2) => r1 !== r2}过滤掉相同项
              var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
              return{
                 dataSource: ds.cloneWithRows(Wine)
              }
            },
            <ListView
                 dataSource={this.state.dataSource}  // 数据源
                 renderRow={this.renderRow}
            />
            // 遍历每一项,放回dom放到ListView中
            // sectionID组id
            // rowID索引
            renderRow(rowData,sectionID,rowID){
                   return()
            }
        2)渲染多组数据    
            1.渲染的数据
                var Car = {
                    "data": [
                        {
                          "cars": [
                            {
                              "icon": "m_180_100.png",
                              "name": "AC Schnitzer"
                            },
                          ],
                          "title": "A"
                        },
                        {
                          "cars": [
                            {
                              "icon": "m_180_100.png",
                              "name": "AC Schnitzer"
                            },
                          ],
                          "title": "B"
                        }
                    ]
                }
            2.初始化我们要渲染的数据,固定写法
                // 初始化函数
               getInitialState(){            
                  var  getSectionData = (dataBlob, sectionID) => {
                      return dataBlob[sectionID];
                  };
            
                  var  getRowData = (dataBlob, sectionID, rowID) => {
                      return dataBlob[sectionID + ':' + rowID];
                  };            
                   return{
                       dataSource: new ListView.DataSource({
                           getSectionData: getSectionData, // 获取组中数据
                           getRowData: getRowData, // 获取行中的数据
                           rowHasChanged: (r1, r2) => r1 !== r2, // 组中相同行不渲染
                           sectionHeaderHasChanged:(s1, s2) => s1 !== s2 // 相同组不渲染
                       })
                   }            
               },
           3.得到我们需要渲染的数据格式(多组内置吸顶功能,就是展示在可视区的组标题会固定在listView顶部)
               componentDidMount(){
                   // 调用json数据
                   this.loadDataFromJson();
               },        
               loadDataFromJson(){
                  // 拿到json数据
                   var jsonData = Car.data;            
                  // 定义一些变量
                   var dataBlob = {},
                       sectionIDs = [],
                       rowIDs = [],
                       cars = [];            
                  // 遍历
                   for(var i=0; i<jsonData.length; i++){
                       // 1. 把组号放入sectionIDs数组中
                       sectionIDs.push(i);            
                       // 2.把组中内容放入dataBlob对象中
                       dataBlob[i] = jsonData[i].title            
                       // 3. 取出该组中所有的车
                       cars = jsonData[i].cars;
                       rowIDs[i] = [];            
                       // 4. 遍历所有的车数组
                       for(var j=0; j<cars.length; j++){
                           // 把行号放入rowIDs
                           rowIDs[i].push(j);
                           // 把每一行中的内容放入dataBlob对象中
                           dataBlob[i+':'+j] = cars[j];
                       }
                   }            
                   // 更新状态
                   this.setState({
                       dataSource: this.state.dataSource.cloneWithRowsAndSections(dataBlob,sectionIDs,rowIDs)
                   });            
               },
               4.dataBlob,sectionIDs,rowIDs对应的数据格式
                   dataBlob = {
                       'sectionID1':第一组标题内容如titleA,
                       'sectionID2':第二组标题内容如titleB,
                       ...
                       'sectionID1:rowID1':第一组第一行内容如titleA,
                       'sectionID1:rowID2':第一组第二行内容如titleA,
                       ...
                       'sectionID2:rowID1':第二组第一行内容如titleA,
                       'sectionID2:rowID2':第二组第二行内容如titleA,
                       ...
                   }
                   //放每组id
                   sectionIDs=[sectionID1,sectionID2,...]
                   //每个数组放每组每行id
                   rowIDs=[[rowIDs1,rowIDs2,...],[rowIDs1,rowIDs2,...]]
               5.页面结构
                   <ListView
                   dataSource={this.state.dataSource}
                   renderRow={this.renderRow} // 渲染每行的数据有参数rowData(行数据),sectionID(组id),rowID(行id)
                   renderSectionHeader={this.renderSectionHeader} // 渲染每组的数据有参数sectionData(组数据),sectionID(组id)
               />
    TabBarIOS:底部导航,只在ios中有效,项目中会使用第三方库兼容安卓和ios,TabBarIOS.Item每项
        <TabBarIOS
            barTintColor='orange' //背景颜色
            tintColor = 'purple'  //选中项颜色
        >
            {/*第一块*/}
            <TabBarIOS.Item
                systemIcon="downloads"  // 系统提供图标和图标标题
                icon="xxx" //自定义图标,systemIcon图标优先级更高
                title="张三" //自定义图标标题,systemIcon图标标题优先级更高
                badge="3" //图标右上方小红色气泡内容
                selected={this.state.selectedTabBarItem == 'home'} // true表示被选中,false相反
                onPress = {()=>{this.setState({selectedTabBarItem: 'home'})}} // 点击事件
            >
                // 选中时展示的内容,View的样式会加到TabBarIOS结构所占的位置
               <View style={[styles.commonViewStyle,{backgroundColor:'red'}]}>
                   <Text>首页</Text>
               </View>
            </TabBarIOS.Item>
        </TabBarIOS>
    NavigatorIOS:头部导航,只在ios中有效
        <NavigatorIOS
            // 初始化路由内容
           initialRoute = {
              {
                component: Home, // 路由
                title:'网易', // 标题
                passProps:{}, //传递的参数
                leftButtonIcon:require('image!navigationbar_friendattention'), //左图标
                rightButtonIcon:require('image!navigationbar_pop'), //右图标
                tintColor = "orange", //左右图标颜色
              }
           }
           />
    Navigator:Navigator与NavigatorIOS一样都是用来做路由切换的,Navigator在ios和安卓都兼容,NavigatorIOS在加载路由时自带头部导航,Navigator需要自己写
        <Navigator
            initialRoute={{name:'首页',component:Home}} // 路由信息
            configureScene={()=>{
                 return Navigator.SceneConfigs.PushFromRight; // 路由进来的动画形式,PushFromRight从左到右
            }}
            renderScene={(route,navigator)=>{ // 渲染路由
               let Component = route.component;
               return <Component {...route.passProps} navigator={navigator}/>;
            }}
        />       
5.一份代码在ios和安卓上运行
    1)创建一个js文件
        import React, { Component } from 'react';
        class loginView extends Component {
            render(){}
        }
        const styles = StyleSheet.create({})
        module.exports = loginView;
    2)index.ios.js和index.android.js文件中
        import React, { Component } from 'react';
        import {
            AppRegistry,
        } from 'react-native';
        // 引入外部的js文件
        var LoginView = require('./loginView');
        class BTextInputDemo extends Component {
          render() {
            return (
               <LoginView />
            );
          }
        }
        AppRegistry.registerComponent('BTextInputDemo', () => BTextInputDemo);
        
6.适配
    var Dimensions = require('Dimensions');
    var {width,height} = Dimensions.get('window');
    loginBtnStyle:{
        width:width*0.9,
    }
    
7.组件state和prop属性
    1)es5定义
        import React, { Component } from 'react';
        var DTouchabelDemo = React.createClass({
          // 定义prop属性
          getDefaultProps(){
             return{
                age: 18
             }
          },
          propTypes:{
              age:React.PropTypes.string // 定义prop属性类型
          },
         // 定义state,this.setState()更新state
          getInitialState(){
             return{
               title:'不透明触摸',
             }
          },        
          render() {
            return (
                <View ref="topView" style={styles.container}>
                  <View>
                      <Text>{this.state.title}</Text>
                      <Text>{this.props.age}</Text>
                  </View>
                </View>
            );
          },
        });
    2)es6定义                                        
        class BTextInputDemo extends Component {
          constructor(props){
              super(props)
              // 现在可能可以在constructor外面定义
              this.state = {
               title:'不透明触摸',
            }
          }
          render() {
            return (
               <View>
                     // 获取
                  <Text>{this.state.title}</Text>
                  </View>
            );
          }
        }
        // es6定义prop属性是定义在类外面,现在可能可以定义在类里面了
        BTextInputDemo.defaultProps={title:'不透明触摸'}
        BTextInputDemo.propTypes={
              title:React.PropTypes.string // 定义prop属性类型
        },
7.组件prop属性
    class BTextInputDemo extends Component {
      // prop的值不可以改变
      getDefaultProps(){
         return{
            age: 18
         }
      },
      render() {
        return (
           <View>
                 // 获取
              <Text>{this.props.age}</Text>
              </View>
        );
      }
    }

8.事件
    onPress:点击
    onPressIn:按下
    onPressOut:抬起
    onLongPress:长按
    
9.创建组件
    1)es5方式
        import React, { Component } from 'react';
        var DTouchabelDemo = React.createClass({
          // 不可改变的值
          getDefaultProps(){
             return{
                age: 18
             }
          },
          render() {
            return (
                <View ref="topView" style={styles.container}>
                </View>
            );
          }
        });
    2)es6方式
        import React, { Component } from 'react';
        import {
            AppRegistry,
        } from 'react-native';
        // 引入外部的js文件
        var LoginView = require('./loginView');
        class BTextInputDemo extends Component {
          render() {
            return (
               <LoginView />
            );
          }
        }
        AppRegistry.registerComponent('BTextInputDemo', () => BTextInputDemo);
        
10)获取真实的dom
    // 获取this.refs.event
    <Text ref="event">常用的事件</Text>
    
11)使用第三方库
    npm i react-timer-mixin
    // 引入计时器类库
    var TimerMixin = require('react-timer-mixin');
    var FScrollViewDemo1 = React.createClass({
        // 注册计时器
        mixins: [TimerMixin]
    })
    
12)放多个样式
    <Text key={i} style={[{fontSize:25},{fontSize:25}]}></Text>
    
13)事件对象
    onAnimationEnd(e){
      // e.nativeEvent为事件对象
      // 求出水平方向的偏移量
      var offSetX = e.nativeEvent.contentOffset.x;
   }
   
14)路由
    // 跳转到下一个路由
    // 要和Navigator组件一起使用,参数就是Navigator组件的initialRoute
    // 使用Navigator父组件将navigator对象传下去,才能继续调用路由api,调用api跳转的路由不需要在向下传navigator对象
    <Navigator
        initialRoute={{name:'首页',component:Home}} // 路由信息
        configureScene={()=>{
             return Navigator.SceneConfigs.PushFromRight; // 路由进来的动画形式,PushFromRight从左到右
        }}
        renderScene={(route,navigator)=>{ // 渲染路由
           let Component = route.component;
           return <Component {...route.passProps} navigator={navigator}/>;
        }}
    />  
    this.props.navigator.push({
        component: NewsDetail, //组件
        title: rowData.title, // 标题
        passProps:{rowData}  // 参数,this.props.rowData拿到参数
    })
    this.props.navigator.pop():返回
    this.props.navigator.replace():替代

15)电商实战
    1.使用react-native-tab-navigator库完成兼容ios和安卓的底部导航功能(就是TabBarIOS组件)
    2.使用react-native-tab-navigator库和Navigator实现底部路由切换和头部
    3.完成更多、我的、首页、商家功能


    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值