一、Flexbox布局
1.容器属性
(1)flexDirection
- row 水平布局
- column 竖直布局(默认方式)
(2)flexWrap
决定其子元素沿着轴线的排列成一行或者空间不够后自动换行
- nowrap 不自动换行(默认方式)
- wrap 自动换行
(3)justifyContent
决定其子元素沿着主轴的排列方式
- flex-start
- center
- flex-end
- space-around
- space-between
(4)align-items
决定其子元素沿着交叉轴的排列方式
- flex-start
- flex-end
- center
- baseline
- stretch
2.元素属性
(1)alignSelf
允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。
- auto (默认方式)
- flex-start
- center
- flex-end
- stretch
(2)图片
- contain
- cover
- stretch
(3)定位(相对定位和绝对定位)
和top、left配合使用
- absolute
- relative
(4)text
Text之间存在属性继承
- textAlign enum("auto", 'left', 'right', 'center')
- lineHeight number
- writingDirection enum("auto", 'ltr', 'rtl')
- numberOfLines number( 需要放在最外层的Text元素上,且虽然截取了文字但是还是会占用空间)
3.公共属性
(1)flex
权重,类似安卓布局中的layout_weight属性。
(2) 盒子模型(margin和padding)
和Android、css中一样
二、ListView-多个布局样式
1.数据结构
目前支持如下的数据结构
- { sectionID_1: { rowID_1: rowData1, ... }, ... }
- { sectionID_1: [ rowData1, rowData2, ... ], ... }
- [ [ rowData1, rowData2, ... ], ... ]
大多数情况下我们会用到第二种(字典套数组)和第三种(纯数组),每一个数组对应的key系统会自动提取成sectionId。然后我们可以根据sectionId来判断所加载的section。
如果是纯数组(无section),使用cloneWithRows(dataBlob, rowIdentities) 该方法接收两个参数,dataBlob是原始数据源。在没有section的时候使用此方法,传入一个数组。rowIdentities为可选类型,为数据源的每一项指明一个id。默认的id为字符串'0','1','2'...dataBlob.count。
如果是字典套数组的结构(有section),我们使用下面的方法为数据源赋值。sectionIdentities和rowIdentities都是可选类型。 cloneWithRowsAndSections(dataBlob, sectionIdentities, rowIdentities)
代码示例:
//数据结构
const datas={
sectionWithTitle:[
{
title:'精选菜单',
pic:'http://image.hongbeibang.com/FjigYOhuPOLLS6M4F5ejd6psqCcI?801X312&imageMogr2/strip/thumbnail/750x750'
},
{
title:'热门菜单',
pic:'http://image.hongbeibang.com/Fof924bIoB1hqE2MTs38bBcGEzk3?802X313&imageMogr2/strip/thumbnail/750x750'
}
],
sectionWithoutTitle:[
{
pic:'http://image.hongbeibang.com/FqBRH1E0EP2I488s7DXww1RVGQOF?801X311&imageMogr2/strip/thumbnail/750x750'
},
{
pic:'http://image.hongbeibang.com/FulhGNdLtEmHKTKkLX0cLjlH9Wxi?802X312&imageMogr2/strip/thumbnail/750x750'
},
{
pic:'http://image.hongbeibang.com/FkC4ySvlw9--96qkfJfFNeG9AgMa?800X313&imageMogr2/strip/thumbnail/750x750'
}
]
};
//构造方法
constructor(props){
super(props);
const ds = new ListView.DataSource(
{
rowHasChanged:(r1,r2)=>r1!==r2,//判断不同item行是否相同
sectionHeaderHasChanged:(s1,s2)=>s1!==s2//不同之处,还应判断section是否相同
});
this.state={
dataSource:ds,
isLoaded:false
}
}
//渲染方法
render() {
if(!this.state.isLoaded){
return this.renderLoading()
}
return (
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData,sectionId,rowId)=>this.renderSections(rowData,rowId,sectionId)}//注意不同之处。可以拿到sectId
/>
);
}
//更新数据
componentDidMount(){
var that = this;
var change =function () {
that.setState({
dataSource:that.state.dataSource.cloneWithRowsAndSections(datas),//注意调用方法的差别
isLoaded:true
})
};
setTimeout(change,1000);
}
三、封装独立组件
父组件向子组件传值方式:props(上一篇文章已总结过)
子组件向父组件传值
- 1.EventEmitter
简单的观察者模式。发送端发送通知,接收端接受到通知后,通过状态机来改变渲染。发送端和接受端同时需要引入DeviceEventEmitter组件。
代码示例:
//父组件
DeviceEventEmitter.addListener("监听事件名",(来自子组件的参数1,来自子组件的参数2,...)=>{
//父组件收到数据后进行操作
})
//子组件
DeviceEventEmitter.emit("监听事件名",传递给父组件的参数1,传递给父子组件的参数2,...)
- 2.callback
代码示例:
//第一个页面
ToNextView(){
this.props.navigator.push({
component:NextView,
passProps:{
callback:((接受的参数)=>{
this.seedToSecond(接受的参数)
})
}
})
}
//第二个页面
popToHome(){
this.props.navigatior.pop();
this.props.callback('要传递的参数')
}