Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React和real-DOM在js中的协作_Javascript_Reactjs - Fatal编程技术网

Javascript React和real-DOM在js中的协作

Javascript React和real-DOM在js中的协作,javascript,reactjs,Javascript,Reactjs,我正在尝试使用React withShapleJS地图库,我不知道如何最好地实现这一点 我知道那里有一个react-lippergithub项目,但就我而言,我需要使用raw(javaScript)lipperjs库(以便使用更多不受支持的功能,例如在标记上支持html的divIcon:) 我编写的以下代码肯定不是React方式(因为它删除和卸载所有内容,然后重新创建和装载所有内容),但它可以正常工作(经过数小时的尝试和错误) 我在地图上有大约300个标记(汽车),我用不同的标准隐藏了其中的一些

我正在尝试使用React with
ShapleJS
地图库,我不知道如何最好地实现这一点

我知道那里有一个
react-lipper
github项目,但就我而言,我需要使用raw(javaScript)
lipperjs
库(以便使用更多不受支持的功能,例如在标记上支持html的divIcon:)

我编写的以下代码肯定不是React方式(因为它删除和卸载所有内容,然后重新创建和装载所有内容),但它可以正常工作(经过数小时的尝试和错误)

我在地图上有大约300个标记(汽车),我用不同的标准隐藏了其中的一些。我还从服务器检索稍微更新的数据

问题是,在我使用
unmountComponentAtNode
方法之前,React开发工具显示每个Reender上添加了300个组件。因此,我有3000个组件,尽管它们的底层(真正的DOM)div被window.map.carsLayerGroup.clearLayers()删除,但它们在某个时候还在增长;方法

因此:

  • 移除DOM“DIVs”(通过外部库)是否也应该自动“卸载”相关的已装载组件?有没有办法做到这一点

  • 如果没有,是否有一种方法可以将所有300多个汽车部件一起卸下而不循环?例如,React.unmountComponents(“Car”)之类的内容。因为我的循环不是完全证明:当我检索新数据时,一些旧项目仍将保持装载状态,因为它们不会出现在将循环卸载的新列表中

  • 关于如何处理这个问题有什么想法吗?每个标记的(非react)DOM DIV需要存在,因此我需要找到一种方法,使react组件呈现在那里,并使用react生命周期,而不必卸载它并在每个重新渲染器上重新创建它

  • 谢谢大家!

    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
      }
    }