react-route配合豆瓣api实现电影分类小项目

写在前面

本项目使用豆瓣的api和react的路由跳转功能实现页面的基本切换:1.可能因为豆瓣图片防盗链的关系,图片不显示;2.项目使用antd组件库进行项目页面的布局;3.在解决跨域方面使用fetch-jsonp工具

这篇博客我记录下自己的每一步操作,主要为了巩固知识点,不准确的地方请留言指出,不足之处请谅解。

项目代码地址:https://github.com/jishuaizhen/react-movie.git

一、页面布局

react-route配合豆瓣api实现电影分类小项目_第1张图片
react-route配合豆瓣api实现电影分类小项目_第2张图片

  1. 顶部
    顶部为首页、电影、关于导航栏,主要实现了电影部分的功能

  2. 内容区域
    内容区域为电影模块下的正在热映、即将上映、top250三部分,三部分布局相似,主要是为了练习react的路由切换。

  3. 底部
    底部为了配合布局,可以忽略。

二、主入口文件App.js

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]]}

三、主要内容文件Movie.js

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
    函数渲染页面

五、点击单个电影进入电影详情页面MovieDetail.js

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.写博客既是为了分享,也是为了对知识点的巩固,不准确的地方还请留言提出

你可能感兴趣的:(React,react)