这一篇来讲一下电影列表页面的详细页面具体是如何实现的
首先我们看一下各个组件在页面上的布局是什么样子的
作为MovieContainer 组件,主要使用Slider,Menu和Route等组件,将对应的模块导航到相应的页面上去
这里涉及到路由规则的设置
和inline 即html元素将块级元素变为内联元素,
MovieContainer
import React from 'react'
//布局相关的组件
import { Layout, Menu, Icon } from 'antd';
const { SubMenu } = Menu;
const { Header, Content, Sider } = Layout
//导入路由相关的组件
import { Link, Route } from 'react-router-dom'
//导入路由组件页面
import MovieList from './MovieList.jsx'
export default class MovieContainer extends React.Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
return <Layout style={{ height: '100%' }}>
<Sider style={{ background: '#fff' }}>
<Menu mode="inline" defaultSelectedKeys={['1']}
style={{ height: '100%', borderRight: 0 }}
>
<Menu.Item key="1">
<Link to='/movie/in_theaters/1/ff55df4f0a2e6df7f2cced306fb4912d/3/json' >正在热映</Link>
</Menu.Item>
<Menu.Item key="2">
<Link to='/movie/coming_soon/1/ff55df4f0a2e6df7f2cced306fb4912d/3/json'>即将上映</Link>
</Menu.Item>
<Menu.Item key="3">
<Link to='/movie/top250/1/ff55df4f0a2e6df7f2cced306fb4912d/3/json'>Top250</Link>
</Menu.Item>
</Menu>
</Sider>
{/* <Layout style={{ paddingLeft: '1px' }}></Layout> */}
<Content style={{ background: '#fff', padding: 10, margin: 0, minHeight: 280 }}>
{/* 在匹配路由规则的时候,提供了两个参数 */}
{/* 如果想要从路由规则中,提取参数,需要使用this.props.match.params中获取 */}
<Route path="/movie/:type/:page/:key/:cityid/:dtype" component={MovieList}></Route>
</Content>
</Layout>
}
}
MovieList 组件,
主要在组件将要渲染之前, componentWillMount 方法
和浏览器地址栏改变的时候,componentWillReceiveProps方法
去请求后台接口,获取电影数据,并且传递给MovieItem组件
import React from 'react'
//导入loading组件
import { Spin, Alert } from 'antd';
//导入fetch-jsonp
import fetchJSONP from 'fetch-jsonp'
import fetchJsonp from 'fetch-jsonp'
import Item from 'antd/lib/list/Item'
import MovieItem from './MovieItem.jsx'
export default class MovieList extends React.Component {
constructor(props) {
super(props)
this.state = {
movies: [], //电影列表
nowPage: parseInt(props.match.params.page) || 1,//当前展示第几页的数据
pageSize: 14,
total: 0, //当前电影分类下,总共有多少条数据
isloading: true,//数据是否正在加载,如果为true,表示正在加载数据
cityid: parseInt(props.match.params.cityid) || 3,
dtype: props.match.params.dtype,
key: props.match.params.key
}
}
loadMovieListByTypeAndPage = () => {
//开始获取数据的索引
// const start = this.state.pageSize * (this.state.nowPage - 1)
// const url = 'http://v.juhe.cn/movie/movies.today?cityid=' + this.state.cityid + '&dtype=' + this.state.dtype + '&key=' + this.state.key
// //根据电源类型和电影的页码,获取电影数据
// //fetch 有跨域限制
// // fetch('http://v.juhe.cn/movie/movies.today?cityid=3&dtype=json&key=ff55df4f0a2e6df7f2cced306fb4912d')
// // .then(
// // response => response.json()
// // ).then(data => {
// // console.log(data)
// // })
// fetchJSONP(url)
// .then(response => response.json())
// .then(data => {
// console.log(data)
// console.log(data.result.length)
// this.setState({
// isloading: false,
// movies: data.result,
// total: data.result.length,
// movieType: this.props.match.params.type //保存一下,要获取的电影的类型
// })
// })
const data = require('../dataS/hot_movie.json')
setTimeout(() => {
this.setState({
isloading: false,
movies: data.result,
total: data.result.length,
movieType: this.props.match.params.type
})
}, 1000)
}
componentWillMount() {
this.loadMovieListByTypeAndPage()
// setTimeout(() => {
// //假设1秒以后,数据回来了
// this.setState({
// isloading: false//当数据获取回来之后,把isloading加载中,设置为false
// })
// }, 1000)
// fetch('http://v.juhe.cn/movie/movies.today')
// .then(response => {//当使用fetch API获取数据的时候,第一个.then中,获取不到数据
// //第一个.then中拿到的是一个Response对象,我们可以调用response.json()得到一个新的promise
// //console.log(response)
// return response.json()
// })
// .then(
// data => {
// console.log(data);
// }
// )
}
//组件将要接收新属性
componentWillReceiveProps(nextProps) {
console.log(nextProps.match)
//每当地址栏变化的时候,重置state中的参数项,重置完毕之后,我们可以重新发起数据请求了
this.setState({
isloading: true,//又要重新加载电影数据了
nowPage: parseInt(nextProps.match.params.page),//要获取第几页的数据
movieType: nextProps.match.params.type,//电影类型
total: 0
}, function () {
this.loadMovieListByTypeAndPage()
})
}
render() {
return <div>
{this.renderList()}
</div>
}
renderList = () => {
if (this.state.isloading) {
//正在加载中
return <Spin tip="Loading...">
<Alert
message="正在请求电影列表,精彩内容马上呈现"
description="Further details about the context of this alert."
type="info"
/>
</Spin>
} else {
//加载完成
return <div style={{ display: 'flex', flexWrap: 'wrap' }}>
{this.state.movies.map(item => {
return <MovieItem {...item} key={item.movieId}></MovieItem>
})}
</div>
}
}
}
//在React 中,可以使用fetch API来获取数据
//fetch API是基于Promise封装的
MovieItem组件
主要用来进行单个电影图片样式的渲染
import React from 'react'
import styles from '../../css/movieitem.scss'
import { Rate } from 'antd';
export default class MovieItem extends React.Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
return <div className="box">
<img src={this.props.pic_url} alt={this.props.movieName} className="img" ></img>
<h4>电影名称:{this.props.movieName}</h4>
<Rate disabled defaultValue={2} />
</div>
}
}