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"),

服务器反向代理

以后补充

posted on 2018-02-09 17:49  ouruixi  阅读(165)  评论(0编辑  收藏  举报

导航