React-Native
React-Native看起来很像React,不同的是,基础组件是原生组建而非web组件,
编写“hello world”
import React,{Component} from "react";
import {AppRegistry,Text} from "react-native";
class Hello extends Component{
render(){
return{
<Text>hello world</Text>
}
}
}
AppRegistry.registerComponent("Hello",()=>Hello)
AppRegistry模块则是用来告知React Native哪一个组件被注册为整个应用的根容器。你无需在此深究,因为一般在整个应用里AppRegistry.registerComponent这个方法只会调用一次。上面的代码里已经包含了具体的用法,你只需整个复制到index.ios.js或是index.android.js文件中即可运行。
Props(属性)
自定义的组件也能使用props,以此提高复用率 只需要在render函数中使用this。props
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
class Greeting extends Component {
render() {
return (
<Text>Hello {this.props.name}!</Text>
);
}
}
class LotsOfGreetings extends Component {
render() {
return (
<View style={{alignItems: 'center'}}>
<Greeting name='Rexxar' />
<Greeting name='Jaina' />
<Greeting name='Valeera' />
</View>
);
}
}
AppRegistry.registerComponent('LotsOfGreetings', () => LotsOfGreetings);
State(状态)
做一个不断闪烁的文字的效果
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
class Blink extends Component {
constractor(props){
surper(props)
this.state={
flag:true
}
setInterval(()=>{
this.setState({flag:!this.state.flag})
},1000)
}
render(){
let text=this.state.flag?this.state.flag:""
return{
<Text>{text}</Text>
}
}
}
class Blinks extends Component{
render(){
<View>
<Blink text="weni"></Blink>
</View>
}
}
AppRegistry.registerComponent('BlinkApp', () => BlinkApp);
样式
使用驼峰命名
StyleSheet。create集中定义样式
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View } from 'react-native';
class LotsOfStyles extends Component {
render() {
return (
<View>
<Text style={styles.red}>just red</Text>
<Text style={styles.bigblue}>just bigblue</Text>
<Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text>
<Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text>
</View>
);
}
}
const styles = StyleSheet.create({
bigblue: {
color: 'blue',
fontWeight: 'bold',
fontSize: 30,
},
red: {
color: 'red',
},
});
AppRegistry.registerComponent('LotsOfStyles', () => LotsOfStyles);
宽度和高度
React-Native中的尺寸都是无单位的,表示的是与设备像素密度无关的逻辑像素点。
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
class FixedDimensionsBasics extends Component {
render() {
return (
<View>
<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
</View>
);
}
};
// 注册应用(registerComponent)后才能正确渲染
// 注意:只把应用作为一个整体注册一次,而不是每个组件/模块都注册
AppRegistry.registerComponent('AwesomeProject', () => FixedDimensionsBasics);
弹性宽高
在组件样式中使用flex
可以使其在可利用的空间中动态地扩张或收缩。一般而言我们会使用flex:1
来指定某个组件扩张以撑满所有剩余的空间。如果有多个并列的子组件使用了flex:1
,则这些子组件会平分父容器中剩余的空间。如果这些并列的子组件的flex
值不一样,则谁的值更大,谁占据剩余空间的比例就更大(即占据剩余空间的比等于并列组件间flex
值的比)
组件能够撑满剩余空间的前提是其父容器的尺寸不为零。如果父容器既没有固定的width和height,也没有设定flex,则父容器的尺寸为零。其子组件如果使用了flex,也是无法显示的。
flexbox布局
我们在React Native中使用flexbox规则来指定某个组件的子元素的布局。Flexbox可以在不同屏幕尺寸上提供一致的布局结构。一般来说,使用flexDirection
、alignItems
和 justifyContent
三个样式属性就已经能满足大多数布局需求
处理文本输入
TextInput是一个允许用户输入文本的基础组件。它有一个名为onChangeText
的属性,此属性接受一个函数,而此函数会在文本变化时被调用。另外还有一个名为onSubmitEditing
的属性,会在文本被提交后(用户按下软键盘上的提交键)调用。
import React, { Component } from 'react';
import { AppRegistry, Text, TextInput, View } from 'react-native';
class PizzaTranslator extends Component {
constructor(props) {
super(props);
this.state = {text: ''};
}
render() {
return (
<View style={{padding: 10}}>
<TextInput
style={{height: 40}}
placeholder="Type here to translate!"
onChangeText={(text) => this.setState({text})}
/>
<Text style={{padding: 10, fontSize: 42}}>
{this.state.text.split(' ').map((word) => word && '��').join(' ')}
</Text>
</View>
);
}
}
// 注册应用(registerComponent)后才能正确渲染
// 注意:只把应用作为一个整体注册一次,而不是每个组件/模块都注册
AppRegistry.registerComponent('PizzaTranslator', () => PizzaTranslator);
ScrollView
ScrollView
是一个通用的可滚动的容器,你可以在其中放入多个组件和视图,而且这些组件并不需要是同类型的。ScrollView不仅可以垂直滚动,还能水平滚动(通过horizontal
属性来设置)
ListView
ListView
组件用于显示一个垂直的滚动列表,其中的元素之间结构近似而仅数据不同。
ListView
更适于长列表数据,且元素个数可以增删。和ScrollView
不同的是,ListView
并不立即渲染所有元素,而是优先渲染屏幕上可见的元素。
ListView
组件必须的两个属性是dataSource
和renderRow
。dataSource
是列表的数据源,而renderRow
则逐个解析数据源中的数据,然后返回一个设定好格式的组件来渲染。
rowHasChanged函数也是ListView的必需属性。这里我们只是简单的比较两行数据是否是同一个数据(===符号只比较基本类型数据的值,和引用类型的地址)来判断某行数据是否变化了。
import React, { Component } from 'react';
import { AppRegistry, ListView, Text, View } from 'react-native';
class ListViewBasics extends Component {
// 初始化模拟数据
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([
'John', 'Joel', 'James', 'Jimmy', 'Jackson', 'Jillian', 'Julie', 'Devin'
])
};
}
render() {
return (
<View style={{paddingTop: 22}}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text>{rowData}</Text>}
/>
</View>
);
}
}
// 注册应用(registerComponent)后才能正确渲染
// 注意:只把应用作为一个整体注册一次,而不是每个组件/模块都注册
AppRegistry.registerComponent('ListViewBasics', () => ListViewBasics);
使用导航栏跳转页面
Navigator
可以跨平台工作,同时也便于定制。
场景sence的概念和使用
摆放在一个屏幕中的组件,就共同构成了一个“场景(Scene)”。场景简单来说其实就是一个全屏的React组件。
import React, { Component } from 'react';
import { AppRegistry, Navigator, Text, View } from 'react-native';
import MyScene from './MyScene';
class SimpleNavigationApp extends Component {
render() {
return (
<Navigator
initialRoute={{ title: 'My Initial Scene', index: 0 }}
renderScene={(route, navigator) =>
<MyScene
title={route.title}
// Function to call when a new scene should be displayed
onForward={ () => {
const nextIndex = route.index + 1;
navigator.push({
title: 'Scene ' + nextIndex,
index: nextIndex,
});
}}
// Function to call to go back to the previous scene
onBack={() => {
if (route.index > 0) {
navigator.pop();
}
}}
/>
}
/>
)
}
}
AppRegistry.registerComponent('SimpleNavigationApp', () => SimpleNavigationApp);
对应的MyScene.js代码如下:
import React, { Component, PropTypes } from 'react';
import { View, Text, TouchableHighlight } from 'react-native';
export default class MyScene extends Component {
static propTypes = {
title: PropTypes.string.isRequired,
onForward: PropTypes.func.isRequired,
onBack: PropTypes.func.isRequired,
}
render() {
return (
<View>
<Text>Current Scene: { this.props.title }</Text>
<TouchableHighlight onPress={this.props.onForward}>
<Text>点我进入下一场景</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.props.onBack}>
<Text>点我返回上一场景</Text>
</TouchableHighlight>
</View>
)
}
}
在这个例子中,MyScene
通过title
属性接受了路由对象中的title值。它还包含了两个可点击的组件TouchableHighlight
,会在点击时分别调用通过props传入的onForward
和onBack
方法,而这两个方法各自调用了navigator.push()
和navigator.pop()
,从而实现了场景的变化。
引入图片
<Image source={require('./img/a.jpg')}/>
网络图片
// 正确
<Image source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}
style={{width: 400, height: 400}} //必须的
/>
// 错误
<Image source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}} />
CameraRoll
模块提供了访问本地相册的功能。
通过嵌套实现背景图片
类似于web中的背景图片 background-image
return(
<Image source={...}>
<Text>wenben</Text>
</Image>
)
处理触摸事件
当需要捕捉用户点击操作时,可以使用touchable开头的一系列组件,这些组件通过onpress属性接受一个点击事件的处理函数
class MyButton extends Component {
_onPressButton() {
console.log("You tapped the button!");
}
render() {
return (
<TouchableHighlight onPress={this._onPressButton}>
<Text>Button</Text>
</TouchableHighlight>
);
}
}
- 一般来说,你可以使用TouchableHighlight来制作按钮或者链接。注意此组件的背景会在用户手指按下时变暗。
- 在Android上还可以使用TouchableNativeFeedback,它会在用户手指按下时形成类似墨水涟漪的视觉效果。
- TouchableOpacity会在用户手指按下时降低按钮的透明度,而不会改变背景的颜色。
- 如果你想在处理点击事件的同时不显示任何视觉反馈,则需要使用TouchableWithoutFeedback。
长按
onLongPress
双指缩放
如果在ScrollView中只放置一个组件,则可以用来实现缩放操作。
设置maximumZoomScale和minimumZoomScale属性即可以使用户能够缩放其中的内容。