Javascript React和real-DOM在js中的协作
我正在尝试使用React withJavascript React和real-DOM在js中的协作,javascript,reactjs,Javascript,Reactjs,我正在尝试使用React withShapleJS地图库,我不知道如何最好地实现这一点 我知道那里有一个react-lippergithub项目,但就我而言,我需要使用raw(javaScript)lipperjs库(以便使用更多不受支持的功能,例如在标记上支持html的divIcon:) 我编写的以下代码肯定不是React方式(因为它删除和卸载所有内容,然后重新创建和装载所有内容),但它可以正常工作(经过数小时的尝试和错误) 我在地图上有大约300个标记(汽车),我用不同的标准隐藏了其中的一些
ShapleJS
地图库,我不知道如何最好地实现这一点
我知道那里有一个react-lipper
github项目,但就我而言,我需要使用raw(javaScript)lipperjs
库(以便使用更多不受支持的功能,例如在标记上支持html的divIcon:)
我编写的以下代码肯定不是React方式(因为它删除和卸载所有内容,然后重新创建和装载所有内容),但它可以正常工作(经过数小时的尝试和错误)
我在地图上有大约300个标记(汽车),我用不同的标准隐藏了其中的一些。我还从服务器检索稍微更新的数据
问题是,在我使用unmountComponentAtNode
方法之前,React开发工具显示每个Reender上添加了300个组件。因此,我有3000个组件,尽管它们的底层(真正的DOM)div被window.map.carsLayerGroup.clearLayers()删除,但它们在某个时候还在增长;方法
因此:
componentWillUpdate() {
const {props, state} = this;
const {cars} = props;
cars.map((car,i) => { //Clean the previous React components
try {
React.unmountComponentAtNode(document.getElementById(`s${car.id}`));
}
catch (e) {
//do nothing, continue execution
}});
window.map.carsLayerGroup.clearLayers();
cars.map((car,i) => {
var myIcon = L.divIcon({
//className: '',
iconSize: [24, 24],
html: `<div id="s${car.id}"></div>`,
});
var ang = 45;
var lat = car.lat+0.02220,
lon = car.lon+0.02220;
var marker = L.marker([lat, lon], {icon: myIcon});
window.map.carsLayerGroup.addLayer(marker);
if (myData.filters[`checkCarsOfType${car.type}`])
React.render(<Car key={car.id} car={car} carIndex={i} {...props}/>,document.getElementById(`${car.id}`));
});
componentWillUpdate(){
const{props,state}=this;
const{cars}=道具;
cars.map((car,i)=>{//清洁前面的React组件
试一试{
React.unmountComponentAtNode(document.getElementById(`s${car.id}');
}
捕获(e){
//什么也不做,继续执行
}});
window.map.carsLayerGroup.clearLayers();
cars.map((car,i)=>{
var myIcon=L.divIcon({
//类名:“”,
iconSize:[24,24],
html:``,
});
var ang=45;
var lat=轿厢lat+0.02220,
lon=car.lon+0.02220;
var marker=L.marker([lat,lon],{icon:myIcon});
window.map.carsLayerGroup.addLayer(marker);
if(myData.filters[`checkCarsOfType${car.type}`]
React.render(,document.getElementById(`${car.id}`));
});
移除DOM“DIVs”(通过外部库)不应该也自动“卸载”相关的已装载组件吗?有办法吗
我知道除了自己监控和检查DOM节点之外,没有其他方法可以实现自动化
如果没有,是否有一种方法可以在不循环的情况下将所有300多个Car组件一起卸载?例如,React.unmountComponents(“Car”)之类的东西
我不这么认为,但我对下一个问题的回答可能会解决这个问题
关于如何实现这一点有什么想法吗?每个标记的(非react)DOM DIV需要存在,因此我需要找到一种方法,使react组件呈现在那里,并使用react生命周期,而不必在每次重新加载时卸载和重新创建它
如前所述,您可以使用React-using组件对几乎任何类型的嵌套、树状数据进行建模。让我们看看在这种情况下粘贴代码的组件可能是什么样子。(注意,为了伪代码,我在这里做了一些假设;还请注意,我对传单API不是很熟悉:)
类myleafletmapp扩展了React.Component{
render(){
}
}
类CarMap扩展了React.Component{
render(){
{this.props.cars.map(this.renderCar)}
}
渲染器(汽车,idx){
返回;
}
}
类映射扩展了React.Component{
构造函数(){
超级();
this.state={mapCreated:false};
}
componentDidMount(){
var mapElement=React.findDOMNode(this.refs.map);
this.map=L.map(mapElement,{…});
this.setState({mapCreated:true});
}
组件将卸载(){
//清理地图
}
render(){
//确保每个孩子都知道地图;
//在贴图存在之前不要渲染子对象
儿童;
if(this.state.mapCreated){
var map=this.map;
children=React.children.map(this.props.children,(child)=>{
返回子元素?React.cloneElement(子元素,{map:map}):null;
});
}否则{
children=null;
}
返回{children};
}
}
类扩展了React.Component{
构造函数(){
超级();
此.state={
divIconHtml:React.renderToStaticMarkup(
谢谢,我不知道你在最后一段中的意思。我不明白有状态的React组件如何处理divIcon变异问题,等等@user2078023唯一支持这种自定义标记的内置层是divIcon
,不能变异,但我相信可以创建一个使用更改的DOM包装有状态的React组件。
class MyLeafletMapApp extends React.Component {
render() {
<CarMap cars={arrayOfCarsFromSomewhere} />
}
}
class CarMap extends React.Component {
render() {
<LeafletMap>
{this.props.cars.map(this.renderCar)}
<LeafletMap>
}
renderCar(car, idx) {
return <CarIcon key={car.id} index={idx} car={car} />;
}
}
class LeafletMap extends React.Component {
constructor() {
super();
this.state = { mapCreated: false };
}
componentDidMount() {
var mapElement = React.findDOMNode(this.refs.map);
this.map = L.map(mapElement, {...});
this.setState({mapCreated: true});
}
componentWillUnmount() {
// clean up the map
}
render() {
// make sure each child knows about the map;
// don't render children until map exists
var children;
if (this.state.mapCreated) {
var map = this.map;
children = React.Children.map(this.props.children, (child) => {
return child ? React.cloneElement(child, {map: map}) : null;
});
} else {
children = null;
}
return <div ref="map">{children}</div>;
}
}
class CarIcon extends React.Component {
constructor() {
super();
this.state = {
divIconHtml: React.renderToStaticMarkup(
<Car car={this.props.car} carIndex={this.props.index}
)
};
}
componentDidMount() {
this.createMarker();
}
componentWillUnmount() {
this.props.map.removeLayer(this.marker);
}
createMarker() {
if (this.marker) {
this.props.map.removeLayer(this.marker);
}
this.icon = L.divIcon({
iconSize: [24, 24],
html: React.renderToString(
<Car car={this.props.car} carIndex={this.props.index} />
)
});
this.marker = L.marker(this.getLatLng(), {icon: this.icon});
this.props.map.addLayer(this.marker);
}
componentWillReceiveProps(nextProps) {
// `carIsDifferent` not implemented in this example
if (carIsDifferent(nextProps.car, this.props.car) {
this.setState({
divIconHtml: React.renderToStaticMarkup(
<Car car={nextProps.car} carIndex={nextProps.index} />
)
});
}
}
componentDidUpdate(prevProps, prevState) {
if (prevState.divIconHtml !== this.state.divIconHtml) {
// If the HTML changed, we need to recreate the marker.
this.createMarker();
} else {
// otherwise, we can keep the same marker, just move it
this.marker.setLatLng(this.getLatLng());
}
}
getLatLng() {
return [ ... ];
}
render() {
return null; // don't render anything, we attach to the map
}
}