您的位置:首页 > Web前端 > React

React-Native笔记

2016-07-27 08:54 585 查看
react-native 学习环境安装:http://reactnative.cn/docs/0.48/getting-started.html#content创建并运行项目:react-native init AwesomeProject
cd AwesomeProject
react-native run-ios
ps:可以使用[code]--version
参数(注意是
个杠)创建指定版本的项目。例如
react-native init MyApp --version 0.44.3。
[/code]
0.45及以上版本需要下载boost库编译 —》查看
http://bbs.reactnative.cn/topic/4301/ios-rn-0-45%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%AC%E6%89%80%E9%9C%80%E7%9A%84%E7%AC%AC%E4%B8%89%E6%96%B9%E7%BC%96%E8%AF%91%E5%BA%93-boost%E7%AD%89[/code]
在模拟器中,commond+R是重新加载
属性(props)的使用
//自定义的控件
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>);}}
props
是在父组件中指定,而且一经指定,在被指定的组件的生命周期中则不再改变[/code]
对于需要改变的数据,我们需要使用[code]state
[/code]
一般在 constructor中初始化 state,在需要修改时调用[code]setState
方法[/code]
组件的生命周期。
组件的生命周期分成三个状态:Mounting:已插入真实 DOMUpdating:正在被重新渲染Unmounting:已移出真实 DOMReact 为每个状态都提供了两种处理函数,will函数在进入状态之前调用,did函数在进入状态之后调用,三种状态共计五种处理函数。componentWillMount():只会在装载之前调用一次,在 render之前调用,你可以在这个方法里面调用setState改变状态,并且不会导致额外调用一次 rendercomponentDidMount():只会在装载完成之后调用一次,在 render之后调用,从这里开始可以通过ReactDOM.findDOMNode(this)获取到组件的 DOM 节点。componentWillUpdate(object nextProps, object nextState)componentDidUpdate(object prevProps, object prevState)componentWillUnmount():卸载组件触发此外,React还提供两种特殊状态的处理函数。componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用特别注意:以下这些方法不会在首次 render组件的周期调用componentWillReceivePropsshouldComponentUpdatecomponentWillUpdatecomponentDidUpdate
创建组件实例并插入DOM时,会调用:
constructor() 
//初始化 state 的位置,如果不需要初始化 state 并且不绑定方法的话,则不用实现该构造函数,注意state
不会随着任何props更新而更新,所以不要这样写:constructor(props) {super(props);this.state = {color: props.initialColor};}
componentWillMount()
//在插入 DOM 前调用,官方建议用 constructor 代替
render()  //
在调用时,应该检查
this.props
this.state
,并返回一个作出反应的元素。此元素可以是本机DOM组件的表示形式,也可以是
<div />
您自己定义的另一个复合组件。您也可以返回
null
false
指示您不想要任何呈现。当返回
null
或者
false
ReactDOM.findDOMNode(this)
将返回
null
如果
shouldComponentUpdate()
返回false,则render()不会被调用
componentDidMount()
//在插入 DOM 后调用,在此方法中设置/更新 state都会重新渲染组件,如果需要从远程端点加载数据,这是实例化网络请求的好地方更新 state 或者 props,当重新渲染组件的时候,会调用:
componentWillReceiveProps()
//接收新的 props 前会调用,要注意的是,就算 props 没有发生改变,这个方法也可能会触发,所以请确保比较当前值和下一个值,然后在执行后面的处理。//在 props初始化的时候不会调用这个方法,只有在更新state 的时候才會调用,调用
this.setState
一般不会触发该方法
shouldComponentUpdate()
//默认返回 true,此方法在接收新的 state 或者 props 前被调用。当 render()或者forceUpdate被调用的时候并不会调用此方法。//返回 false 并不会阻止组件在state 改变时候的重新渲染,但是
componentWillUpdate()
render()
componentDidUpdate()
将不会被调用,所以可以通过比较
this.props
nextProps
this.state与
nextState来告诉组件跳过更新。
//返回 false可能导致组件的重新渲染。
componentWillUpdate()
这个方法会在接收到新的 state 或者 props 前调用,初始化渲染的时候不会调用该方法。不能在这个方法里面调用 this.setState(),如果需要更新 state 来响应 props 的改变,用componentWillReceiveProps代替。当
shouldComponentUpdate()返回 false 的时候,这个方法不会被调用。
render()
componentDidUpdate()
该方法在更新后会被立即调用,同样不会在初始化渲染的时候调用。这个方法也是操作 DOM 组件的好地方,比如可以比较 前后的props来判断是否需要进行网络请求。从 DOM 删除组件的时候,会调用:
componentWillUnmount()
在组件销魂和删除前会调用该方法,在此方法中执行任何必要的清理,例如使定时器无效,取消网络请求或清除在componentDidMount创建的对象
每个组件还提供了一些其他API:
setState()
setState(updater, [callback])第一个参数是(prevState, props) => stateChange
prevState
是对以前状态的引用。不应该直接改变它,而是应该根据
prevState
和props构建一个新对象来表示更改。例如,假设我们想增加一个状态值
props.state
this.setState((prevState, props) => {return {counter: prevState.counter + props.step};});
第二个参数是一个可选的回调函数,官方建议用componentDidUpdate代替它的使用。
如果下一个 state 仅依赖上一个 state,官方建议如下形式使用:
this.setState((prevState) => {
return {counter: prevState.quantity + 1};});
forceUpdate()
在大多数情况下,应该尽量避免使用这个方法,并且 this.state 和 this.props的读操作应该只在render()中发生。

