react杂记
React
webpack+react (hello world)
项目结构:
src:
app.js
main.js
package.json
webpack_dev_config.js
需要安装包:
yarn add react react-dom --save
app.js
import React, {component} from 'react';
class App extends Component {
render(){
return (
<div>
hello world
</div>
)
}
}
export default App
注意:
return 最外一层的div不能破坏,内容全部写在div里面
浏览器不识别jsx,所以用babel来转换
见webpack_dev_config.js中的配置
网页地址:
https://babeljs.cn/docs/setup/#installation
main.js(导入根组件,并渲染根组件)
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
ReactDOM.render(
<App />, document.getElementById('root'));
注意:
如果App.js的导出是
export App
则引入时应该是
import {App} from 'xxxxx'
webpack_dev_config.js
配置babel:
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
开发阶段:
网址:
https://github.com/jantimon/html-webpack-plugin
结合webpack-dev-server 配合 html-webpack-plugin
1. 安装包
yarn add webpack html-webpack-plugin webpack-dev-server --dev
代码:
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.json
配置scripts
"scripts": {
"dev": "webpack-dev-server --progress --open --config webpack_dev_config.js --prot 6008"
}
.babelrc
{
"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里面跟着做三步
React对css、less、sass处理
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"
})
prop-types检查类型 15.0+之后
import PropTypes from 'prop-types'
static propTypes = {
initCount: PropTypes.number/string
}
生命周期
componentWillMount(){}
render(){}
componentDidMount(){}
componentWillReceiveProps(){}
shouldComponentUpdate(){
return true
}
componentWillUpdate(){}
componentDidUpdate(){}
集成 Ant-Design
参考地址:
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
react-router-dom
参考地址:
https://reacttraining.com/react-router/web/example/basic
yarn add react-router-dom --save
fetch-jsonp
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()
}
webpack打包
参考地址(性能优化):
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"),
服务器反向代理
以后补充