本项目使用豆瓣的api和react的路由跳转功能实现页面的基本切换:1.可能因为豆瓣图片防盗链的关系,图片不显示;2.项目使用antd组件库进行项目页面的布局;3.在解决跨域方面使用fetch-jsonp工具
这篇博客我记录下自己的每一步操作,主要为了巩固知识点,不准确的地方请留言指出,不足之处请谅解。
项目代码地址:https://github.com/jishuaizhen/react-movie.git
顶部
顶部为首页、电影、关于导航栏,主要实现了电影部分的功能
内容区域
内容区域为电影模块下的正在热映、即将上映、top250三部分,三部分布局相似,主要是为了练习react的路由切换。
底部
底部为了配合布局,可以忽略。
1.使用antd中的layout组件进行布局
2.HashRouter,Route,Link为react路由切换主要使用的组件:HashRouter表示路由的跟容器
,所有的路由信息都要包裹在HashRouter中,一个网站内只要使用一次HashRouter即可,HashRouter中只能有一个根元素
;Route表示路由规则,Route上有两个重要的属性,path和component;Link表示路由的链接
3.Route就是我们创建的路由,path对应路径,component对应组件,Rroute为占位符
,可以直接替代Vue中的router-view; 默认情况下路由是模糊匹配的,为Route添加exact
属性表示精确匹配;如果要匹配参数,可以在匹配规则中使用:修饰符
为了保证页面刷新之后还是保留之前选择的页面,
设置defaultSelectedKeys={[window.location.hash.split('/')[1]]}
1.movie.js为中间的主要内容区域,也是使用antd中的layout组件进行布局,左侧是正在热映、即将上映、top250三栏切换,右侧是MovieList.js详细信息展示
2.MovieList.js为内容区域的右侧组件,从路由里面提取参数方法this.props.match.params
3.请求列表接口需要:电影类型、开始电影个数、每页显示多少电影个数三个参数
http://api.douban.com/v2/movie/${this.state.movieType}?start=${start}&count=${this.state.pageSize}
4.在MovieList.js组件中的state中设置对应值获取参数
constructor(props){
super(props)
this.state={
movies:[],//电影列表
nowPage:parseInt(props.match.params.page)||1,//当前显示多少页
pageSize:6,//每页显示多少数据
total:0,//当前分类总共多少数据
isLoading:true,//是否显示加载动画
movieType:props.match.params.type//显示哪一种类型电影
}
}
//......other code
loadMovie = ()=>{
const start = this.state.pageSize*(this.state.nowPage - 1)
const url = `http://api.douban.com/v2/movie/${this.state.movieType}?start=${start}&count=${this.state.pageSize}`
fetchJSONP(url)
.then(res=>res.json())
.then(data=>{
this.setState({
isLoading:false,
movies:data.subjects,
total:data.total
})
})
}
1.分页功能组件使用antd中的Pagination组件进行布局
Pagination组件需要传递当前页数,每页显示多少个电影、电影总数
2.通过在Pagination组件上绑定页面改变函数实现分页功能
pageChange=(page)=>{
// window.location.href='/#/movie/'+this.state.movieType+'/'+page
this.props.history.push('/movie/'+this.state.movieType+'/'+page)
}
//这里是两种方法,一种是操作BOM修改window.location.href值,一种是利用编程式导航修改props数据
3.修改props数据之后会触发react生命周期中componentWillReceiveProps函数
componentWillReceiveProps(nextProps){
// console.log(nextProps.match.params)
this.setState({
isLoading:true,
nowPage:parseInt(nextProps.match.params.page)||1,
movieType:nextProps.match.params.type,
},function(){
this.loadMovie()
})
}
//利用nextProps参数获取最新的NewPage和movieType的值,之后调用loadMovie
函数渲染页面
1.在MovieList.js组件是由多个MovieItem.js组件组成,这里添加了加载动画
renderList = ()=>{
if(this.state.isLoading){
return
}else{
return
{this.state.movies.map(item=>{
return
})}
}
}
//当loadMovie请求到数据之后,加载动画消失通过map方法返回MovieItem.js组件
2.MovieItem.js组件接收到参数之后进行页面渲染
render(){
return
电影名称:{this.props.title}
上映年份:{this.props.year}年
电影类型:{this.props.genres.join(',')}
3.实现点击进入电影详情页面,为每个组件绑定goDetail函数
goDetail=()=>{
this.props.history.push('/movie/detail/'+this.props.id)
}
//通过对props的操作跳转至指定路由
4.注意:detail区域和MovieList区域是重合的,为Route添加exact属性虽然会由默认的模糊匹配改为严格匹配,但是MovieList和MovieDetail路由相似,所以触发goDetail函数可能同时显示两个组件。为了解决这一问题需要在路由外使用 组件进行包裹, 组件作用即加载一个路由之后不再加载其他路由。
{/* 使用路由的Switch组件可以优先匹配前面的路由,放弃后面的匹配 */}
5.进入详情页以及返回功能
//利用props中的id进行请求
componentWillMount(){
fetchJSONP('http://api.douban.com/v2/movie/subject/'+this.props.match.params.id)
.then(res=>res.json())
.then(data=>{
this.setState({
info:data,
isLoading:false
})
})
}
//为返回按钮绑定goBack事件
goBack=()=>{
this.props.history.go(-1)
}
1.项目的主要通过Route、this.props.match.params路由跳转提取参数以及在组件内修改props参数达到路由切换和页面重新渲染的功能
2.react和vue类似,主要通过操作数据进而操作页面,所以掌握获取和修改props和state中的数据更容易进行开发
3.写博客既是为了分享,也是为了对知识点的巩固,不准确的地方还请留言提出