尽管ReactNative不再是流行的跨平台技术,但你仍然可以看到很多公司和个人在使用它。Flutter优于Flutter,RN也有自己的一席之地。至于哪个更好,我们不做太多比较。最近在升级本书《React Native移动开发实战》。书中物品都有切换城市的功能,效果如下图所示。可以看到这个城市选择页面非常常规,包括了当前所在的城市和城市列表,右侧的SlideBar可以用来快速定位。此外,该组件还支持搜索功能。首先,让我们看一下城市列表。对于这个功能,我们可以使用SectionList组件,因为我们可以使用SectionList的ListHeaderComponent属性来实现当前定位布局,而右边字母索引的效果需要使用SectionList的scrollToLocation()函数,如图下面显示。const_scrollTo=(index,letter)=>{listViewRef?.current?.scrollToLocation({itemIndex:0,sectionIndex:index});};而搜索功能就更简单了,直接用FlatList组件显示就可以了,这里还有List功能可以用list.map循环开发。CitySelectScreen.jsimportReact,{useState,useEffect}from'react';import{View,Text,TextInput,StyleSheet,TouchableOpacity,Keyboard,}from'react-native';importPropTypesfrom'prop-types';import{CityList}from'./components';importapiRequestfrom'../../api';importHeaderfrom'../../common/Header/Header';constCitySelectScreen=({location='上海市',navigation})=>{让inputRef=null;const[城市,setCities]=useState([]);const[currentCityList,setCurrentCityList]=useState({});const[isFocused,setIsFocused]=useState(false);const[结果,setResult]=useState([]);const[关键字,setKeyword]=useState('');useEffect(()=>{getCities();},[]);constonChangeText=e=>{setKeyword(e);};constonSelectCity=city=>{setTimeout(()=>{navigation.navigate('SelectCinemaScreen',{title:city.CITY_NAME,CITY_CD:city.CITY_CD,});},200);设置结果([]);};constsearchSubmit=()=>{if(isFocused){inputRef.blur();setIsFocused(假);设置结果([]);键盘.dismiss();}else{setIsFocused(true);inputRef.focus();}};constgetCities=async()=>{leturl='https://prd-api.cgv.com.cn/product/areas/that/group';constres=awaitapiRequest.get(url);设置城市(资源);};constsearchCities=async()=>{leturl='https://prd-api.cgv.com.cn/product/areas/that/group';constparams={条件:关键字};constres=awaitapiRequest.get(url,params);控制台日志(资源[0].数据);setResult(res[0].data);};constonCurrentPress=(name='上海市')=>{cities.map(item=>item.data.map(val=>{if(val.CITY_NAME===name){onSelectCity(val);returnnull;}}),);};constrenderSearchView=()=>{return({inputRef=c;}}onChangeText={onChangeText}returnKeyType="search"onSubmitEditing={()=>{if(关键字){searchCities();}}}onFocus={()=>setIsFocused(true)}placeholder="输入城市名称或拼音"/>searchSubmit(isFocused)}>{!isFocused?'搜索':'取消'});};return({renderSearchView()}{(!isFocused&&!keyword&&keyword.length<1)||!isFocused?():()});};constSearchResult=({list,onSelectCity})=>{return({list.map((item,index)=>({onSelectCity(item);}}>{item.CITY_NAME}))});};conststyles=StyleSheet.create({container:{flex:1,flexDirection:'column',},searchView:{height:48,flexDirection:'row',backgroundColor:'#fff',alignItems:'center',paddingLeft:10,paddingRight:10,},searchTxt:{颜色:'#FC5869',marginRight:5,fontSize:16,},rowView:{backgroundColor:'#fff',height:44,paddingLeft:13,justifyContent:'center',},leftIcon:{width:28,height:28,paddingLeft:13,},});CitySelectScreen.propTypes={城市:PropTypes.array,getCities:PropTypes.func,};exportdefaultCitySelectScreen;CityList.js代码如下:importReact,{useEffect,useRef}from'react';import{View,SectionList,TouchableOpacity,StyleSheet,Text,Image,Dimensions,}from'react-native';从'prop-types'导入PropTypes;从'../../../../common/ItemSeparator'导入ItemSeparatorComponent;从'../../../..导入位置/assets/images/home/location.png';从'../../../../assets/images/home/refresh.png'导入刷新;const{width}=Dimensions.get('window');constpropTypes={关键字:PropTypes.string,onChangeTextKeyword:PropTypes.func,};constdefaultProps={};constCityList=({onSelectCity,allCityList=[],currentCity,onCurrentCityPress,position:_position,})=>{constlistViewRef=useRef(null);}useEffect(()=>{console.log(allCityList);},[]);constcity=currentCity&¤tCity.city?currentCity.city:'定位失败,请手动选择城市';const_cityNameClick=cityJson=>{onSelectCity(cityJson);};constgetLocation=async()=>{//awaitPermissionsAndroid.request(//PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,//);//constres=awaitGeocode.reverse({//纬度:'29.604451007313266',//经度:'106.52727499999997',//});//_position(res);};constCityHeader=props=>{const{currentCity='上海',onCurrentCityPress}=props;return(<文本样式={{fontSize:15}}>当前城市onCurrentCityPress(currentCity)}style={styles.headerContainer}>{currentCity}文本>getLocation()}>);};const_renderListRow=(cityJson,rowId)=>{return(_cityNameClick(cityJson.item)}>{cityJson.item.CITY_NAME});};const_scrollTo=(index,letter)=>{listViewRef?.current?.scrollToLocation({itemIndex:0,sectionIndex:index});};const_renderRightLetters=(letter,index)=>{return({_scrollTo(index,letter);}}><查看style={styles.letter}>{letter});};return(({length:44,offset:44*index,index,})}ListHeaderComponent={}ref={listViewRef}sections={allCityList}keyExtractor={(item,index)=>index.toString()}renderItem={_renderListRow}ItemSeparatorComponent={()=>}renderSectionHeader={({section:{name}})=>({name})}stickySectionHeadersEnabled={true}/>{allCityList.map((item,index)=>_renderRightLetters(item.name,index),)}查看>);};conststyles=StyleSheet.create({container:{flex:1,backgroundColor:'#F4F4F4',},sectionTitle:{paddingVertical:5,paddingLeft:12,backgroundC颜色:'#F3F4F5',},iconContainer:{height:40,justifyContent:'center',alignItems:'center',},leftIconContainer:{marginEnd:12,},rightIconContainer:{marginStart:8,},headerView:{width:width,display:'flex',flexDirection:'row',position:'relative',alignItems:'center',backgroundColor:'#fff',},leftIcon:{width:15,height:13,marginLeft:15,marginRight:5,},rowView:{paddingLeft:12,backgroundColor:'#fff',},rowData:{width:宽度,height:44,justifyContent:'center',},headerContainer:{flexDirection:'行',justifyContent:'space-between',alignItems:'center',backgroundColor:'#fff',paddingHorizo??ntal:12,height:44,},headerLeft:{flexDirection:'row',alignItems:'center',},letter:{marginBottom:3,},letterSpace:{位置:'absolute',right:4,bottom:0,top:0,justifyContent:'center',},});CityList.propTypes=propTypes;CityList.defaultProps=defaultProps;exportdefaultCityList;另外,我们的网络请求使用了axios,相关内容可以参考我之前文章的介绍:ReactNative使用axios进行网络请求源码:https://github.com/xiangzhihong/rn_city