1、进行全局安装
cnpm i create-react-app -g (全局安装只需安装一次)
2、项目创建
create-react-app myapp
myapp是项目名称
3、抽离配置文件命令
cd myapp //进入创建的项目
cnpm run eject //抽离配置文件命令
在命令行中输入抽离配置命令
抽离成功如下图:
4、配置@的别名指向src目录
打开config文件夹里的webpack.config.dev和webpack.config.dev的指定位置加入如下代码 ‘@’: path.join(__dirname, ‘…/’, ‘src’)
alias: {
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
**'@': path.join(__dirname, '../', 'src')**
},
5、创建文件夹components、store
在src中创建components和store两个文件夹,将App.js 和 App.test.js 放入components文件夹中src里保留index.js 和 serviceWorker
6、安装scss
如果使用scss可以安装scss
cnpm i node-sass sass-loader -S
7、加入路由模块
cnpm i react-router-dom -S
8、UI类型的组件
cnpm i antd-mobile -S
入口页面的相关配置 --- click/promise支持
<script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script>
<script>
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
if(!window.Promise) {
document.writeln('<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js"'+'>'+'<'+'/'+'script>');
}
安装babel-plugin-import
cnpm i babel-plugin-import -D
在webapck.config.dev.js和webapck.config.prod.js中添加:
[“import”, { libraryName: “antd-mobile”, style: “css” }]
plugins: [
[
require.resolve('babel-plugin-named-asset-import'),
{
loaderMap: {
svg: {
ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
},
},
},
],
["import", { libraryName: "antd-mobile", style: "css" }]
],
9、在components创建home.js 代码如下
import React, { Component } from 'react';
import axios from 'axios'; //引入axios
import Banner from './Banner'; //引入加入的轮播图
import List from './List'; //引入加入的数据
import Footer from './Footer';
class App extends Component {
constructor (props) {
super (props);
this.state = {
banner: [],
imgHeight: 176,
disabled: false,
list: [],
}
}
getBannerData () {
return axios.get('http://jx.xuzhixiang.top/ap/api/bannerlist.php?id=13184')
}
getListData () {
return axios.get('douban')
}
// 使用axios请求数据
componentDidMount () {
axios.all([this.getBannerData(),this.getListData()])
.then(axios.spread((banner,list) => {
console.log('banner', banner)
console.log('list', list)
this.setState({
banner: banner.data.data,
list: list.data
})
console.log(this.state)
}))
}
// 进入详情
goPageFn (id) {
console.log(id)
this.props.history.push('/detail/'+id);
}
render() {
return (
<div className="box">
<header className="header">
首页头部
</header>
<div className="content">
首页内容
<Banner banner={ this.state.banner } imgHeight={ this.state.imgHeight }/>
<List list={ this.state.list } disabled={ this.state.disabled } goPageFn = { this.goPageFn.bind(this) }/>
</div>
<Footer />
</div>
);
}
}
export default App;
9.1、将Footer底部抽离出来
Footer.js
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
class footer extends Component {
constructor (props) {
super(props);
this.state = {
list: [
{
icon: 'iconfont icon-ai-home',
name: '首页',
path: '/home'
},
{
icon: 'iconfont icon-fenlei',
name: '分类',
path: '/kind'
},
{
icon: 'iconfont icon-gouwuche',
name: '购物车',
path: '/cart'
},
{
icon: 'iconfont icon-04f',
name: '我的',
path: '/user'
}
]
}
}
render() {
return (
<footer className="footer">
<ul>
{
this.state.list.map((item, index) => {
return (
<li key= { index }>
<NavLink to = { item.path }> //设置跳转路由
<span className= { item.icon }></span>
<p>{ item.name }</p>
</NavLink>
</li>
)
})
}
</ul>
</footer>
);
}
}
export default footer
9.2、数据组件List.js
import React, { Component } from 'react';
import { List } from 'antd-mobile';
const Item = List.Item;
const Brief = Item.Brief;
class list extends Component {
// constructor(props) {
// super(props);
// }
sendIdFn (id) { // 向父组件home.js传值
this.props.goPageFn(id)
}
render() {
let lists = []
this.props.list.map((item,index) => {
// console.log(item.images.small)
lists.push(
<Item key={index} extra={item.year} align="top" thumb={item.images.small} multipleLine onClick={ this.sendIdFn.bind(this, item.id) }>
{ item.title } <Brief>豆瓣评分:{ item.rating.average }分</Brief>
</Item>
)
return lists
})
return (<div>
<List renderHeader={() => '豆瓣电影'} className="my-list">
{ lists }
</List>
</div>);
}
}
export default list;
9.3、轮播图组件Banner.js
import React, { Component } from 'react';
import { Carousel, } from 'antd-mobile'; //使用
class banner extends Component {
// constructor (props) {
// super (props);
// }
render() {
return (
<Carousel
autoplay={true}
infinite
beforeChange={(from, to) => console.log(`slide from ${from} to ${to}`)}
afterChange={index => console.log('slide to', index)}
>
{this.props.banner.map((item, val) => (
<a
key={val}
href="http://www.alipay.com"
style={{ display: 'inline-block', width: '100%', height: this.props.imgHeight }}
>
<img
src={ item.banner_img_url }
alt=""
style={{ width: '100%', verticalAlign: 'top' }}
onLoad={() => {
// fire window resize event to change height
window.dispatchEvent(new Event('resize'));
this.setState({ imgHeight: 'auto' });
}}
/>
</a>
))}
</Carousel>
);
}
}
export default banner;
9.4详情页面Detail.js
import React, { Component } from 'react';
import axios from 'axios';
class App extends Component {
constructor (props) {
super (props);
this.state = {
// film: [], // film 电影
title: '',
year: '',
average: '',
genres: [],
alt: '',
img: ''
}
}
getFilmData () {
// console.log('detail', this)
// console.log(this.props.match.params)
const { id } = this.props.match.params
return axios.get(`detail?id=${id}`)
}
componentDidMount () {
// console.log(this.props.match.params)
axios.all([this.getFilmData()])
.then(axios.spread((film) => {
// console.log('film', film.data[0])
// console.log(film.data[0].genres)
this.setState({
title: film.data[0].title,
year: film.data[0].year,
average: film.data[0].rating.average,
genres: film.data[0].genres,
img: film.data[0].images.small
})
}))
}
render() {
let tags=[]
this.state.genres.map((item,index) => {
tags.push(
<span key={ index } style={ {margin: "0 0.05rem"} }>
{ item }
</span>
)
return tags
})
let imgstyle = {
width: "1.6rem",
height: "2.3rem",
flost: "left"
}
let liheight = {
margin: '0.05rem 0'
}
return (
<div className="container">
<div className="box">
<header className="header">
电影详情
</header>
<div className="content">
<div className="detail"
style={{width: "90%", display: 'flex', margin: '0.25rem auto'}}
>
<p style={ {width: "50%"} }>
<img src={ this.state.img } alt="" style={ imgstyle }/>
</p>
<ul style={ {width:"50%", float: "right", padding: "0 0.1rem"} }>
<h3 style={ {margin: '0.15rem 0'} }>{ this.state.title }</h3>
<li style= { liheight }>{ this.state.year }年</li>
<li style= { liheight }>豆瓣评分:{ this.state.average }分</li>
<li style= { liheight }>分类:{ tags }</li>
</ul>
</div>
</div>
</div>
<Footer />
</div>
);
}
}
export default App;
9.5src中的index.js中的代码
import React from 'react';
import ReactDOM from 'react-dom';
import { HashRouter as Router, Route, Switch, Redirect } from 'react-router-dom'
// import './index.css';
// import App from '@/components/App';
import Home from '@/components/Home';
import Cart from '@/components/Cart';
import Kind from '@/components/Kind';
import User from '@/components/User';
import Detail from '@/components/Detail';
import * as serviceWorker from './serviceWorker';
import './main.scss';
ReactDOM.render(
<Router>
<Switch>
<Route path='/home' component = { Home } />
<Route path='/cart' component = { Cart } />
<Route path='/kind' component = { Kind } />
<Route path='/user' component = { User } />
<Route path='/detail/:id' component = { Detail } />
<Redirect to={ {pathname: '/home'} } />
</Switch>
</Router>
, document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();