类属性

defaultProps
用设置默认 的props,但如果设置好的 props 为 null,则默认设置不会生效。e.g.:class CustomButton extends React.Component { // ...}CustomButton.defaultProps = { color: 'blue'};如果
props.color
没有提供,它将默认设置为
'blue'
  render() {return <CustomButton /> ; // props.color will be set to blue}
如果
props.color
设置为null,它将保持为空:
  render() {return <CustomButton color={null} /> ; // props.color will remain null}
displayName

实例属性

props
state
用户定义、JavaScript对象,用于包含特定的组件数据,这些数据会发生变化。如果要改变它,不要直接 this.state 的方式,而是用 setState()

弹性(Flex)宽高

在组件样式中使用[code]flex
可以使其在可利用的空间中动态地扩张或收缩。一般而言我们会使用
flex:1
来指定某个组件扩张以撑满所有剩余的空间。如果有多个并列的子组件使用了
flex:1
,则这些子组件会平分父容器中剩余的空间。如果这些并列的子组件的
flex
值不一样,则谁的值更大,谁占据剩余空间的比例就更大(即占据剩余空间的比等于并列组件间
flex
值的比)。[/code]
ps: flexDirection标签控制 flex 拉伸方向(控制主轴方向),默认是column竖直轴(默认拉伸高度),可以设置成水平轴([code]row
)[/code]
justifyContent标签可以控制子组件的排列顺序,分别是:
flex-start:
主轴首部[/code]
center:主轴中部
flex-end:主轴尾部
space-around:组件在主轴方向按固定间距排列(比如每个组件都是左右间距50或者每个组件上下间距都是50)
space-between:主轴方向等间距排列。
[/code]

Align Items

在组件的style中指定
alignItems
可以决定其子元素沿着次轴
对应的这些可选项有:
flex-start
、[code]center
flex-end
以及
stretch
。[/code]
注意:要使
stretch
选项生效的话,子元素在次轴方向上不能有固定的尺寸
style 賦值
e.g.:
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',},});
后声明的属性会覆盖先声明的同名属性(上面的例子是覆蓋了 color 這個屬性)
所以文本的風格是(:紅藍、大紅、大藍、大
Textinput
从TextInput里取值这就是目前唯一的做法:订阅它的[code]onChangeText
事件来读取用户的输入,即使用
onChangeText
写入state,然后从this.state中取出值[/code]
TextInput
在安卓上默认有一个底边框,同时会有一些padding。如果要想使其看起来和iOS上尽量一致,则需要设置
padding: 0
,同时设置
underlineColorAndroid="transparent"
来去掉底边框。又,在安卓上如果设置
multiline = {true}
,文本默认会垂直居中,可设置
textAlignVertical: 'top'
样式来使其居顶显示。又又,在安卓上长按选择文本会导致
windowSoftInputMode
设置变为
adjustResize
,这样可能导致绝对定位的元素被键盘给顶起来。要解决这一问题你需要在AndroidManifest.xml中明确指定合适的
windowSoftInputMode
https://developer.android.com/guide/topics/manifest/activity-element.html )值,或是自己监听事件来处理布局变化长列表(listview):FlatList或是SectionList。FlatList:没有组视图const myListData = [{key: 'Devin'},{key: 'Jackson'},{key: 'James'},{key: 'Joel'},{key: 'John'},{key: 'Jillian'},{key: 'Jimmy'},{key: 'Julie'},];export default class MyListViewDemo extends Component<{}> {render() {return (<View style = {styles.container}><FlatListdata = {myListData}renderItem = { ({item}) =><View style = {styles.flesone}><Image source = {require('./image/test.png')} style = {{alignItems: 'center'}}/><Text style = {styles.item} >{item.key}</Text></View>}/></View>);}}SectionList:有组视图const sectionListData = [{title: {name: 'Jo', age: 20}, data: [{key: 'Devin'},{key: 'Jackson'},{key: 'James'},{key: 'Joel'},{key: 'John'},{key: 'Jillian'},{key: 'Jimmy'},{key: 'Julie'},]},{title: {name: 'XYF', age: 30}, data: [{key: 'XYF_SSS'},{key: 'XYF_Jackson'},{key: 'XYF_James'},{key: 'XYF_Joel'},]},];export default class MySectionListDemo extends Component<{}> {render() {return (<View style = {styles.flexone}><SectionListsections = {sectionListData}renderItem = {({item}) =><Text style = {{color: 'red', fontSize: 20}}>{item.key}</Text>}renderSectionHeader = {({section}) =><Text style = {{fontSize: 30, marginLeft: 100}}>{section.title.name}</Text>}/></View>);}}导航栏:目前主推react-navigation只针对iOS平台开发,并且想和系统原生外观一致,那么可以选择
NavigatorIOS
e.g.:
//只有声明了
{ navigation }的才能继续跳转。
const HomeScreen = ({ navigation }) => (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Text>Home Screen</Text><ButtononPress={() => 
navigation.navigate('Details’) //跳转到” Details"界面}
      title="Go to details"/></View>);const DetailsScreen = () => (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Text>Details Screen</Text></View>);//初始化
StackNavigator,注册导航栏所在的窗口视图
const RootNavigator = StackNavigator({Home: {screen: HomeScreen,navigationOptions: {
	//导航栏标题headerTitle: 'Home',},},Details: {screen: DetailsScreen,navigationOptions: {
	//导航栏标题headerTitle: 'Details',},},});export default class MainScreen extends Component<{}> {render() {return (<RootNavigator />);}}
其他:TabNavigator、DrawerNavigator参考:https://reactnavigation.org/docs/intro/quick-start属性(个别需要特别注意的)

keyboardType enum("default", 'numeric', 'email-address', "ascii-capable", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search') 

决定弹出的何种软键盘的,譬如
numeric
(纯数字键盘)。这些值在所有平台都可用:defaultnumericemail-addressphone-pad

returnKeyType enum('done', 'go', 'next', 'search', 'send', 'none', 'previous', 'default', 'emergency-call', 'google', 'join', 'route', 'yahoo') 

决定“确定”按钮显示的内容。在Android上你还可以使用
returnKeyLabel
来自定义文本。跨平台下列这些选项是跨平台可用的:
done
go
next
search
send
限Android下列这些选项仅限Android使用:
none
previous
限iOS下列这些选项仅限iOS使用:
default
emergency-call
google
join
route
yahoo
加载图片
http://reactnative.cn/docs/0.49/images.html
ps: 在iOS上,每次调整Image组件的宽度或者高度,都需要重新裁剪和缩放原始图片。这个操作开销会非常大,尤其是大的图片。比起直接修改尺寸,更好的方案是使用[code]transform: [{scale}]
的样式属性来改变尺寸。比如当你点击一个图片,要将它放大到全屏的时候,就可以使用这个属性[/code]
resizeMode的属性:cover(默认),contain(全部展示图片,自动缩放)、stretch(拉伸图片,让宽或者高占满控件)设置背景色为透明色: backgroundColor: ‘transparent’
各种颜色参数:http://reactnative.cn/docs/0.49/colors.html#content
可点击/长按的组件(点击效果按钮)
一般来说,你可以使用TouchableHighlight来制作按钮或者链接。注意此组件的背景会在用户手指按下时变暗。在Android上还可以使用TouchableNativeFeedback,它会在用户手指按下时形成类似墨水涟漪的视觉效果。TouchableOpacity会在用户手指按下时降低按钮的透明度,而不会改变背景的颜色。如果你想在处理点击事件的同时不显示任何视觉反馈,则需要使用TouchableWithoutFeedback。e.g.:<TouchableHighlight onPress = {() => Alert.alert("测试单击”)}onLongPress = {() => Alert.alert("这是长按效果")}><Text>My Test </Text></TouchableHighlight>
定时器使用
需要注意的是铭记[code]在unmount组件时清除(clearTimeout/clearInterval)所有用到的定时器
[/code]
直接操作组件setNativeProps的简单使用:http://reactnative.cn/docs/0.49/direct-manipulation.html#content

各种性能影响比如:ListView初始化渲染太慢以及列表过长时滚动性能太差,滑动画面卡顿等的解决方法:http://reactnative.cn/docs/0.49/performance.html#content

升级教程:http://reactnative.cn/docs/0.49/upgrading.html#content
特定平台代码的区分:http://reactnative.cn/docs/0.49/platform-specific-code.html#content
React Native会检测某个文件是否具有
.ios.
或是
.android.
的扩展名,然后根据当前运行的平台加载正确对应的文件。假设你的项目中有如下两个文件:
BigButton.ios.jsBigButton.android.js
这样命名组件后你就可以在其他组件中直接引用,而无需关心当前运行的平台是哪个。
import BigButton from './components/BigButton';
React Native会根据运行平台的不同引入正确对应的组件。实用的方法是Platform.select()e.g.:
import { Platform, StyleSheet } from 'react-native';var styles = StyleSheet.create({container: {flex: 1,...Platform.select({ios: {backgroundColor: 'red',},android: {backgroundColor: 'blue',},}),},});
上面的代码会根据平台的不同返回不同的container样式——iOS上背景色为红色,而android为蓝色。这一方法可以接受任何合法类型的参数,因此你也可以直接用它针对不同平台返回不同的组件,像下面这样:
var Component = Platform.select({ios: () => require('ComponentIOS'),android: () => require('ComponentAndroid'),})();<Component />;

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ReactNative