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>