import React from 'react';
import invariant from '../../utils/invariant';
import AnimatedValueSubscription from '../AnimatedValueSubscription';
const MIN_POSITION_OFFSET = 0.01;
/**
* Create a higher-order component that automatically computes the
* `pointerEvents` property for a component whenever navigation position
* changes.
*
* 该文件定义并导出了这样一个高阶组件(HOC):
* 1. 这是一个容器组件 Container ;
* 2. 这个容器组件 Container 只封装一个传入的组件 Component ,也只渲染这个组件 ;
* 3. 一旦导航位置 navigation position 发生变化,会重新计算属性 pointerEvents
* 并设置到所封装的组件 Component ;
*
*/
export default function create(Component) {
class Container extends React.Component {
constructor(props, context) {
super(props, context);
this._pointerEvents = this._computePointerEvents();
}
componentWillMount() {
this._onPositionChange = this._onPositionChange.bind(this);
this._onComponentRef = this._onComponentRef.bind(this);
}
componentDidMount() {
// 组件挂载时绑定 props.position 动画值变化监听器
this._bindPosition(this.props);
}
componentWillUnmount() {
// 组件将要卸载时删除 props.position 动画值变化监听器
this._positionListener && this._positionListener.remove();
}
componentWillReceiveProps(nextProps) {
// 当前组件的属性发生变化时重新绑定对属性 props.position 动画值
// 的变化监听
this._bindPosition(nextProps);
}
render() {
this._pointerEvents = this._computePointerEvents();
return (
<Component
{...this.props}
pointerEvents={this._pointerEvents}
onComponentRef={this._onComponentRef}
/>
);
}
_onComponentRef(component) {
this._component = component;
if (component) {
invariant(
typeof component.setNativeProps === 'function',
'component must implement method `setNativeProps`'
);
}
}
/**
* 创建一个监听器,监听 props.position 动画值的变化,
* 一旦有变化执行相应的逻辑 this._onPositionChange
* @param props
* @private
*/
_bindPosition(props) {
this._positionListener && this._positionListener.remove();
this._positionListener = new AnimatedValueSubscription(
props.position,
this._onPositionChange
);
}
/**
* props.position 动画值的变化事件的响应处理逻辑
* @private
*/
_onPositionChange() {
if (this._component) {
const pointerEvents = this._computePointerEvents();
if (this._pointerEvents !== pointerEvents) {
this._pointerEvents = pointerEvents;
this._component.setNativeProps({pointerEvents});
}
}
}
/**
* 重新计算属性 Pointer Event
* @returns {string}
* @private
*/
_computePointerEvents() {
const {navigation, position, scene} = this.props;
if (scene.isStale || navigation.state.index !== scene.index) {
// The scene isn't focused.
return scene.index > navigation.state.index ? 'box-only' : 'none';
}
const offset = position.__getAnimatedValue() - navigation.state.index;
if (Math.abs(offset) > MIN_POSITION_OFFSET) {
// The positon is still away from scene's index.
// Scene's children should not receive touches until the position
// is close enough to scene's index.
return 'box-only';
}
return 'auto';
}
}
return Container;
}
React Navigation源代码阅读 :views/CardStack/PointerEventsContainer.js
最新推荐文章于 2024-06-19 15:20:21 发布