【问题标题】:How can detect that should update a property of previous object?如何检测应该更新先前对象的属性?
【发布时间】:2018-12-13 19:33:49
【问题描述】:

首先,感谢您阅读我的问题并尝试帮助我并为我的英语道歉。

我正在尝试使用 React 在 Redux 上创建一个方法来改变层的可见性。

我的问题是更改可见性完美,但是当所有图层都不可见并尝试将它们更改为可见时,它们的 before 属性未定义,除了最后一个更改。

我会用一个例子更好地解释我。

mapLayers 是一个包含 3 层的数组:

  • [2]第三层
  • 1Layer2
  • [0] 层 1

案例 1:

如果我隐藏Layer1,他的前属性未定义,现在我显示Layer1,现在他的前属性ID 为Layer2

我的问题:

  • [2]第三层
  • 1Layer2
  • [0] 层 1

3 层是不可见的,所以:

  1. Layer2 更改为可见 -> before = undefined
  2. Layer3 更改为可见 -> before = undefined
  3. Layer1 更改为可见 -> before = id of Layer2

但是当将 Layer3 更改为可见时(在第 2 步中), before 应该是未定义的,之后,当 Layer2.. before 的 Layer3 的可见性应该是 Layer2 id。

重要的是知道我正在使用 react-mapbox-gl,并且我需要在属性之前移动和隐藏/显示图层。

before: string 传递一个图层的id,会在id定义的图层之前显示当前图层。

https://github.com/alex3165/react-mapbox-gl/blob/master/docs/API.md

这是我的代码:

static changeLayerVisibility(layer) {
    let mapLayers = [... AxisStore.getStore().getState().map.mapGLlayers];
    const ids = mapLayers.map(l => l.id);
    const index = ids.indexOf(layer.id);
    const newVisibility = (layer.layout.visibility === 'visible') ? 'none' : 'visible';

    let nextVisibleLayer = mapLayers.find((layerObj, idx) => idx > index && layerObj.layout.visibility === 'visible');

    let updateLayout = Object.assign({}, mapLayers[index], {
        layout: Object.assign({}, mapLayers[index].layout, { visibility: newVisibility }),
        paint: Object.assign({}, mapLayers[index].paint),
        before: newVisibility === 'visible' && nextVisibleLayer ? nextVisibleLayer.id: undefined
    });

    mapLayers.splice(index, 1, updateLayout);

    return (dispatch) => {
        dispatch({
            type: MapTypeConstants.SET_MAP_LAYERS,
            payload: mapLayers
        });
    };
}

【问题讨论】:

    标签: javascript reactjs mapbox mapbox-gl-js


    【解决方案1】:

    实际上,我认为有更好的方法来设置你的属性。


    首先,使用一个数组来存储可见性属性。如下所示,初始值应该为false。

    interface InVisiablityProps {
       visible: Array<Boolean>
    }
    
    const initialState:InVisiablityProps = {
       invisible: [false,false,false]
    }
    

    每次将视图更改为不可见。将属性更改为 !(property)

    【讨论】:

    • 但是可以删除图层或添加新图层。我正在使用 react-mapbox-gl,这就是我之前需要属性的原因。 before: string 传递一个图层的id,它会在id定义的图层之前显示当前图层。 github.com/alex3165/react-mapbox-gl/blob/master/docs/API.md
    • 像以前一样只创建一个字符串属性,每次更改InVisiablityProps,传递id属性并将before属性更改为id。@JaviLesPaul
    • 感谢您的想法,但它最复杂,因为之前的属性可能会使应用程序崩溃;)
    【解决方案2】:

    解决方案:

    非常感谢您的帮助和想法,但我已经这样解决了。

    在 Redux 中,我创建了一个新方法来更新 before 属性,当 layer 改变了他的可见性并且未定义什么时候应该是下一个 layer 的 id。

    而且,不可能在 changeVisibility 中更新该图层,因为应该绘制(渲染)更改可见性的图层。如果不绘制,应用程序崩溃,因为之前的属性有下一层的id,下一层还没有绘制。

    REDUX:

    static changeLayerVisibility(layer) {
    
        let mapLayers = [... AxisStore.getStore().getState().map.mapGLlayers];
        const ids = mapLayers.map(l => l.id);
        const index = ids.indexOf(layer.id);
        const layoutVisibility = (layer.layout.visibility === 'visible') ? 'none' : 'visible';
    
        let nextVisibleLayer = mapLayers.find((layerObj, idx) => idx > index && layerObj.layout && layerObj.layout.visibility && layerObj.layout.visibility === 'visible');
        let updateLayout = Object.assign({}, mapLayers[index], {
            layout: Object.assign({}, mapLayers[index].layout, { visibility: layoutVisibility }),
            paint: Object.assign({}, mapLayers[index].paint),
            filter: (mapLayers[index].filter) ? Object.assign({}, mapLayers[index].filter) : {},
            before: layoutVisibility === 'visible' && nextVisibleLayer ? nextVisibleLayer.id: undefined,
            visible: (layoutVisibility === 'visible') ? true : false
        });
        if (this.updateLayout.type === 'raster') delete updateLayout.filter;
    
        mapLayers.splice(index, 1, updateLayout);
    
        return (dispatch) => {
            dispatch({
                type: MapTypeConstants.SET_MAP_LAYERS,
                payload: mapLayers
            });
        };
    }
    
    
    static updateBefore(layer) {
    
        let mapLayers = [... AxisStore.getStore().getState().map.mapGLlayers];
        const ids = mapLayers.map(l => l.id);
        const posInRedux = ids.indexOf(layer.id);
    
        let updateBeforeLayout = Object.assign({}, layer, {
            layout: Object.assign({}, layer.layout),
            paint: Object.assign({}, layer.paint),
            filter: (layer.filter) ? Object.assign({}, layer.filter) : {},
            before: (mapLayers[posInRedux + 1]) ? String(mapLayers[posInRedux + 1].id) : undefined,
            visible: layer.visible
        });
        if (this.updateBeforeLayout.type === 'raster') delete updateBeforeLayout.filter;
    
        mapLayers.splice(posInRedux, 1, updateBeforeLayout);
    
        return (dispatch) => {
            dispatch({
                type: MapTypeConstants.SET_MAP_LAYERS,
                payload: mapLayers
            });
        };
    }
    

    前端:

    changeVisibility(layer) {
        this.props.changeLayerVisibility(layer);
        let layerBeforeUndefined = this.props.mapGLlayers.find(l => l.visible === true && l.before === undefined);
        if (layerBeforeUndefined) {
            setTimeout( () => {
                this.props.updateBefore(layerBeforeUndefined);
            });
        }
    };
    

    现在,我想在前面减少代码,因为所有逻辑都必须是一个 redux,而且它必须看起来像这样:

    changeVisibility(layer) {
        let userMapboxLayers = this.props.map.getStyle().layers.filter(l => l.source && l.source.indexOf('sourceId_') !== -1);
        this.props.changeLayerVisibility(userMapboxLayers, layer);
    };
    

    【讨论】:

      猜你喜欢
      • 2013-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-04
      • 2016-08-08
      • 2020-03-16
      • 2018-12-24
      相关资源
      最近更新 更多