FBI WARMING:必须会Ract框架,最好会ES6语法,其次是flex弹性布局和请求网络
官方文档:https://reactnative.cn/
本人萌新一天内跟着官方文档学完这基础,现在总结笔记,来带大家超光速学习,
1、安装Node(版本高于8.3)
2、安装JDK(版本必须是1.8)
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
3、安装Python(版本必须是2.x)
4、安装yarn和react-native手脚架(不能用cnpm,有bug)
npm install -g yarn react-native-cli
5、设置yarn的镜像源(以后安装模块就快很多)
yarn config set registry https://registry.npm.taobao.org --global
yarn config set disturl https://npm.taobao.org/dist --global
有兴趣的同学自己安装AS或各种虚拟机,我直接用真机安卓调试的(穷)。
在你想创建项目的地方,shift+鼠标右击,选择‘在此处打开Powershell窗口’,输入:
react-native init hello,hello就是你的项目名
(不同手机系统具体操作不一样,请自行百度哦,但步骤都是几乎相似的)
1、开启开发者模式
2、开启usb调试
3、使用usb数据线连接手机和电脑
4、允许USB安装(有些手机有选项,要打开,要不然等下没有权限在手机上安装项目)
5、在项目下打开终端,输入:react-native run-android
项目在手机跑起来后,摇一摇手机:
1、点击 Enable Hot Reloading
,以后保存代码就会实时更新效果
2、 如果代码里写了console.log,点击 Debug JS Remotely
,电脑会自动打开浏览器,然后按 F12 打开开发者工具栏,然后你就能在控制台看到了
坑:这个刷新是有bug的,有时保存了代码,App也不会立即更新,有时需要使用react-native run-android重新编译
3、 如果你需要非常牛逼的调试方式,请打开:https://github.com/facebook/react-devtools/tree/master/packages/react-devtools ,否则你可以直接跳过看下面内容
打开根目录的App.js,如下图所示写并运行代码
import React, { Component } from 'react';
import { Text, View } from 'react-native';
export default class HelloWorldApp extends Component {
render() {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Hello world!</Text>
</View>
);
}
}
被export default导出的就是根组件
导入组件:import { Text, View } from 'react-native’
坑:接下来你学到的所有组件请自觉在头部这里导入!!!
下面请在render函数的return中写代码,和react一样,只能有一个根组件,常用View组件包裹
学习建议:请把接下来学习的组件当作学习新的html标签,这样比较好受
这货就是div,用法和以前一样
注意:该组件的样式中,使用 elevation
来设置z轴高度,和z-index用法一样
用于显示文本的组件,也支持触摸操作,像div一样占一整行,文本元素只能写在Text中,可以使用换行符
Text是文本布局,不是弹性布局,所以只支持文本样式
<Text>Hello world!{'\n'}</Text>
这货就是img,src 变成 source
导入项目中的静态图片:require里面写你图片相对于这个组件的路径
<Image source={require('./images/1.jpg')}/>
导入远程图片:(IOS只支持https协议的图片,而且必须设置宽高)
<Image source={uri:图片的地址} style={{width: 193, height: 30}}/>
坑1:是 uri
,不是url
坑2:Image里的require 中的路径必须是静态字符串,不能有变量,你可以如下所示拼凑路径
var a = images
var pic = require('./'+a+'/1.jpg')
<Image source={pic}/>
设置背景图片,只需要用Image组件包裹内容就行,这样Image就相当于背景图:
<Image source={require('./images/1.jpg')}>
<Text>123</Text> //Image就相当于以前的div中的url加载背景图的形式
</Image>
支持的图片格式,RN默认支持JPG和PNG,ios还支持GIF、WebP,但安卓却默认不支持这两种格式
打开项目目录下的 android/gradle/build.gradle,按情况添加以下代码
dependencies {
compile 'com.facebook.fresco:animated-gif:0.11.0' //需要GIF动画支持添加本行语句
compile 'com.facebook.fresco:webpsupport:0.11.0' //需要WebP格式支持添加本行语句
compile 'com.facebook.fresco:animated-webp:0.11.0' //需要WebP动画支持添加本行语句
}
resizeMode
:图像显示模式,在组件内当作属性或者在样式内当作样式使用都行,如下所示
<Image source={'./images/1.jpg'} style={{flex:1,width:200, height:100, resizeMode: Image.resizeMode.stretch}} />
有5中模式:cover
、contain
、stretch
、center
和 repeat
cover
(默认):图片比例不变,可能不能完整展示图片,但填满Image
contain
:图片比例不变,完整展示图片,但可能填不满Image
stretch
:图片比例可以变化,完整展示图片,能填满Image
center
:图片比例不变,完整展示图片,但可以填不满Image,图片位于显示区域的中心
repeat
(iOS 独有):用一张或者多张图片来填满整个 Image区域
组件在创建时使用的各种参数来进行设置,这些参数就称为Props
就是组件的属性都在Props中,下面是利用Props传参的例子
在import下面自定义一个叫Greeting的组件
class Greeting extends Component {
render(){
return(
<View style={{alignItems: 'center'}}>
<Text>Hello {this.props.name}!</Text>
</View>
)
}
}
在根组件中使用
<Greeting name='abc'/>
根组件为子组件传入了name这个自定义属性,并赋值abc,子组件通过this.props.name接收到,并在Text内展示出来
需要改变的数据就存在state中,否则就存在props中
与react用法一样,在组件内定义,与render函数同级
state = {
count: 0 //在这定义你需要的数据
}
也有很多教程在构造函数中定义,但没必要这么麻烦
修改state中的数据必须使用setState()方法
this.state.count = 100 //这样直接修改无效
this.setState({ //这样写才对
count : 100
})
setState()是异步方法,你可以使用回调函数
this.setState({count : 100}, () => { /* 你需要的操作... */ })
注意:因为在js中写css,所以样式属性名要使用驼峰式,例如下面例子中的backgroundColor
在style中写样式,传入对象:
<View style={{alignItems: 'center',backgroundColor: 'red'}} />
StyleSheet组件可以让我们把样式定义在外部:
一般常在在最下面定义样式
const styles = StyleSheet.create({
bigBlue: {
color: 'blue',
fontSize: 30
},
red: {
color: 'red'
},
});
导入样式:
<Text style={styles.bigBlue}>just bigBlue</Text>
<Text style={[styles.bigBlue, styles.red]}>bigBlue, then red</Text>
多个样式用数组包裹
注意:为什么有时两个花括号,有时一个?
无论如何绑定属性只有一个花括号,两个花括号是因为在style内写样式时要传入对象
这里就稍微说一下,和react一模一样
指定宽高,尺寸都是没有单位的,表示的是与设备像素密度无关的逻辑像素点(看不懂没关系)
<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
<View style={{width: 100, height: 100, backgroundColor: 'skyblue'}} />
<View style={{width: 150, height: 150, backgroundColor: 'steelblue'}} />
弹性宽高,下面举个例子
<View style={{flex: 1}}>
<View style={{flex: 1, backgroundColor: 'powderblue'}} />
<View style={{flex: 2, backgroundColor: 'skyblue'}} />
<View style={{flex: 3, backgroundColor: 'steelblue'}} />
</View>
RN中是默认flex布局,主轴方向是从上到下,flex的具体知识请百度
Dimensions这个API用于获取设备屏幕的宽高,常用来做安装IOS双系统界面适配
var a = Dimensions.get('window').width; //获取设备宽度
var b = Dimensions.get('window').height; //获取设备高度
这货就是input,onChange变成 onChangeText
,下面是例子:
<TextInput style={{height: 40}} placeholder="请输入" onChangeText={(text) => this.setState({text})} />
可以设置 password
属性为true来变成密码框,默认false
Button:这货就是button,click变成 onPress
,color
设置按钮背景颜色
必须设置 title
,这属性就是设置你的按钮上的文字
常见的触摸事件:onPress
点击、onPressIn
按下、onPressOut
抬起、onLongPress
长按
<Button onPress={() => {alert("a")}} onLongPress={() => {alert("b")}} title="点我" color="#841584" />
<Button>123</Button> //这样写没用,要用title设置按钮上的文字
Button只能提供固定样式的按钮,无法设置样式
自定义按钮需要使用下面的Touchable 系列组件
该系列组件内部必须定义一个子组件,且必须只能有一个根子组件,多个子组件可以用View包裹
TouchableHighlight,按下时默认变黑
可以用 underlayColor
属性设置点击时要变化到指定颜色,activeOpacity
设置点击时的显示的不透明度(取值0-1直接)
<TouchableHighlight onPress={() => {Alert.alert("你点击了按钮")}} underlayColor="red" style={{width: 150, height: 40, backgroundColor: 'yellow'}}>
<View>
<Text>Button</Text>
</View>
</TouchableHighlight>
坑:按钮样式最好写在按钮组件上,这是特例,下面的按钮组件,样式都写在根子组件上
TouchableOpacity,按下时变半透明,一样能使用 activeOpacity
属性
<TouchableOpacity onPress={() => {Alert.alert("你点击了按钮")}} >
<View style={{width: 190, height: 40, backgroundColor: 'green'}} >
<Text>Button</Text>
</View>
</TouchableOpacity>
TouchableNativeFeedback ,按下时产生墨水涟漪效果
<TouchableNativeFeedback onPress={() => {Alert.alert("你点击了按钮")}} >
<View style={{width: 180, height: 40, backgroundColor: 'red'}}>
<Text>Button</Text>
</View>
</TouchableNativeFeedback>
TouchableWithoutFeedback,无任何颜色和效果,只能设置宽高,不常用
使用场景是实现点击空白处触发某个操作,空白部分用该组件包起来,或绝对定位覆盖住
<TouchableWithoutFeedback onPress={() => {Alert.alert("你点击了按钮")}}>
<View style={{width: 150, height: 40, backgroundColor: 'origin'}} >
<Text>Button</Text>
</View>
</TouchableWithoutFeedback>
ScrollView 是一个通用的可滚动的容器,可以在其中放入多个组件和视图,而且这些组件并不需要是同类型的
<ScrollView>
<Text style={{fontSize:150}}>Fighting</Text>
...
</ScrollView>
ScrollView 必须有一个确定的高度才能正常工作
要么直接设置高度(不推荐,因为它会根据内部组件自动延伸自己的尺寸到合适的大小)
ScrollView 中不要加 flex:1
ScrollView 响应的优先级比内部组件高,没办法改变
可以设置 horizontal
属性为true,使其为横向滚动,默认为false
该组件适合显示较短或结构不一样的内容,因为所有组件都会被渲染,性能很差,较长内容用下面的长列表渲染
长列表组件会优先渲染屏幕可见区的元素,所以性能好。
FlatList适合渲染结构相似,仅仅数据不同的内容。
FlatList有两个必须设置的属性:data
是数据源,renderItem
是渲染格式
keyExtractor
属性和react列表渲染的key一样,规范来说最好设置一下,提高渲染效率
<FlatList data={[{key: 'Devin'},{key: 'Jackson'},{key: 'James'}]}
renderItem={({item}) => <Text>{item.key}</Text>}
keyExtractor={(item, index) => index} />
SectionList适合渲染的是一组需要分组的数据,也许还带有分组标签
和上面相似,sections
是数据源,renderItem
是渲染格式,renderSectionHeader
是分组头部渲染格式
<SectionList sections={[
{title: 'D', data: ['Devin']},
{title: 'J', data: ['Jackson', 'James', 'Jillian']},
]}
renderItem={({item}) => <Text>{item}</Text>}
renderSectionHeader={({section}) => <Text>{section.title}</Text>}
keyExtractor={(item, index) => index} />
Fetch
function getMoviesFromApiAsync() {
return fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) => {
console.error(error);
});
}
Ajax,RN已经内置ajax,你可以直接写原生,也能用比如axios、frisbee,但不能用JQuery
而且你既可以用Promise写法,也能用Async/Await函数
WebSocket 也支持
var ws = new WebSocket('ws://host.com/path');
ws.onopen = () => {
// connection opened
ws.send('something'); // send a message
};
ws.onmessage = (e) => {
// a message was received
console.log(e.data);
};
ws.onerror = (e) => {
// an error occurred
console.log(e.message);
};
ws.onclose = (e) => {
// connection closed
console.log(e.code, e.reason);
};
上面学了滚动视图和网络请求,我们就可以学下拉刷新啦
示例:
class RefreshableList extends Component {
state = { refresh: false }
Refresh = () => {
this.setState({refreshing: true});
fetchData().then(() => {
this.setState({refreshing: false});
});
}
render() {
return (
<ScrollView
refreshControl={<RefreshControl refreshing={this.state.refresh} onRefresh={this.Refresh}/>}
...
/>
);
}
...
}
如上图所示,在滚动视图组件 ScrollView
中,设置 refreshControl
属性,在该属性中添加 RefreshControl
组件
refreshing
控制转圈圈的指示器是否开启,true为开启,false为关闭
onRefresh
是下拉刷新时,要执行的方法
上面例子中,该方法首先开启指示器,然后向网络请求最新数据,获取到数据后,就会关闭指示器
其它滚动组件也能使用,比如 FlatList 和 SectionList
上图可大致分为创建阶段,更新阶段,销毁阶段
下面我是严格按照函数的执行顺序说明的
getDefaultProps( ):初始化默认的属性(props)
通常会将固定的内容放在这个函数中进行初始化和赋值,可以通过 this.props 获取属性,由于组件初始化后,再次使用该组件不会调用getDefaultProps函数,所以组件自己不可以自己修改props(即 props 可认为是只读的),只可由其他组件调用它时在外部修改
getInitialState( ):初始化组件状态(state)
该函数不同于getDefaultProps,在以后的过程中,会再次调用,所以可以将控制控件状态的一些变量放在这里初始化,可以通过 this.state 来获取值,通过 this.setState 来修改。注意:一旦调用了this.setState方法,组件一定会调用render方法,对组件进行再次渲染
componentWillMount( ) :页面挂载前运行的函数
render( ):渲染模板的函数
视图层的DOM就在这里
componentDidMount( ):页面挂载完成时运行的函数
有关DOM的操作都放在此处执行,因为此时DOM才加载完。处理网络请求等加载数据的操作,一般都在此执行
shouldComponentUpdate:判断是否要执行更新组件操作的函数
该函数自带两个参数,第一个参数为父组件传的值,第二个参数是更新后的值。
此外还会return一个布尔值,false就不执行更新操作,不会加载下面的钩子。true就执行更新组件,并加载接下来更新组件的钩子
如果你不写这个函数,就默认为true
一般用于优化,可以返回false或true来控制是否进行渲染
componentWillUpdate( ):组件更新前运行的函数
render( ):每次更新数据,render都会运行重新渲染
componentDidUpdate( ):组件完成更新时运行的函数
componentWillReceiveProps( )
该函数自带一个参数,为父组件的传值。
如果子组件使用父组件的传值,紧接着会触发组件数据更新时的钩子,也就是上面的4个函数
componentWillUnmount( )
一般在此清理定时器和监听器
当你学到这时,你已经有能力写单页面了,接下来,你看我的超光速学习笔记二,学习组件间的跳转吧:https://blog.csdn.net/weixin_43943881/article/details/88561446