react实战 : 用矩阵思想做一个自适应布局容器组件
需求是这样的。
- 有一个需要显示若干方块型元素的小区域
- 数量比较少的时候显示一排
- 数量比较多的时候显示两排
用 grid 不好,因为当数量为奇数的时候需要两排里面的元素都乖乖的居中显示。
用 flex 的话,直接写需要写很多判断,因为行数不同的时候页面结构也会不同。
所以,我想到用二维数组(矩阵)来表示在什么时候想怎样显示。
上代码。
// 波浪效果测试 import React from 'react' import Styles from './index.less' import Wave from '../wave/index.js' import { Flex } from 'antd-mobile' class WaveContainer extends React.Component { constructor(props){ super(props) this.state = { } } render(){ console.log(this.props.dataBar) const baseFlex = { display: 'flex', justifyContent: 'center', alignItems: 'center' } const theStyle = { main:{ ...baseFlex, width:'17.552vw', height:'10.521vw', color:"#fff" }, tem:{ ...baseFlex, flex:"auto", color:'#fff' }, shellA:{ ...baseFlex, width:'100%', height:'100%' }, shellB:{ ...baseFlex, width:'100%', height:'50%' } } const dataBar = this.props.dataBar const Container = ((dataBar) => { const flexMatrix = [ [0,0], [1,0], [2,0], [3,0], [2,2], [3,2], [3,3], [4,3], [4,4], [5,4], [5,5], [6,5], [6,6] ] const sData = dataBar.data.sData const length = sData.length const matrix = flexMatrix[length] ? flexMatrix[length] : flexMatrix[12] if (matrix[0] === 0) { return "" } let temShell, temA, temB temA = sData.slice(0, matrix[0]).map((item, index) => <div style={theStyle.tem} key={index.toString()}> <Wave data={item} /> </div> ); if (matrix[1] === 0) { temB = "" } else { temB = sData.slice(matrix[0], (matrix[0] + matrix[1])).map((item, index) => <div style={theStyle.tem} key={index.toString()}> <Wave data={item} /> </div> ); } if (matrix[1] === 0) { temShell = <div style={theStyle.shellA} > {temA} </div> } else { temShell = [0,0].map((item, index) => <div style={theStyle.shellB} key={"temShell" + index.toString()}> {index === 0 ? temA : temB} </div> ); theStyle.main.flexWrap = "wrap" } console.log(temShell) return temShell })(dataBar) return ( <div style={theStyle.main}> {/* <Wave /> */} { Container } </div> ); } } export default WaveContainer
稍微解释一下。
- 用展开运算符使样式更简洁。
-
flexMatrix 就是记录数据的矩阵。
-
temA, temB 是放一行元素的容器。
-
temShell 是放 temA, temB 的容器。
-
theStyle.main.flexWrap = "wrap" 让元素可以正常换行。
-
slice 的作用是分割数据对象,一行只渲染一行需要的那些数据。
-
[0,0] 是因为需要两行,所以用有两个元素的数组,用 map 输出 JSX。
然后是从页面传入的数据的代码。
render(){ const dataBar = { data:{ sData:[ { name: 'a', data: 55, color:'rgb(79,239,223)' }, { name: 'b', data: 5, color:'rgb(79,239,223)'}, { name: 'c', data: 36, color:'rgb(79,239,223)'}, { name: 'd', data: 476, color:'rgb(87,207,30)'}, { name: 'e', data: 226, color:'rgb(79,239,223)'}, { name: 'f', data: 273, color:'rgb(251,211,36)'} ] } } return ( <div className={Styles.main}> <WaveContainer dataBar={dataBar} /> </div> ); }
其实和他也没什么关系。因为直接把对象传入了更里面的元素。
以上。
posted on 2019-11-19 22:43 fox_charon 阅读(735) 评论(0) 编辑 收藏 举报