React战记之玩转Flex布局(上篇--容器属性)
2018-12-09 本文已影响33人
e4e52c116681
零、前言
最近一直在总结Android,前端这块感觉忘得也差不多了
Flex布局以前也听过,但没有详细学习过,趁机会用React玩转一下,
遇到一个新的知识怎么学,一大堆的参数让人发懵,我最喜欢的一句话:能应对变化的只有变化本身
用自己的能力让学习的对象非静态,就像与你交流的是一个活的人而非人偶
本文并非React基础教程,也非Flex布局讲解教程,只是做一个Flex布局演示器
源码见文尾捷文规范
不废话了,留图镇楼:
效果图一、搭建React项目:
1.创建+scss配置
个人比较喜欢scss,最新的create-react-app的webpack已经对scss进行了配置
只需添加node-sass就行了
npm i create-react-app
npm i node-sass -D
2.搭建静态页面
静态页面.png2.1:.Flex
矩形div(默认长宽1000*300px)
.Flex {
border: red 2px solid;
margin-top: 20px;
margin-left: 20px;
width: 1000px;
height: 300px;
background-color: rgba(71,71,71,.6);
display: flex;
.title {
border-radius: 10px;
font-size: 30px;
text-align: center;
}
}
Flex.png
2.2:生成若干的条目
1.准备动态数据
let justifyContent = {
index: 0,
data: ["normal", "flex-start", "flex-end", "center", "space-between", "space-around"]
};
let flexDirection = {
index: 0,
data: ["row", "row-reverse", "column", "column-reverse"]
};
let flexWrap = {
index: 0,
data: ["nowrap", "wrap", "wrap-reverse"]
};
let alignItems = {
index: 0,
data: ["normal", "stretch", "flex-start", "flex-end", "center", "baseline"]
};
let alignContent = {
index: 0,
data: ["normal", "stretch", "flex-start", "flex-end", "center", "space-between", "space-around"]
};
<div className="Flex" style={{
width: this.state.ctrl[1].data + "px",
height: this.state.ctrl[2].data + "px",
flexDirection: flexDirection.data[flexDirection.index % flexDirection.data.length],
flexWrap: flexWrap.data[flexWrap.index % flexWrap.data.length],
justifyContent: justifyContent.data[justifyContent.index % justifyContent.data.length],
alignItems: alignItems.data[alignItems.index % alignItems.data.length],
alignContent: alignContent.data[alignContent.index % alignContent.data.length]
}}>
{this.formItem()}
</div>
加条目.png
辅助函数:随机颜色:
Logic.randomRGB
/**
* 随机颜色
* @param a 透明度--默认为1
* @returns {string}
*/
static randomRGB(a = 1) {
return `rgba(${this.rangeInt(0, 255)},${this.rangeInt(0, 255)},${this.rangeInt(0, 255)},${a})`
}
根据数组动态生成随机颜色的条目:
Flex.formItem
formItem() {
let color = [];
for (let i = 0; i < this.state.ctrl[0].data; i++) {
color.push(Logic.randomRGB(.8))
}
return (
color.map((item, index) => {
return (
<div className={"title"} style={{backgroundColor: item}} key={index}>
Toly{index}
</div>
);
})
)
}
3.底部栏的组件:ListInfo.js
底部+点击回调.png
<ListInfo data={this.state.flexObj}
onItemClick={this.onItemClick.bind(this)}/>
3.1:数据的获取:flexObj
:
可以说是以其人之道还治其人之身,用
.Flex
div的自身属性自动生成对象
notifyChanged() {
this.setState({
flexObj: {
"flex-direction": flexDirection.data[flexDirection.index],//元素排列方向
"flex-wrap": flexWrap.data[flexWrap.index],//换行
"justify-content": justifyContent.data[justifyContent.index],//水平对齐方式
"align-items": alignItems.data[alignItems.index],//垂直对齐方式
"align-content": alignContent.data[alignContent.index],//多行垂直对齐方式,
}
});
}
3.2:数据的显示:ListInfo.js
import React, {Component} from 'react';
import './ListInfo.scss'
class ListInfo extends Component {
render() {
return (
<div className="ListInfo" >
{this.formList(this.props.data)}
</div>
)
}
formList(data) {//对象转化数组
let datas = [];
for (let key in data) {
datas.push({
name: key,
data: data[key]
}
);
}
return (
<div id="list-container">
{datas.map((item, index) => {
return (//此处点击回调onItemClick,捕获索引
<div key={index} className="card" onClick={() => {
this.props.onItemClick && this.props.onItemClick(index);
}}>
{item.name}:<br/>
{item.data}<br/>
</div>
)
})}
</div>
)
}
}
3.3:样式:ListInfo.scss
#list-container {
display: flex;
.card{
background-color: #26A5F8;
cursor: pointer;
margin-top: 20px;
margin-left: 30px;
padding: 10px;
font-weight: bold;
font-size: 24px;
border-radius: 10px;
box-shadow: #61dafb 2px 2px 10px 2px;
}
}
4.右栏的控制界面:
右侧控制.png4.1:数据样式:Flex.js
this.state = {
flexObj: '',
ctrl: [
{
data: 10,
info: "条目数量",
fun: this.onCountChanged.bind(this)
},
{
data: 1000,
info: "容器宽度",
fun: this.onBoxWidthChanged.bind(this)
},
{
data: 300,
info: "容器高度",
fun: this.onBoxHeightChanged.bind(this)
},
{
data: "auto",
info: "条目宽度",
fun: this.onItemWidthChanged.bind(this)
},
{
data: "auto",
info: "条目高度",
fun: this.onItemHeightChanged.bind(this)
}
]
}
4.2:接收数据,渲染界面+回调CtrlBox.js
import React, {Component} from 'react';
import './CtrlBox.scss'
class CtrlBox extends Component {
render() {
return (
<div className="right-ctrl">
{this.createItem(this.props.ctrl)}
</div>
)
}
createItem(ctrl) {
return (
ctrl.map((item, index) => {
return (
<div className={"container"} key={index}>
<label>{this.props.ctrl[index].info}:</label>
<input
onChange={
(v) => {
this.bindCallback(index, v);
}}
defaultValue={this.props.ctrl[index].data}/>
<label>px</label>
</div>
);
})
)
}
/**
* 绑定回调事件
* @param index
* @param v
*/
bindCallback(index, v) {
switch (index) {
case 0:
this.props.onCountChanged(v.target.value);
break;
case 1:
this.props.onBoxWidthChanged(v.target.value);
break;
case 2:
this.props.onBoxHeightChanged(v.target.value);
break;
case 3:
this.props.onItemWidthChanged(v.target.value);
break;
case 4:
this.props.onItemHeightChanged(v.target.value);
break;
default:
break;
}
}
}
export default CtrlBox;
4.3、回调函数与使用:Flex.js
<CtrlBox
ctrl={this.state.ctrl}
onCountChanged={this.state.ctrl[0].fun}
onBoxWidthChanged={this.state.ctrl[1].fun}
onBoxHeightChanged={this.state.ctrl[2].fun}
onItemWidthChanged={this.state.ctrl[3].fun}
onItemHeightChanged={this.state.ctrl[4].fun}/>
/**
* 数量变化时的处理
* @param count
*/
onCountChanged(count) {
}
/**
* flex盒子宽变化时处理
* @param num
*/
onBoxWidthChanged(num) {
}
/**
* flex盒子高变化时处理
* @param num
*/
onBoxHeightChanged(num) {
}
/**
* item宽变化时处理
* @param num
*/
onItemWidthChanged(num) {
}
/**
* item高变化时处理
* @param num
*/
onItemHeightChanged(num) {
}
静态界面.png
这样静态页面和回调都实现了,下面只要对回调具体逻辑进行编写就行了
三、回调的具体逻辑
1.点击下方条目时,动态改变数据
/**
* 点击下方条目
* @param index
*/
onItemClick(index) {
switch (index) {
case 0:
flexDirection.index++;
break;
case 1:
flexWrap.index++;
break;
case 2:
justifyContent.index++;
break;
case 3:
alignItems.index++;
break;
case 4:
alignContent.index++;
break;
default:
break;
}
this.notifyChanged();
}
2.输入框的回调:
/**
* 数量变化时的处理
* @param count
*/
onCountChanged(count) {
let ctrl = this.state.ctrl;
ctrl[0].data = count;
this.setState({
ctrl
})
}
/**
* flex盒子宽变化时处理
* @param num
*/
onBoxWidthChanged(num) {
let ctrl = this.state.ctrl;
ctrl[1].data = num;
this.setState({
ctrl
});
}
/**
* flex盒子高变化时处理
* @param num
*/
onBoxHeightChanged(num) {
let ctrl = this.state.ctrl;
ctrl[2].data = num;
this.setState({
ctrl
});
}
/**
* item宽变化时处理
* @param num
*/
onItemWidthChanged(num) {
let ctrl = this.state.ctrl;
ctrl[3].data = num;
this.setState({
ctrl
});
}
/**
* item高变化时处理
* @param num
*/
onItemHeightChanged(num) {
let ctrl = this.state.ctrl;
ctrl[4].data = num;
this.setState({
ctrl
});
}
看似功能挺复杂,其实也就这点代码,重点在于数据的把握与对象的封装
我并非一开始就能把数据统筹成这样,也是遇到了,看能合并,就合并一下,零散的属性看着烦心
这也全靠Android(或java)让我对对象认识深刻,所以什么事就是有联系的,思想有了,一切好办
后记:捷文规范
1.本文成长记录及勘误表
项目源码 | 日期 | 备注 |
---|---|---|
V0.1--github | 2018-12-9 | React战记之玩转Flex布局(上篇--容器属性) |
2.更多关于我
笔名 | 微信 | 爱好 | |
---|---|---|---|
张风捷特烈 | 1981462002 | zdl1994328 | 语言 |
我的github | 我的简书 | 我的掘金 | 个人网站 |
3.声明
1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持
icon_wx_200.png