如何为组件中的每个元素绑定相同的事件而不手动逐个添加?

时间:2018-02-06 09:28:14

标签: javascript reactjs react-native

我的组件中有很多元素,因为它是一个SVG,如:

export default mySVG = ({ onPress }) => (
    <Svg>
        <Circle ref='circle1' r="40" />
        <Circle ref='circle2' r="30" />
        <Circle ref='circle3' r="34" />
        <Circle ref='circle4' r="35" />
        <Circle ref='circle5' r="100" />
        <Circle ref='circle6' />
        <Rect />
        <Path ref='path1' />
        <Circle ref='circle7' />
        <Circle ref='circle8' />
        <Circle ref='circle9' />
        <Rect />
        <Path ref='path2' />
    </Svg>
)

我想做的是将onPress事件绑定到Circle和Path中的每一个(Rect除外)。

所以我不能将事件绑定到<Svg>元素,这个代码只是一个例子,它可能更大,所以可能很难添加onPress={onPress}(或任何其他重复代码)一个接一个。

有没有办法将相同的事件自动绑定到每个事件?

编辑1: 我需要处理一些复杂的SVG,这就是我要避免将道具逐个传递给那些组件的原因,它可能是一千个组件。

点击组件后,它应该将ref作为参数传递。

我尝试在setNativePropscomponentDidMount设置事件,例如:

componentDidMount() {
    for(let key in this.refs) {
        this.refs[ key ].setNativeProps({
            onPress: this.props.onPress.bind(this, key)
        });
    }
}

但似乎无法设置事件,只能设置fill等属性。

2 个答案:

答案 0 :(得分:1)

也许你可以这样做:

const MyCircle = ({ onPress }) => {
    return <MyCircle onPress={onPress} />
};

const MyPath = ({ onPress }) => {
    return <MyPath onPress={onPress} />
};

export default mySVG = (props) => (
    <Svg>
        <MyCircle ref='circle1' {...props} />
        <MyCircle ref='circle2' {...props} />
        <MyCircle ref='circle3' {...props} />
        <MyCircle ref='circle4' {...props} />
        <MyCircle ref='circle5' {...props} />
        <MyCircle ref='circle6' {...props} />
        <Rect {...props} />
        <MyPath ref='path1' {...props} />
        <MyCircle ref='circle7' {...props} />
        <MyCircle ref='circle8' {...props} />
        <MyCircle ref='circle9' {...props} />
        <Rect {...props} />
        <MyPath ref='path2' {...props} />
    </Svg>
)

编辑:

但是你的mySVG组件的结构怎么样?它固定不变吗?那么如果你创建一个像

这样的列表可能会更容易
const svgElements = ['Circle', 'Circle', 'Circle', 'Circle', 'Circle', 'Circle', 'Rect', 'Path', 'Circle', etc...]

并使用以下函数映射:

export default ({onPress}) => {
    const svgElements = ['Circle', 'Circle', 'Circle', 'Circle', 'Circle', 'Circle', 'Rect', 'Path', 'Circle'];
    const svgContent = svgElements.map((svgElement, i) => {
        switch(svgElement) {
            case 'Circle':
                return <Circle ref={`circle${i}`} onPress={onPress} />;
            case 'Rect':
                return <Rect ref={`rect${i}`} />;
            case 'Path':
                return <Path ref={`path${i}`} onPress={onPress} />;
        }
    });
    return (
        <Svg>
            {svgContent}
        </Svg>
    )
}

答案 1 :(得分:1)

如果我理解正确,您可以做的是创建执行onPress事件的自定义组件,然后您可以直接使用该组件而不是CirclePath组件。如果您愿意,也可以覆盖onPress事件。

export default class CustomCircle extends Component {
  constructor(props) {
    super(props);
  }

  _onPress() {
    console.log('this is onPress');
    if (this.props.onPress) {
      this.props.onPress();
    }
  }

  render() {
    return <Circle { ...this.props } onPress={ this._onPress } />
  }
}
export default class CustomPath extends Component {
  constructor(props) {
    super(props);
  }

  _onPress() {
    console.log('this is onPress');
    if (this.props.onPress) {
      this.props.onPress();
    }
  }

  render() {
    return <Path { ...this.props } onPress={ this._onPress } />
  }
}
export default mySVG = ({ onPress }) => (
    <Svg>
        <CustomCircle ref='circle1' onPress={onPress} />
        <CustomCircle ref='circle2' />
        <CustomCircle ref='circle3' />
        <CustomCircle ref='circle4' />
        <CustomCircle ref='circle5' />
        <CustomCircle ref='circle6' />
        <Rect />
        <CustomPath ref='path1' />
        <CustomCircle ref='circle7' />
        <CustomCircle ref='circle8' />
        <CustomCircle ref='circle9' />
        <Rect />
        <CustomPath ref='path2' />
    </Svg>
)