本文是个人学习笔记,例子都是来自React Native官网。之前不是做前端的,没有使用过react,要学习react native做混合开发,react,包括react jsx还是得补补。
react和react jsx
react是一个js库。有很多可以用的方法,react jsx是对javascript进行封装,提供一种类似于xml格式的语句,跟html也类似,使得在js中创建、修改元素,建立元素之间的层级关系变得更加直观方便。jsx在执行的时候会被转换为js语句。
例如:
<input type=“button"/>;
这样就相当于调用了
React.createElement()
方法来创建一个button
在jsx中可以使用js语句,但是要用花括号括起来,比如:
var person = <Person name={window.isLoggedIn ? window.name : ''} />;
jsx中,元素可以直接嵌套,这个和html、xml都是一样的。
jsx中,布尔值用{true}和{false}表示。
jsx中,插入注释,就是用/* 注释 */
react和jsx混合起来,数据绑定的实现
假如有一个这样的数据(js定义的数据)
var data = [
{id: 1, author: "Pete Hunt", text: "This is one comment"},
{id: 2, author: "Jordan Walke", text: "This is *another* comment"}
];
希望建立一个列表,其中每一项,展示以上data中的一条数据:
于是定义一个CommentList的组件,其中每一项是一个Comment对象(假设之前已经定义好了Comment组件)。
var CommentList = React.createClass({//创建一个组件,或者理解成创建一个类也可以
render: function() {//render函数是在组件声明周期中会被自动调用的方法之一,作用是返回组件的内容
var commentNodes = this.props.data.map(function(comment) {
//这个comment参数对于data中的一条记录,map函数会为this.props.data的每一条记录调用一次这个function(comment)方法。每次调用都返回一个Comment组件对象,最终返回一个包含多个Comment的数组。
return (
<Comment author={comment.author} key={comment.id}>
{comment.text}
</Comment>
);
});
return (
<div className="commentList">
{commentNodes}//包含CommentNodes,由于是js,所以用花括号括起来。
</div>
);
}
});
使用这个定义好的CommentList,并且和数据绑定起来。
ReactDOM.render(
<CommentBox data={data} />,
document.getElementById('content')
);
属性 props 和 状态 state
上面例子中其实已经用到了react中一个比较重要的东西——属性。在jsx中,属性就类似于html的属性,包含在标签内,如这里的data
。
<CommentBox data={data} />
在组件的定义中,要访问自己的属性就通过this.prop.属性名,如这里的data。
this.props.data
在上面的用法中,可以看到,CommentBox的data属性是在使用CommentBox的时候,进行了设置,也就是CommentBox的父级对它进行了属性的设置。在CommentBox内部,只能通过this.props.data
来使用这个属性,但不能改变这个属性。也就是说,属性是由组件的父级来设置的,对于组件来说,是不可变的。
但要在CommentBox中对自己的属性进行修改却是经常有的事,react对此为组件定义了一个状态的概念,state
。组件的状态就是一组属性值。组件的属性不可直接修改,但可以修改组件的状态。可以为组件定义状态,也就是定义state,然后在需要时,进行状态的切换,这样,就实现了组件的属性从一个状态切换到另一种状态。
切换状态通过setState()
方法,比如:
this.setState({data: []});//更新状态,给data属性赋一个空数组。
访问当前状态的属性值,可以通过this.state.属性名
,比如data,就是this.state.data
。
通过getInitialState
方法,设置组件的初始状态。方法中
return{
属性一:值一,
属性二:值二,
…
}
利用state来保证组件的当前值,和属性的当前值始终一致。
下面建立一个commentForm组件,包含两个输入框,一个输入author一个输入text,演示如何利用state来实现,commentForm的author和text属性的值,始终和两个输入框中显示的值保持一致。
var CommentForm = React.createClass({
getInitialState: function() {
return {author: '', text: ‘’}; //设定初始化状态,给author和text属性都赋空值
},
//定义了两个方法,在用户输入变化的时候会调用它们
handleAuthorChange: function(e) {
this.setState({author: e.target.value});
},
handleTextChange: function(e) {
this.setState({text: e.target.value});
},
//render方法
render: function() {
return (
//建立表单,让输入框的value始终等于属性author或text的值,在输入框value变化的时候更新author或text的值。
<form className="commentForm">
<input
type="text"
placeholder="Your name"
value={this.state.author} //让输入框的value始终等于属性author的值
onChange={this.handleAuthorChange} //在输入框value变化的时候更新author的值
/>
<input
type="text"
placeholder="Say something..."/让输入框的value始终等于属性text的值
value={this.state.text}//在输入框value变化的时候更新text的值
onChange={this.handleTextChange}
/>
<input type="submit" value="Post" />
</form>
);
}
});
样式 style
基本上所有的核心组件都有style这个属性。要设置组件的外观只要给style赋值。通常会使用js。
<View style={{backgroundColor: ‘powderblue’,width:50,height:30}} />
第一个花括号表示语句块,第二个花括号表示在jsx中内嵌js。
通常界面复杂,样式复杂的时候,最好把样式集中定义。
使用StyleSheet.create()
方法创建一个样式表,里面可以定义多种样式,然后用点语法进行访问。如下定义了一个样式表styles,里面定义了两种样式,bigblue和red。在使用的时候就可以通过styles.bigblue
或者styles.red
找到。
const styles = StyleSheet.create({
bigblue: {
color: 'blue',
fontWeight: 'bold',
fontSize: 30,
},
red: {
color: 'red',
},
});
使用的时候这样:
<Text style={styles.red}>just red</Text>
<Text style={styles.bigblue}>just bigblue</Text>
<Text style={[styles.bigblue, styles.red]}>i love you</Text>
注意,像第三句中使用了两种样式,那么排在后面的样式会覆盖前面的样式。
布局
大小:
组件的大小可以用flex来确定。这个东西是相对的。把屏幕大小作为1,那么先将父级的flex设置为1。然后子级的组件就可以通过设置flex的值来确定占据父级空间中的百分比。
比如总共有两个子级的组件,其中子级1的flex为1,子级2的flex为2,那么两个子级的flex加起来就是3,所以子级1就占据父级的三分之一,而子级2占据父级三分之二。没错,就是这么简单。
直观一些:(这里有3个子级咯,思想是一样的)
<View style={{flex: 1}}>
<View style={{flex: 1, backgroundColor: 'powderblue'}} />
<View style={{flex: 2, backgroundColor: 'skyblue'}} />
<View style={{flex: 3, backgroundColor: 'steelblue'}} />
</View>
效果:
这个就是flexbox的基本思想。它可以用来适配不同屏幕大小。
位置:
使用flexbox中的三个属性联合来确定组件的位置:flexDirection、alignItems、justifyContent。
说白了flexbox就是流布局,或者有的叫瀑布流也可以。
- flexDirection就是流的方向,是row的话,组件从左到右排列(横向),column的话,组件从上到下排列(纵向)。默认是row,从左到右。
- justifyContent就是组件沿着纵flexDirection排列时的分布方式或者对齐方式。可以是居中,集中在开头,集中在尾部,或者分散分布等等。可以自己把这些候选值都试个遍:flex-start, center, flex-end, space-around, and space-between。
比如这样:
<View style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-end',
}}>
<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} />
</View>
效果:
- alignItems也是对齐方式,或者分布方式,不过和justifyContent不同的是,justifyContent是规定该组件在flexDirection方向上的对齐方式,alignItems恰恰是规定该组件在另一个方向上的对齐方式。也就是说,如果组件是纵向排列的,那么这个alignItems规定组件在横向上的排列方式。候选值:flex-start,center,flex-end,stretch。
注意到,上面说的三个属性,都是给父级组件管理其子级组件时使用。
以上纯属个人初学简单理解,可以作为参考。需要更权威的知识总结在官网可以找到。