在本机中订阅侦听器的一般解决方案

时间:2018-06-27 07:32:49

标签: reactjs react-native

是否有一种可重用的方式来订阅监听器,例如键盘事件。

实际上,我在屏幕的最底部有一个绝对位置的按钮,当键盘弹出时,它浮在顶部,看起来不太好。

因此,当键盘可见时,我将隐藏该按钮,但是如果您在多个屏幕上都有类似的情况,那么现在在每个屏幕上添加订阅都变得很麻烦,我正在这样做。

<form id="form" name="form" action="test.php" method="post">
        <input id="writer" type="text" name="writer" value="" placeholder="writer" /> <br />
        <textarea id="content" name="content" placeholder="content" ></textarea> <br />
        <button type="button" >Submit (no action)</button>
</form>
<button type="button" onClick="changeValue(this, 'content')">Change Content</button>

我不喜欢上述解决方案,因为我必须向我要订阅键盘事件的每个组件添加与订阅相关的代码,而我对javascript还是陌生的,并且仍在学习它。

如果有任何人可以帮助我提供一些一般的解决方案,那就很好了。

1 个答案:

答案 0 :(得分:1)

在这些情况下,自定义组件会派上用场。您可以创建一个实现了所需行为的单个组件,然后将该组件添加到要使用的屏幕中。

样品

export default class CustomButton extends Component {
  state = {
    visible: true
  }
  componentDidMount() {
    // subscribing to keyboard listeners on didMount
    this.keyboardDidShowListener = Keyboard.addListener(
      'keyboardDidShow',
      () => this._toggleVisiblity(false)
    );

    this.keyboardDidHideListener = Keyboard.addListener(
      'keyboardDidHide',
      () => this._toggleVisiblity(true)
    );
  }
  _toggleVisiblity = (visible) => {
    this.setState({ visible })
  }
  componentWillUnmount() {
    // unsubscribing listeners on unMount

    this.keyboardDidShowListener.remove();
    this.keyboardDidHideListener.remove();
  }
  render() {
    if (this.state.visible === false) return null
    return (
      <View
        style={{
          flex: 1,
          justifyContent: 'flex-end',
        }}>
        <AnimatedBottomButton
          title="Done"
          onPress={() => Actions.pop()}
          style={{
            opacity: this.anim5,
            transform: [{ scale: this.anim5 }],
            marginBottom: Utils.isPhoneX() ? Metrics.doubleBaseMargin : 0,
          }}
        />
      </View>
    );
  }
}

class Profile extends Component {
  render() {
    return (
      <ScrollView
        style={styles.containerStyle}
        bounces={false}
        contentContainerStyle={{ flex: 1 }}
        keyboardShouldPersistTaps="handled">
        {this.renderUserImage()}
        {this.renderUserDetail()}
        <CustomButton />
      </ScrollView>
    );
  }
}

如果愿意,可以走更远一点,并创建一个HOC

样品

const withKeyboardEvents = WrappedComponent => {
  return class extends Component {
    state = {
      visible: true,
    };
    componentDidMount() {
      this.keyboardDidShowListener = Keyboard.addListener(
        'keyboardDidShow',
        () => this._toggleVisiblity(false)
      );
      this.keyboardDidHideListener = Keyboard.addListener(
        'keyboardDidHide',
        () => this._toggleVisiblity(true)
      );
    }
    _toggleVisiblity = visible => {
      this.setState({ visible });
    };
    componentWillUnmount() {
      this.keyboardDidShowListener.remove();
      this.keyboardDidHideListener.remove();
    }
    render() {
      return (
        <React.Fragment>
          {this.state.visible === true && (
            <View
              style={{
                flex: 1,
                justifyContent: 'flex-end',
              }}>
              <AnimatedBottomButton
                title="Done"
                onPress={() => Actions.pop()}
                style={{
                  opacity: this.anim5,
                  transform: [{ scale: this.anim5 }],
                  marginBottom: Utils.isPhoneX() ? Metrics.doubleBaseMargin : 0,
                }}
              />
            </View>
          )}
          <WrappedComponent />
        </React.Fragment>
      );
    }
  };
};

class Profile extends Component {
  render() {
    return (
      <ScrollView
        style={styles.containerStyle}
        bounces={false}
        contentContainerStyle={{ flex: 1 }}
        keyboardShouldPersistTaps="handled">
        {this.renderUserImage()}
        {this.renderUserDetail()}
      </ScrollView>
    );
  }
}
export default withKeyboardEvents(Profile)