React Native 的 Navigator 组件使用方式

arahant12 8年前
   <p><strong>React Native</strong>的编程思想类似于<code>iOS</code>, 导航栏也使用<code>Navigator</code>作为标识, 类似于<code>Android</code>的<code>ActionBar</code>. 导航栏作为最重要的应用组件之一, 除了处理页面导航功能以外, 还会提供<strong>页面栈</strong>的管理, 管理页面的跳入和跳出. 本文介绍一下 <a href="/misc/goto?guid=4959671243740424058">Navigator 组件</a>的使用方式.</p>    <p>关于<strong>React Native</strong>项目的启动, <a href="http://www.open-open.com/lib/view/open1461047509548.html">参考1</a>, <a href="http://www.open-open.com/lib/view/open1461047765021.html">参考2</a>.</p>    <h2>简单使用</h2>    <h3>Navigator</h3>    <p>添加 <strong>Navigator</strong> 的组件<code><Navigator/></code>. 设置方法: 初始化路由(initialRoute), 配置场景动画(configureScene), 渲染场景(renderScene). <strong>初始化路由(initialRoute)</strong>, 使用<code>FirstPage</code>页面作为首页.</p>    <pre>  <code class="language-java">// 主模块  class SimpleView extends Component {    // ...    render() {      return (        <Navigator          style={{flex:1}}          initialRoute={{component: FirstPage}}          configureScene={this.configureScene}          renderScene={this.renderScene}/>      );    }  }</code></pre>    <p><strong>配置场景动画(configureScene)</strong>: 根据路由的<code>type</code>属性, 判断使用的动画样式, 底部弹出或右侧弹出.</p>    <pre>  <code class="language-java">  /**     * 配置场景动画     * @param route 路由     * @param routeStack 路由栈     * @returns {*} 动画     */    configureScene(route, routeStack) {      if (route.type == 'Bottom') {        return Navigator.SceneConfigs.FloatFromBottom; // 底部弹出      }      return Navigator.SceneConfigs.PushFromRight; // 右侧弹出    }</code></pre>    <p><strong>渲染场景(renderScene)</strong>: 使用动态加载组件的方式. 设置加载页面的<code>navigator</code>参数, 其余使用<code>route.passProps</code>属性传递其他参数.</p>    <pre>  <code class="language-java">  /**     * 使用动态页面加载     * @param route 路由     * @param navigator 导航器     * @returns {XML} 页面     */    renderScene(route, navigator) {      return <route.component navigator={navigator}  {...route.passProps} />;    }</code></pre>    <p>也可以使用<code>静态加载组件</code>, 需要预定义组件, 没有动态加载灵活.</p>    <pre>  <code class="language-java">  /**     * 渲染场景, 通过不同参数, 设置不同页面     * @param route 路由, 场景信息     * @param navigator 导航器     * @returns {XML} 页面     */    renderScene(route, navigator) {      if (route.name == 'FirstPage') {        return <FirstPage navigator={navigator} {...route.passProps}/>      } else if (route.name == 'SecondPage') {        return <SecondPage navigator={navigator} {...route.passProps}/>      }    }</code></pre>    <h3>第一页</h3>    <p><strong>FirstPage组件</strong>: 包含<strong>导航栏标题</strong>和两个<strong>跳转按钮</strong>. 提供两种跳转动画, 右出和底部. 点击按钮调用<code>_navigate()</code>方法, 跳转到<strong>第二页</strong>.</p>    <pre>  <code class="language-java">// 第一页. 使用Component可以自动生成注释, 符合标准  class FirstPage extends Component {      // ...      render() {      return (        <View style={styles.container}>          <View style={styles.heading}>            <Text style={styles.headText}>              {'第一页'}            </Text>          </View>          <TouchableOpacity            style={styles.button}            onPress={()=>this._navigate('你好! (来源第一页:右出)')}>            <Text style={styles.buttonText}>              {'跳转至第二页(右出)'}            </Text>          </TouchableOpacity>          <TouchableOpacity            style={styles.button}            onPress={()=>this._navigate('你好! (来源第一页:底出)', 'Bottom')}>            <Text style={styles.buttonText}>              {'跳转至第二页(底部)'}            </Text>          </TouchableOpacity>        </View>      );    }  }</code></pre>    <blockquote>     <p>也可以使用<code>var FirstPage = React.createClass()</code>创建组件, 但没有使用<code>继承Component方式</code>规范, 不能自动生成注释.</p>    </blockquote>    <p><a href="https://simg.open-open.com/show/a1a7776a1e2d64453c9189e5d9cd3df3.png"><img alt="React Native 的 Navigator 组件使用方式" src="https://simg.open-open.com/show/a1a7776a1e2d64453c9189e5d9cd3df3.png"></a></p>    <p><strong><code>_navigate()</code>方法</strong>: 导航跳转, 调用<code>navigator.push()</code>方法. 传递参数<code>passProps</code>的<code>name</code>属性, <code>type</code>动画类型, <code>component</code>跳转组件.</p>    <pre>  <code class="language-java">  /**     * 给Navigator传递参数.     * @param name 参数     * @private     */    _navigate(name, type = 'Normal') {      this.props.navigator.push({        component: SecondPage,        passProps: {          name: name        },        type: type      })    }</code></pre>    <blockquote>     <p>下划线表示私有方法, 类似Java的private限定符.</p>    </blockquote>    <h3>第二页</h3>    <p><strong>SecondPage组件</strong>: 第二页, 跳出返回第一页. 调用<code>navigator.pop()</code>方法, 使用当前页面出栈, 显示上一个栈内页面.</p>    <pre>  <code class="language-java">// 第二页, 点击跳出返回第一页  class SecondPage extends Component {    render() {      return (        <View style={styles.container}>          <View style={styles.heading}>            <Text style={styles.headText}>              第二页: {this.props.name}            </Text>          </View>          <TouchableOpacity            style={styles.button}            onPress={()=>this.props.navigator.pop()}>            <Text style={styles.buttonText}>              返回上一页            </Text>          </TouchableOpacity>        </View>      );    }  }</code></pre>    <p><a href="https://simg.open-open.com/show/8e7e5b35237e3f3bf800ae8b3ef11d21.png"><img alt="React Native 的 Navigator 组件使用方式" src="https://simg.open-open.com/show/8e7e5b35237e3f3bf800ae8b3ef11d21.png"></a></p>    <p>Navigator的主要功能, 是管理页面栈, 控制页面的跳入跳出.</p>    <h2>统一导航栏</h2>    <p>对于应用而言, 需要统一的导航栏, Navigator 组件也提供导航栏的定制.</p>    <h3>Navigator</h3>    <p>与上文类似, 额外添加<code>navigationBar</code>的属性, 自定义设置导航栏, 保持所有页面的导航栏一致. 属性添加<code><NavigationBar/></code>标签, 通过<code>routeMapper</code>控制导航栏的功能和样式.</p>    <pre>  <code class="language-java">// 主模块  class UniformView extends Component {    //...      render() {      return (        <Navigator          style={{flex:1}}          initialRoute={{name: 'FirstPage', component: FirstPage}}          configureScene={this.configureScene}          renderScene={this.renderScene}          navigationBar={            <Navigator.NavigationBar              style={styles.navContainer}              routeMapper={NavigationBarRouteMapper}/>}          />      );    }  }</code></pre>    <h3>NavigationBarRouteMapper</h3>    <p><strong>NavigationBarRouteMapper</strong>: 导航栏路由映射器, 设置<strong>左键LeftButton</strong>, <strong>右键RightButton</strong>, <strong>标题Title</strong>.</p>    <pre>  <code class="language-java">// 导航栏的Mapper  var NavigationBarRouteMapper = {    // 左键    LeftButton(route, navigator, index, navState) {      // ...    },    // 右键    RightButton(route, navigator, index, navState) {      // ...    },    // 标题    Title(route, navigator, index, navState) {      return (        <View style={styles.navContainer}>          <Text style={styles.title}>            应用标题          </Text>        </View>      );    }  };</code></pre>    <p><strong>左键LeftButton</strong>: <code>index</code>属性表示当前页面的索引, 通过判断<code>index</code>属性, 获知栈内是否有其他页面, 判断<code>后退</code>按钮是否显示. 点击调用<code>navigator.pop()</code>出栈.</p>    <pre>  <code class="language-java">  // 左键    LeftButton(route, navigator, index, navState) {      if (index > 0) {        return (          <View style={styles.navContainer}>            <TouchableOpacity              underlayColor='transparent'              onPress={() => {if (index > 0) {navigator.pop()}}}>              <Text style={styles.leftNavButtonText}>                后退              </Text>            </TouchableOpacity>          </View>        );      } else {        return null;      }    },</code></pre>    <p><strong>右键RightButton</strong>: 点击调用<strong>路由(route)</strong>的<code>onPress()</code>方法, 提示信息. 根据路由的<code>rightText</code>属性添加显示文字.</p>    <pre>  <code class="language-java">  // 右键    RightButton(route, navigator, index, navState) {      if (route.onPress)        return (          <View style={styles.navContainer}>            <TouchableOpacity              onPress={() => route.onPress()}>              <Text style={styles.rightNavButtonText}>                {route.rightText || '右键'}              </Text>            </TouchableOpacity>          </View>        );    },</code></pre>    <p><a href="https://simg.open-open.com/show/94a298b3d41c8d6340cb204593e9d1ae.png"><img alt="React Native 的 Navigator 组件使用方式" src="https://simg.open-open.com/show/94a298b3d41c8d6340cb204593e9d1ae.png"></a></p>    <h3>第一页/第二页</h3>    <p>第一页与第二页与上文类似, 当第一页跳转时, 传递的路由信息有些变化, 控制第二页与导航栏的显示信息.</p>    <pre>  <code class="language-java">  // 填出提示框    onPress() {      alert("我是Spike!");    }      /**     * 跳转页面至SecondPage     * @param name 传递参数     * @param type 动画类型     */    gotoNext(name, type = 'Normal') {      this.props.navigator.push({        component: SecondPage,        passProps: {          id: name        },        onPress: this.onPress,        rightText: 'ALERT!',        type: type      })    }</code></pre>    <p>React Native 路由的基本功能就是这些, 控制页面的切换, 控制导航栏的功能. 导航栏作为应用最重要的组件之一, 一定要熟练掌握.</p>    <p>OK, that's all ! Enjoy it!</p>    <p>来源:https://github.com/SpikeKing/WclNavigator</p>