项目结构: src: app.js main.js package.json webpack_dev_config.js 须要安装包: yarn add react react-dom --save
app.jscss
import React, {component} from 'react'; class App extends Component { render(){ return ( <div> hello world </div> ) } } export default App
注意:html
return 最外一层的div不能破坏,内容所有写在div里面 浏览器不识别jsx,因此用babel来转换 见webpack_dev_config.js中的配置 网页地址: https://babeljs.cn/docs/setup/#installation
main.js(导入根组件,并渲染根组件)node
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App' ReactDOM.render( <App />, document.getElementById('root'));
注意:react
若是App.js的导出是 export App 则引入时应该是 import {App} from 'xxxxx'
webpack_dev_config.jswebpack
配置babel:git
https://babeljs.cn/ https://babeljs.cn/docs/setup/#installation //详情看这个 1. 安装包 yarn add babel-loader babel-core --dev //转es6 yarn add babel-preset-env --dev //转换jsx,并添加 "react" 到你的 .babelrc 的 presets 数组中。 yarn add babel-preset-react --dev
开发阶段:es6
网址: https://github.com/jantimon/html-webpack-plugin 结合webpack-dev-server 配合 html-webpack-plugin 1. 安装包 yarn add webpack html-webpack-plugin webpack-dev-server --dev
代码:github
var HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/main.js', module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" } ] }, plugins: [ new HtmlWebpackPlugin({ template: './template.html', filename: 'index.html' }) ] }
package.jsonweb
配置scripts "scripts": { "dev": "webpack-dev-server --progress --open --config webpack_dev_config.js --prot 6008" }
.babelrcnpm
{ "presets": [ "env", "react" ] }
参考地址: https://doc.react-china.org/docs/installation.html npm install -g create-react-app create-react-app my-app
参考地址: https://github.com/gaearon/react-hot-loader 1. yarn add react-hot-loader --dev yarn add babel-polyfill --dev 2. // .babelrc { "presets": [ ["env", { "modules": false }], "react" ], "plugins": ["react-hot-loader/babel"] } 3. https://webpack.js.org/guides/hot-module-replacement/#enabling-hmr 4. // webpack.config.js module.exports = { entry: ['babel-polyfill', 'react-hot-loader/patch', './main.js'], } Note: Make sure to set the output.publicPath property to "/" as well. Otherwise hot reloading won't work as expected for nested routes. 5. // main.js import React from 'react' import ReactDOM from 'react-dom' import { AppContainer } from 'react-hot-loader' import App from './containers/App' const render = Component => { ReactDOM.render( <AppContainer> <Component /> </AppContainer>, document.getElementById('root'), ) } render(App) // Webpack Hot Module Replacement API if (module.hot) { module.hot.accept('./containers/App', () => { render(App) }) } Note: To make this work, you'll need to opt out of Babel transpiling ES2015 modules by changing the Babel ES2015 preset to be ["es2015", { "modules": false }] 6. "scripts": { "dev": "webpack-dev-server --progress --open --config webpack_config_dev.js --port 6008 --hotOnly" }
只须要在根目录下运行npm run eject,目录结构会改变 https://github.com/gaearon/react-hot-loader Migrating from create-react-app里面跟着作三步
1. 直接在标签里经过style写 1. <div style={{color:'red'}}> hello world123 </div> <span style={{ fontSize : 16 + "px"}}>Hello, yoona</span>; 2. 放在单独的对象中 const style = { color: 'green' } <div style={style}> hello world </div> 2. 经过外部样式来写 import 'xxxx.css/xxx.less/xxx.sass' //须要安装loader // style-loader css-loader less-loader sass-loader node-sass(这个用cnpm装) //yarn add style-loader css-loader --dev <div className="xxxx"> hello world123 </div> 注意: 在jsx中,属性名称后面的值,两种状况,一种字符串,一种{}
组件的数据来源于两部分 1. 父组件 2. 本身内部数据 无状态组件: 本身内部没有数据,数据来源于父组件 有状态组件: 便可有父组件数据,也能够有本身内部数据
语法: import React from 'react' function Hello (){ return ( <div>123</div> ) } export default Hello 传值: 传值方: 经过属性名称=值的方式传递 <Hello name="abc" age={10}></Hello> 接收方: function Hello (props){ return ( <div>123,{props.name}</div> ) } 注意: 父组件传过来的值只能展现,不能直接修改
语法: class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } } 传值: 传值方: 经过属性名称=值的方式传递 <Hello name="abc" age={10}></Hello> 接收方: 经过{this.props.name} 私有的值: constructor(){ super() this.state = { name: 'tom' } } 使用: {this.state.name} 默认值(es7): 包:babel-preset-stage-0 .babelrc中添加"stage-0" static defaultProps = { initCount: 300 }
<button onClick={()=>{this.clickme()}}>点我</button> clickme(){ console.log(1) } <button onClick={this.clickme()}>点我</button> 这种绑定是拿不到this的
this.setStatus({ name: "yoona" })
import PropTypes from 'prop-types' static propTypes = { initCount: PropTypes.number/string }
componentWillMount(){} render(){} componentDidMount(){} componentWillReceiveProps(){} shouldComponentUpdate(){ return true } componentWillUpdate(){} componentDidUpdate(){}
参考地址: https://ant.design/docs/react/introduce-cn 1. 安装 yarn add antd 2. import { DatePicker } from 'antd'; 3. import 'antd/dist/antd.css'; // or 'antd/dist/antd.less' 按需导入: 1. // .babelrc or babel-loader option { "plugins": [ ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }] // `style: true` 会加载 less 文件 ] } 而后只需从 antd 引入模块便可,无需单独引入样式 参考地址:https://github.com/ant-design/babel-plugin-import 2. 手动按需导入 import DatePicker from 'antd/lib/date-picker'; // 加载 JS import 'antd/lib/date-picker/style/css'; // 加载 CSS
参考地址: https://reacttraining.com/react-router/web/example/basic yarn add react-router-dom --save
yarn add fetch-jsonp --save import fetchJsonp from 'fetch-jsonp' getFilmList(){ const url = `https://api.douban.com/v2/movie/${this.state.filmType}` fetchJsonp(url).then(response=>response.json()).then(data=>{ this.setState({ isLoading: false, filmList: data.subjects }) }).catch(e=> console.log('error',e)) }
改变数据时:
componentWillReceiveProps(props){ this.setState({ filmType: props.match.params.filmTypes, isLoading: true },()=>{ this.getFilmList() }) }
render里面须要遍历时用{}
render() { if(this.state.isLoading){ return <Spin tip="加载中..."> <Alert message="正在加载中" description="哥正在拼命加载中,请稍后" type="info" /> </Spin> }else{ return ( <div style={{display:'flex',flexWrap:'wrap',textAlign:'center'}}> { this.state.filmList.map((item,i)=>{ return <div key={i} onClick={()=>{this.goMovieDetail(item.id)}} className="movieItem" style={everyMovieItemStyle}> <img style={{height:378}} src={item.images.small} alt=""/> <p><strong>{item.title}</strong></p> <p><strong>电影类型:{item.genres.join(',')}</strong></p> <p><strong>上映年份:{item.year}</strong></p> <div>评分:<Rate disabled defaultValue={item.rating.average / 2} /></div> </div> }) } </div> ) } }
//经过编程式导航跳转到电影详情组件中去 goMovieDetail(movieId){ this.props.history.push(`/movie/detail/${movieId}`) } //返回到上一级 goBack() { this.props.history.goBack() }
参考地址(性能优化): https://doc.react-china.org/docs/optimizing-performance.html webpack指南里面: https://doc.webpack-china.org/guides/production/ 1. 新建一个配置文件webpack_config_prod.js 2. 热重载要干掉 3. 压缩js new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify('production') } }), new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false }, comments: false }) 4. 压缩html 参考网址: https://github.com/jantimon/html-webpack-plugin https://github.com/kangax/html-minifier#options-quick-reference new HtmlWebpackPlugin({ template: './template.html', filename: 'index.html', minify: { collapseWhitespace: true, removeComments: true, minifyCSS: true, minifyJS: true } }) 5. output const path = require('path'); output: { path:path.resolve(__dirname, "dist"), filename: "bundle.js" } 6. 清除原先的dist const CleanWebpackPlugin = require('clean-webpack-plugin'); new CleanWebpackPlugin(['dist']) 7. 配置package.json "build": "webpack --progress --config webpack_config_prod.js" 优化打包: 抽离第三方包 1. 抽离图片 { test: /\.(png|jpg|gif)$/, use: [ { loader: 'url-loader', options: { limit: 4000,//大于4kb就抽离出去 name:"images/[name]-[hash:5].[ext]" } } ] } 2. 明确第三方库 https://doc.webpack-china.org/plugins/commons-chunk-plugin/ entry: { quanjiatong:['react','react-dom','react-router-dom'], fetchJsonp:['fetch-jsonp'], bundle:'./src/main.js' } output: { path:path.resolve(__dirname, "dist"), filename: "js/[name].js" } new webpack.optimize.CommonsChunkPlugin({ name: ['quanjiatong','fetchJsonp'], minChunks: Infinity, }) 3. 抽离对三方样式 https://github.com/webpack-contrib/extract-text-webpack-plugin yarn add extract-text-webpack-plugin --dev //抽离第三方样式的包 const ExtractTextPlugin = require("extract-text-webpack-plugin"); { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: [ { loader: 'css-loader', options: { minimize: true //压缩css } } ] }) } new ExtractTextPlugin("styles.css"),
之后补充