在一个阵营的选项卡组件
问题描述:
管理一个地图的OpenLayers我的建筑内设有各种选项卡的导航栏SPA应用。当选中选项卡时,我会通过REDX发送一个动作,并且AppBody
组件会根据选择哪个选项卡来重新显示自己(请参阅中的renderAppBody()
)。在一个阵营的选项卡组件
我的问题是,标签必须包含的OpenLayers地图。我首先获得地图的安装方面遇到了很多麻烦,因为它必须定位DOM上已存在的元素。我这样做,通过重写componentDidMount
:
MapBody.js
import React from 'react';
import "ol/ol.css"
import Map from 'ol/map'
import View from 'ol/view'
import Tile from 'ol/layer/tile'
import OSM from 'ol/source/osm'
import "../../sass/App.scss";
var map = new Map({
layers: [
new Tile({
source: new OSM()
}),
],
view: new View({
center: [0, 0],
zoom: 4
})
});
const MapBody = React.createClass({
render: function() {
return (<div id="map"></div>);
},
componentDidMount: function() {
map.setTarget("map");
}
});
export default MapBody;
这意味着,每当我切换标签,我的地图元素被破坏/脱除,用下一个标签的内容取代。其效果是,我第一次选择渲染的地图选项卡,但如果我选择另一个选项卡,然后重新选择地图选项卡,地图将不会渲染。
是我的方法固有的缺陷的,我想要的结果?这是我第一个较大的React项目,所以我不确定如何设计这种行为。
我应该:
- 保持到地图项目的引用和reappend它重新呈现? (似乎有问题)
- 隐藏标签而不是替换它们? (似乎也有问题)
- 制作MapBody有两种状态:
visible
和inactive
。然后,它总是呈现在屏幕上,并根据其状态与CSS隐藏它(似乎哈克) - 东西更优雅?
AppBody.js
import React from 'react';
import { connect } from 'react-redux';
import Activity from '../components/body/Activity'
import CategoryBody from '../components/body/CategoryBody'
import MapBody from '../components/body/MapBody'
import Search from '../components/body/Search'
import tabs from "../actions/tabDefinitions.js"
import "../sass/App.scss";
function renderAppBody(activeTab) {
switch (activeTab) {
case tabs.T_CATEGORIES:
return <CategoryBody />
case tabs.T_MAP:
return (<MapBody />)
case tabs.T_SEARCH:
return <Search />
case tabs.T_ACTIVITY:
return <Activity />
default:
return <div>Oops! Something went wrong :(</div>
}
}
const AppBody = ({activeTab}) => (
<div className="frame_wrapper">
{renderAppBody(activeTab)}
</div>
)
const mapStateToProps = (state) => ({
activeTab: state.activeTab,
});
export default connect(mapStateToProps)(AppBody);
谢谢!
答
我最终总是加上MapBody
组分AppBody
无论所选标签的。然后,我添加了active
prop到MapBody
以添加显示/隐藏CSS类。这样地图容器不会在选项卡更改时被移除/重置,因此状态保持良好。我的方法并不觉得特别优雅(阅读:这是一个肮脏,肮脏的黑客),但它仍然有效。
我MapBody
渲染功能变成了:
render: function() {
return (<div id="map"
className={this.props.active ? "active_map" : "inactive_map"}>
</div>);
}
通过添加以下CSS 大多得到期望的行为:
.inactive_map {
display: none;
}
这引起了地图容器切换时能正确显示/隐藏标签,但地图画布是灰色的,并没有渲染任何内容。为了解决这个问题,我覆盖了componentDidUpdate()
以致电map.updateSize()
,这迫使重新计算地图视口大小。最终代码:
MapBody.js
const MapBody = React.createClass({
render: function() {
return (<div id="map"
className={this.props.active ? "active_map" : "inactive_map"}>
</div>);
},
componentDidMount: function() {
this.props.map.setTarget("map");
},
componentDidUpdate: function() {
this.props.map.updateSize();
}
});
AppBody.js
function renderAppBody(activeTab) {
switch (activeTab) {
case tabs.T_CATEGORIES:
return <CategoryBody />
case tabs.T_MAP:
return "";
case tabs.T_SEARCH:
return <Search />
case tabs.T_ACTIVITY:
return <Activity />
default:
return (<div>Oops! Something went wrong :(</div>)
}
}
const AppBody = ({activeTab}) => (
<div className="frame_wrapper">
{renderAppBody(activeTab)}
<Map active={activeTab == tabs.T_MAP}/>
</div>
)