react native 实战系列教程_第1页
react native 实战系列教程_第2页
react native 实战系列教程_第3页
react native 实战系列教程_第4页
react native 实战系列教程_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

reactnative实战系列教程之影片数据

获取并解析fetch介绍fetch是ReactNative的一个网络请求库,使用该库不用引入模块,可以直接使用。一个简单的请求如下:fetch('http://facebook.github.io/react-native/movies.json')发起请求之后,我们还需要对它的响应进行处理,只要这样fetch('http://facebook.github.io/react-native/movies.json').then((response)=>{console.log(response)}).catch((e)=>{console.log(e)})在浏览器中打开调试工具,在Console下输入以上代码:0#■£requWH]DCStMEtrjnMfrwtffetch('/endpoint/',{method:'POST',headers:{'Accept':'application/json','Content-Type':'application/json',},body:JSON.stringify({firstParam:'yourValue',secondParam:'yourOtherValue',})})可以配置请求的方法method,头部headers和body。上面的请求都是异步的,也可以使用同步操作,如下asyncgetMoviesFromApi(){try{letresponse=awaitfetch('http://facebook.github.io/react-native/movies.json');letresponseJson=awaitresponse.json();returnresponseJson.movies;}catch(error){console.error(error);}}整个方法是异步的,但是内部的fetch请求是同步的,使用await会等待fetch返回结果response再执行下一步。记得trycatch任何异常。更多fetch相关,可以查看官方文档使用fetch获取数据打开DramaComponent.js文件,定义一个方法fetchDatafetchData(){varurl='/hanju/new';fetch(url).then((res)=>res.text()).then((html)=>{console.log(html);}).catch((e)=>{console.log(e);//在最初的render方法调用之后立即调用。//网络请求、事件订阅等操作可以在这个方法中调用。//作用相同与Fragment生命周期中的onViewCreate方法。componentDidMount(){this.fetchData();}这样我们就获取到网页html数据,接下来我们要解析html获取想要的数据。使用到的解析库是cheerio。使用cheerio解析html获取影视信息cheerio属于第三方模块,我们要使用它首先要先把它安装到我们的项目中来。cheerio依赖events模块,所以events也要安装进来。不知道依赖关系也没事,在你运行程序的时候,它就会提示你缺少了哪个module,再安装下就可以了。使用命令行cd到我们的跟目录下,然后执行命令npminstallcheerio--savenpminstallevents--save等待安装完毕之后,在DramaComponent.js中引入该模块importCheeriofrom'cheerio';然后将html加载到cheerio解析器里,利用cheerioAPI进行数据提取,通读cheerioAPI。var$=Cheerio.load(html);我们要分析提取的网站地址是/hanju/new。打开该网站,右击查看网页源代码,先自己静态分析下,该如何通过html标签获取筛选到数据。通过分析,我们发现影片列表信息存放在class为m-ddone的div标签下,并且ul的每一li标签代表一部影片,然后继续分析下去获取每一部的详细信息即可,这里就不再详细分析了。我们声明一个方法来解析这一个过程,代码如下://解析htmlresolveHtml(html){var$=Cheerio.load(html);varbody=$('div.m-ddone').find('ul');//uivardatas=[];//影视列表数据集合body.each((index,item)=>{//livardramaItem={name:'',//影片名称title:”,//标题actor:",//演员pic:'',//图片地址url:",〃详情链接};varlink=$(item).find('a');link.each((i,a)=>{//获取影片名称varaTag=$(a);if(i===0){dramaItem.pic=aTag.find('img').attr('src');dramaItem.url=aTag.attr('href');dramaItem.title=aTag.find('label.tit').text();}elseif(i===1){dramaI=aTag.text();}});varactor=$(item).find('li.zyy').text();dramaItem.actor=actor;//datas.push(dramaItem);});//最后记得刷新一下数据this.setState({movies:this.state.movies.cloneWithRows(datas),});}然后在刚才fetchData那里获取到的html传递和调用resolveHtml就可以了fetchData(){fetch(url).then((res)=>res.text()).then((html)=>{//console.log(html);this.resolveHtml(html);}).catch((e)=>{console.log(e);ok,刷新一下界面,现在已经获取到数据并显示了,如下号川■18:074orpiKicmJw■ Nasui- ■Ai^l18-TflSsi—审寒帝国KU号川■18:074orpiKicmJw■ Nasui- ■Ai^l18-TflSsi—审寒帝国KU、带畐樨遞半离地严竝惊人at肉?f,*昱is3?怅血漏FF3BJfSiL然后,你会发现,怎么好像只有一页的数据。嗯,没错,我们还要优化一下,让数据和ListView支持分页功能。我们在多分析下网站的源代码,需要的信息有:总页数、当前页、下一页的链接地址,因此,我们的数据结构修改定义为,如下:dramaList:{totalPage:l,〃总页数currPage:O,〃当前页pages:[],〃页码信息datas:[],〃影片信息列表数据}此时,constructor方法内constructor(props){super(props);this.state={movies:newListView.DataSource({rowHasChanged:(r1,r2)=>r1!=r2,}),dramaList:{totalPage:l,〃总页数currPage:O,〃当前页datas:[],〃影片信息列表数据},}}由于我们初始访问的是这个地址,因此初始化时页码信息也给初始化第一页数据。解析页码信息的关键代码如下://解析页码信息varpage=$('div.pages').find('a');page.each((i,item)=>{if(!$(m).hasClass('next')){dramaList.totalPage++;dramaList.pages.push({index:$(item).text(),url:$(item).attr('href'),});}});dramaList就是this.state.dramaList,因此数据结构改变了,我们也要把之前的datas字段改为dramaList.datas。所以此时resolveHtml方法的完整代码如下://解析htmlresolveHtml(html){var$=Cheerio.load(html);vardramaList=this.state.dramaList;//解析剧集列表varbody=$('div.m-ddone').find('ul');//uibody.each((index,item)=>{//livardramaItem={name:",//影片名称title:”,//标题actor:",//演员pic:'',//图片地址url:",〃详情链接};varlink=$(item).find('a');link.each((i,a)=>{//获取影片名称varaTag=$(a);if(i===0){dramaItem.pic=aTag.find('img').attr('src');dramaItem.url=aTag.attr('href');dramaItem.title=aTag.find('label.tit').text();}elseif(i===1){dramaI=aTag.text();}});varactor=$(item).find('li.zyy').text();dramaItem.actor=actor;//dramaList.datas.push(dramaItem);});//解析页码信息dramaList.currPage++;varpage=$('div.pages').find('a');page.each((i,item)=>{if(!$(item).hasClass('next')){dramaList.totalPage++;dramaList.pages.push({index:$(item).text(),url:$(item).attr('href'),});}});//刷新一下数据this.setState({movies:this.state.movies.cloneWithRows(dramaList.datas),dramaList:dramaList,});}由于每一页的html解析过程都一样,所以我们改造一下fetchData方法,让它传入一个url地址,url参数化。fetchData(url){url=HOST_URL+url; //省略其它代码}HOST_URL是一个const,是该网站的根地址然后还记得在介绍ListView的时候,有个方法—onEndReached是在它拉到底部会调用,是的,我们就在这个方法下去,加载下一页,实现如下:_onEndReached(){vardramaList=this.state.dramaList;vartotalPage=dramaList.totalPage;varcurrPage=dramaList.currPage;varnextPage=currPage+1;if(nextPage<=totalPage){this.fetchData(dramaList.pages[currPage].url);}}记得ListView的onEndReached要调用bind(this),否则_onEndReached的this.state.dramaList会报undefined异常最后,在componentDidMount改下调用方法componentDidMount(){varurl='/hanju/new';this.fetchData(url);}重新执行下代码,就可以看到分页效果了,如果hanju/new地址的数据没有分页,你可以把url改为其他,比如'人气'页/hanju/renqi/,它们的解析过程都一样的。写完加载更多,还有下拉刷新呢!下面我们就来讲讲下拉刷新。下拉刷新ListView有个refreshControl来设置刷新的状态,效果和Android的SwipeRefreshLayout一样。需要额外在'React-native'importRefreshControl组件,代码如下:import{ //省略其它代码RefreshControl,}from'react-native';//刷新_onRefresh(){}<ListViewdataSource={this.state.movies}renderRow={this._renderMovieView.bind(this)}style={styles.listview}initialListSize={10}pageSize={10}onEndReachedThreshold={5}onEndReached={this._onEndReached.bind(this)}enableEmptySections={true}contentContainerStyle={styles.grid}refreshControl={<RefreshControlrefreshing={this.state.isRefreshing}onRefresh={this._onRefresh.bind(this)}colors={['#f74c31','#f74c31','#f74c31','#f74c31']}progressBackgroundColor='#ffffff'/>}/>RefreshControl内有个refreshing布尔值属性,我们需要通过state来设置这个是否正在刷新的状态。constructor(props){super(props);this.state={movies:newListView.DataSource({rowHasChanged:(r1,r2)=>r1!=r2,}),dramaList:{totalPage:l,〃总页数currPage:O,〃当前页pages:[{index:1,url:'/hanju/new'}],/页码信息datas:[],〃影片信息列表数据},isRefreshing:false,//RefreshControl是否正在刷新接着,我们要处理刷新逻辑。当下拉刷新时,要将列表数据清空,初始化到最初的状态。在resolveHtml里添加如下代码:resolveHtml(l){var$=Cheerio.load(html);vardramaList=this.state.dramaList;if(this.state.isRefreshing){dramaList.currPage=0;dramaList.datas=[];}//解析剧集列表 //省略其它代码//刷新一下数据this.setState({movies:this.state.movies.cloneWithRows(dramaList.datas),dramaList:dramaList,isRefreshing:false,});}解析完数据之后,将isRefreshing状态置为false,在刷新回调的方法里fetch初始的地址//刷新_onRefresh(){this.setState({isRefreshing:true});this.fetchData('/hanju/new');}组件参数化上面我们已经将DramaComponent组件的数据获取解析全部实现了,但是我们解析的这个地址是固定写死的,这样一来这个组件就不能提供给别的组件重复使用了,所以我们要将这个地址参数化,由外部调用该组件的时候传入,具体实现如下。组件的参数是通过props设置的,我们通过propTypes定义一个string类型的url,还可以通过defaultProps设置默认初始值。staticpropTypes={url:React.PropTypes.string.isRequired,staticdefaultProps={url:'/hanju/new',}PropType有入下图这些类型atrH鬥雲(severaldefiniiticnx)boolLfunclink"0日尊nuabtrobj*ctO-f«h«Ofon«OfT^p«syabot其中常用到的string\any\array\bool\func\number关于PropType介绍接着,将初始的url都替换成/r/ps.url。两个地方要修改,一个是constructor里的state初始数据,和componentDidMount调用的fetchDataconstructor(props){super(props);this.state={movies:newListView.DataSource({rowHasChanged:(r1,r2)=>r1!=r2,}),dramaList:{totalPage:l,〃总页数currPage:O,〃当前页pages:[{index:1,url:ps.url}],〃页码信息datas:[],〃影片信息列表数据},isRefreshing:false,//RefreshControl是否正在刷新}}componentDidMount(){this.fetchData(ps.url);}最后,我们打开程序入口index.android.js,给组件DramaComponent设置一个url值classXiFanextendsComponent{render(){return(<DramaComponenturl='/hanju/new'/>);}}AppRegistry.registerComponent('XiFan',()=>XiFan);如果你组件没有设置url参数.并且组件内没有defaultFropsj那也由于DramaComponent組件把url设置成了i眾equiedd、埴参数),因此你运行之后会收到一于堇色警告-H3最后再给这个组件优化一下(养成编写代码边思考边优化的习惯!),两点:在组件请求网络并解析数据时,给它一个loading界面,加载完成后再显示结果页面。由于fetchData方法是内部重复循环调用,但是并不是每次都需要去解析页码信息的,只有第一次没有数据的时候要去解析获取页码数据。state增加loaded和hasPage参数constructor(props){super(props);this.state={movies:newListView.DataSource({rowHasChanged:(r1,r2)=>r1!=r2,}),dramaList:{totalPage:l,〃总页数currPage:O,〃当前页pages:[{index:1,url:ps.url}],〃页码信息datas:[],〃影片信息列表数据hasPage:false,〃是否有分页},isRefreshing:false,//RefreshControl是否正在刷新loaded:false,〃是否初始加载完成}}增加加载中页面和逻辑//加载中页面_renderLoadingView(){return(<Viewstyle={{flex:1,justifyContent:'center',alignItems:'center'}}>vText>加载中,请稍后...v/Text〉</View>);}render(){if(!this.state.loaded){returnthis._renderLoadingView();}return(vListView...//省略其它代码/>);}修改解析页码逻辑,并设置loaded状态//解析htmlresolveHtml(html){...//省略其它代码//解析页码信息dramaList.currPage++;if(!dramaList.hasPage)/r/

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论