React Navigation源代码阅读 : navigators/StackNavigator.js

import React from 'react';
import createNavigationContainer from '../createNavigationContainer';
import createNavigator from './createNavigator';
import CardStackTransitioner from '../views/CardStack/CardStackTransitioner';
import StackRouter from '../routers/StackRouter';
import NavigationActions from '../NavigationActions';

// A stack navigators props are the intersection between
// the base navigator props (navgiation, screenProps, etc)
// and the view's props
/**
 *  HOC,用于创建一个栈式导航器
 *  1.一个栈式导航器首先是一个 Navigator
 *  2.一个栈式导航器还是一个 NavigationContainer
 *  3.一个栈式导航器内部使用了一个 CardStackTransitioner 组件来渲染屏幕/场景组件
 *  3.1 CardStackTransitioner 将所要渲染的每个屏幕/场景组件组织的像一个卡片 Card,所有的这
 * 些卡片使用栈方式管理,参考 CardStack
 *  3.2 CardStackTransitioner 同时也负责每个卡片切换时的动作过渡效果
 *  3.3 CardStackTransitioner 不负责路由状态的管理,路由状态的管理由绑在导航器上的
 * StackRouter router来负责
 *  4.一个栈式导航器内部创建了一个 StackRouter router 来管理路由状态,并将其添加到了内部
 * 使用的 CardStackTransitioner 组件上
 *
 *  * @param routeConfigMap 路由配置参数
 * @param stackConfig 其它路由器设置参数
 * @returns {NavigationContainer}
 */
export default (routeConfigMap, stackConfig = {}) => {
    // 从 stackConfig 中获取各个参数项
    const {
        initialRouteKey,//初始路由的key
        initialRouteName,// 初始路由的名称
        initialRouteParams, // 初始路由的参数
        paths, // 每个路由的路径定义
        // 屏幕头部模式:float(独立于屏幕组件浮动),screen(嵌在屏幕顶部跟随屏幕),none(关闭头部)
        headerMode, 
        headerTransitionPreset,
        mode, // 屏幕模式:card(卡片模式),modal(模态)
        cardStyle,
        transitionConfig,//屏幕切换过渡参数设置
        onTransitionStart, // 屏幕切换过渡动画开始回调
        onTransitionEnd, // 屏幕切换过渡动画结束回调
        navigationOptions, // 导航选项参数
    } = stackConfig;

    // 构造栈式路由器要使用的参数
    const stackRouterConfig = {
        initialRouteKey,
        initialRouteName,
        initialRouteParams,
        paths,
        navigationOptions,
    };

    // 创建栈式路由器
    const router = StackRouter(routeConfigMap, stackRouterConfig);

    // 创建导航器组件,使用 CardStackTransitioner 做为其所渲染的View,
    // 而 CardStackTransitioner 最终会把各个路由使用卡片栈的方式管理和渲染(CardStack,Card)
    // CardStackTransitioner 同时也处理屏幕切换时的动画过渡以及相应的动画事件回调
    // Create a navigator with CardStackTransitioner as the view
    const navigator = createNavigator(router, routeConfigMap, stackConfig)(
        props => (
            <CardStackTransitioner
                {...props}
                headerMode={headerMode}
                headerTransitionPreset={headerTransitionPreset}
                mode={mode}
                cardStyle={cardStyle}
                transitionConfig={transitionConfig}
                onTransitionStart={onTransitionStart}
                onTransitionEnd={(lastTransition, transition) => {
                    // 注意,这里动画结束时并不是直接调用外部指定的回调 onTransitionEnd,
                    // 而是先向路由器 router 派送一个事件 completeTransition ,用于结束屏幕
                    // 过渡状态:主要是把路由器中路由状态的是否在屏幕过渡中标记 isTransitioning
                    // 修改为 false,(isTransitioning 设置为 true 是在用户交互时触发的 
                    // navigate/push/pop/back 等动作的处理逻辑中计算出来并设置的)
                    const {state, dispatch} = props.navigation;
                    dispatch(NavigationActions.completeTransition({key: state.key}));

                    // 现在屏幕切换过渡结束了(相关的状态数据已经修改+ 过渡动画已经完成),
                    // 现在调用外部指定的动画结束回调函数 onTransitionEnd (如果指定了的话)
                    onTransitionEnd && onTransitionEnd(lastTransition, transition);
                }}
            />
        )
    );
    // 为导航器做增强,使其具有 navigation 属性,并在导航状态
    // 没有从上面传入时管理导航状态,从而使其可以作为顶层组件使用
    return createNavigationContainer(navigator);
};

猜你喜欢

转载自blog.csdn.net/andy_zhang2007/article/details/80372056