背景
在预期的计划中,响应式和移动端适配是等到项目完成之后再完善的,但在写Home的时候有段时间一直在写布局,也就顺便把已经写好的界面重构为响应式。
目前已适配pad端,并没有继续向其它移动设备适配的打算
方法
主要采取了css与js方法对组件重构,以达到响应式效果
css方法
使用媒体查询@media
,检测临界尺寸切换组件样式,以Home页为例
@media screen and (max-width: 1280px) {
.half-block {
width: 100%;
}
.light-header {
padding: 0 0px 0 36px;
}
}
@media screen and (max-width: 960px) {
.project-nav {
display: none;
}
.half-block,
.one-line-block {
padding-left: 12px;
}
.home-page {
width: 100%;
}
}
- 当width缩小到1280px时,右侧两栏布局变为一栏布局,调整顶部导航栏padding细节
- 当width缩小到960px时,左侧项目选择器隐藏,仅保留顶部选择器,整个页面变成上下布局
js方法
因为顶部导航栏使用了antd提供的Menu组件,以及使用了栅格布局,不便直接通过css进行调整,所以决定使用javascript来实现顶部导航栏的响应式。
首先在导航栏中,因为使用了栅格布局,所以在 width
较大的一定范围内,可以实现响应式栅格布局。在小于某个尺寸后,Menu会被一步步逐渐折叠,这种部分折叠、部分不折叠的样式对于交互十分不友好。后来打算使用设置xs
l
xl
等属性来解决问题,但因为自己在标题的布局中使用了flex
属性,而antd的栅格无法同时支持响应式与flex。所以决定编写代码自己解决边界问题。
将标题栏内容部分组件化:
//App.js
<Header className="light-header" style={{position:'fixed',width:'100%'}}>
<FlexRow flex={flex} flexComponent={components}/>
</Header>
//FlexRow.js
class FlexRow extends React.Component {
constructor(props) {
super(props);
this.state = {
windowWidth: 1920
};
}
componentDidMount() {
this.setState({
windowWidth: window.innerWidth
})
window.addEventListener('resize', () => this.handleResize());
}
componentWillUnmount() {
window.removeEventListener('resize', () => this.handleResize());
}
handleResize() {
this.setState({
windowWidth: window.innerWidth
})
}
render() {
return (
<div>
<Row>
<Col flex={this.props.flex[0]}>
{this.props.flexComponent[0]}
</Col>
<Col flex={this.props.flex[1]}>
{this.props.flexComponent[1]}
</Col>
<Col flex={this.props.flex[2]}>
{this.props.flexComponent[2]}
</Col>
<Col flex={this.state.windowWidth>960?this.props.flex[3]:'74px'}>
{this.props.flexComponent[3]}
</Col>
</Row>
</div>
);
}
}
通过对window绑定resize监听,在页面大小发生变化后,获取页面大小,在960px这一临界值上下采用不同的栅格布局,配合css中编写的顶部导航栏padding样式,达到自然的响应式效果。