react native目录结构解析
工图初始结构如下:
- android:一个完整的,集成react native的android studio工程,用android studio打开运行可以跑到手机或者模拟器上。
- ios:一个完整的ios项目,在Mac下可以直接用xcode打开。运行到模拟器或者手机上
- node_moules:基于node文件依赖系统产生的相关依赖和第三方lib,里面有react native的大部分组件
- watchmanconfig:Watchman的配置文件,Watchman用于监控文件变化
- flowconfig:flow的配置文件,flow用于静态代码检查
- buckconfig:buck的配置文件,buck是Facebook开源的高效编译系统
- App.js:Android和iOS的应用程序入口
- package.json:项目基本信息以及依赖信息
- index.js :app的注入
App.js内容解析
App.js
App.js作为整个程序入口,里面的代码含义相当于Android的
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
//引入 React的抽象组件
import React, {Component} from 'react';
// 引入React具体的组件,比如image,text等
import {AppRegistry, Platform, StyleSheet, Text, View} from 'react-native';
import {name as appName} from "./app";
// 下面根据平台的api展示不同的文字
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
type Props = {};
// 这个class 最终是在index.js中调用了AppRegistry.registerComponent(appName, () => App);注入了才得以显示,类似android的setContentView()
export default class App extends Component<Props> {
// 初始化方法 ---> viewDidLoad ---> 返回具体的组件内容
// 写结构和内容
render() {
// 返回一个View
return (
<View style={styles.container}>
<Text style={styles.welcome}>这是第一次运行成功</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<Text style={styles.instructions}>{instructions}</Text>
</View>
);
}
}
// View组件的样式
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
index.js文件:
/** @format */
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
// App 这个在App.js中定义,等同于之前版本的AppRegistry.registerComponent('untitled1', () => App);
AppRegistry.registerComponent(appName, () => App);
组件View
JSX的由来
React的核心机制之一就是虚拟DOM:可以在内存中创建的虚拟DOM元素。React利用虚拟DOM来减少对实际DOM的操作从而提升性能。传统的创建方式是:
但这样的代码可读性并不好,于是React发明了JSX,利用我们熟悉的HTML语法来创建虚拟DOM:
<View style={styles.container}>
<Text style={styles.welcome}>这是第一次运行成功</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<Text style={styles.instructions}>{instructions}</Text>
</View>
在实际开发中,JSX在产品打包阶段都已经编译成纯JavaScript,JSX的语法不会带来任何性能影响。因此,JSX本身并不是什么高深的技术,可以说只是一个比较高级但很直观的语法糖。
View组件用法
React Native组件View,其作用等同于iOS中的UIView, Android中的android.view,或是网页中的<div>标签,它是所有组件的父组件。下面是具体的用法和需要注意的事项:
// 在下面写注释,必须要 {/* xxxxx */}这么写
export default class App extends Component{
render() {
return (
<View style={styles.container}>
{/* View组件中必须有东西才可以显示 */}
<View style={styles.innerViewStyle}>
<Text>我是里面的View</Text>
</View>
<View style={styles.innerViewStyle2}>
<Text>我是里面下面的View</Text>
</View>
</View>
);
}
}
// 在React Native开发中,更加推荐我们采用StyleSheet来进行组件的布局,这样的话,代码在结构上会更加的清晰、也有利于后期维护。
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ffffff',
padding: 30
},
innerViewStyle:{
backgroundColor:'green',
width:100
},
innerViewStyle2:{
backgroundColor:'yellow',
width:100
}
});
FlexBox布局
在Android中我们有许多的布局,比如线性布局,相对布局等,在react native中FlexBox布局是用的最频繁的,含义是能够伸缩或者很容易变化,以适应外界条件的变化的通用的矩形容器。简称“弹性布局”,旨在通过弹性的方式来对齐和分布容器中内容的空间,使其能适应不同屏幕,为盒装模型提供最大的灵活性。说了那么多就是集合Android线性布局和相对布局等其他布局的一些特征的布局。
Flexbox的排列
- 在CSS中,常规的布局是基于块和内联流方向,而Flex布局是基于flex-flow流,下图很好解释了Flex布局的思想:
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。项目默认沿主轴排列,单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。
- 根据伸缩项目排列方式的不同,主轴和侧轴方向也有所变化:
FlexBox常用属性
容器属性
- flexDirection:
row | row-reverse | column | column-reverse
该属性决定主轴的方向(即项目的排列方向)。
row:主轴为水平方向,起点在左端。
row-reverse:主轴为水平方向,起点在右端。
column(默认值):主轴为垂直方向,起点在上沿。
column-reverse:主轴为垂直方向,起点在下沿。
export default class App extends Component{
render() {
return (
<View style={styles.container}>
{/* View组件中必须有东西才可以显示 */}
<View style={styles.innerViewStyle}>
<Text>我是里面的View</Text>
</View>
<View style={styles.innerViewStyle2}>
<Text>我是中间的View</Text>
</View>
<View style={styles.innerViewStyle3}>
<Text>我是里面下面的View</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ffffff',
padding: 30,
flexDirection: 'row' // 横向
},
innerViewStyle:{
backgroundColor:'green',
width:100
},
innerViewStyle2:{
backgroundColor:'yellow',
width:100
},
innerViewStyle3:{
backgroundColor:'red',
width:100
}
});
- justifyContent:
flex-start | flex-end | center | space-between | space-around
定义了伸缩项目在主轴线的对齐方式
flex-start(默认值):伸缩项目向一行的起始位置靠齐。
flex-end:伸缩项目向一行的结束位置靠齐。
center:伸缩项目向一行的中间位置靠齐。
space-between:两端对齐,项目之间的间隔都相等。
space-around:伸缩项目会平均地分布在行里,两端保留一半的空间
- alignItems:
flex-start | flex-end | center | baseline | stretch
定义项目在交叉轴上如何对齐,可以把其想像成侧轴(垂直于主轴)的“对齐方式”。
flex-start:交叉轴的起点对齐。
flex-end:交叉轴的终点对齐 。
center:交叉轴的中点对齐。
baseline:项目的第一行文字的基线对齐。
stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
- flexWrap:
nowrap | wrap | wrap-reverse
默认情况下,项目都排在一条线(又称"轴线")上。flex-wrap属性定义,如果一条轴线排不下,如何换行。
nowrap(默认值):不换行。
wrap:换行,第一行在上方。
wrap-reverse:换行,第一行在下方。(和wrap相反)
元素属性
- flex
“flex-grow”、“flex-shrink”和“flex-basis”三个属性的缩写, 其中第二个和第三个参数(flex-shrink、flex-basis)是可选参数。
默认值为“0 1 auto”。
宽度 = 弹性宽度 * ( flexGrow / sum( flexGorw ) )
类似Android中的权重
const styles = StyleSheet.create({
container: {
backgroundColor: '#ffffff',
padding: 30,
flexDirection: 'row', // 横向
justifyContent: 'flex-start',
alignItems: 'center',
},
innerViewStyle:{
backgroundColor:'green',
flex: 1
},
innerViewStyle2:{
backgroundColor:'yellow',
flex: 1
},
innerViewStyle3:{
backgroundColor:'red',
flex: 1
}
});
-
align-self属性
align-self属性允许单个项目有与其他项目不一样的侧轴对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
其值除auto外,其他与align-items完全一致。
获取屏幕相关参数
获取当前屏幕的宽度、高度、分辨率
// 引入
var Dimensions = require('Dimensions');
var {width, height, scale} = Dimensions.get('window');
class CFlexBoxDemo3 extends Component {
render() {
return (
<View style={styles3.outViewStyle}>
<Text>当前屏幕的宽度:{Dimensions.get('window').width}</Text>
<Text>当前屏幕的高度:{Dimensions.get('window').height}</Text>
<Text>当前屏幕的分辨率:{Dimensions.get('window').scale}</Text>
</View>
);
}
};
const styles3 = StyleSheet.create({
outViewStyle:{
// 占满屏幕
flex:1,
// 主轴方向居中
justifyContent:'center',
// 侧轴方向居中
alignItems: 'center',
// 背景
backgroundColor:'red'
}
});
绝对定位和相对定位
class CFlexBoxDemo4 extends Component {
render() {
return (
<View style={styles4.outViewStyle}>
<Text>绝对定位</Text>
<View style={styles4.topViewStyle}>
<View style={styles4.innerViewStyle}></View>
</View>
<Text>相对定位</Text>
<View style={styles4.topViewStyle}>
<View style={styles4.innerViewStyle1}></View>
</View>
</View>
);
}
};
const styles4 = StyleSheet.create({
outViewStyle:{
marginTop:20,
width:width,
height:200,
backgroundColor:'red'
},
topViewStyle:{
width:width,
height:150,
backgroundColor:'yellow'
},
innerViewStyle:{
width:60,
height:60,
backgroundColor:'green',
// 绝对定位
position:'absolute',
top:0,
right:0
},
innerViewStyle1:{
width:60,
height:60,
backgroundColor:'green',
// 相对定位
position:'relative',
top:30,
right:-30
}
});
通常情况下设置position和absolute,定位的效果是一样的,但是如果父组件设置了内边距,position会做出相应的定位改变,而absolute则不会。flex的元素如果不设置宽度, 都会百分之百的占满父容器。
- 水平垂直居中
export default class App extends Component {
render() {
return (
<View style={styles.container}>
{/* 水平居中 */}
<View style={{height:100, alignItems: 'center'}}>
<Text style={styles.innerViewStyle}>我是里面的View</Text>
</View>
{/* 垂直居中 */}
<View style={{height:100, justifyContent: 'center'}}>
<Text style={styles.innerViewStyle2}>我是中间的View</Text>
</View>
{/* 水平垂直居中 */}
<View style={{height:100, alignItems: 'center', justifyContent: 'center',backgroundColor:'black'}}>
<Text style={styles.innerViewStyle3}>我是里面下面的View</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#ffffff',
},
innerViewStyle: {
backgroundColor: 'green',
height: 30,
width: 100,
},
innerViewStyle2: {
backgroundColor: 'yellow',
height: 30,
width: 100,
},
innerViewStyle3: {
backgroundColor: 'red',
height: 30,
width: 100,
}
});
注意:一旦设置alignItems属性之后,组件的大小包裹随着内容的尺寸;此外水平居中和垂直居中还要结合FlexDirection进行判断。