項目結構: 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"),
之後補充