詳解webpack2+React 實(shí)例demo
1.目錄結(jié)構(gòu)
源文件在src目錄下,打包后的文件在dist目錄下。

2.webpack.config.js
說明:
1.涉及到的插件需要npm install安裝;
2.html-webpack-plugin創(chuàng)建服務(wù)于 webpack bundle 的 HTML 文件;
3.clean-webpack-plugin清除dist目錄重復(fù)的文件;
4.extract-text-webpack-plugin分離css文件。
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
var config = {
context: path.resolve(__dirname, './src'),
entry: {
app: './main.js'
},
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].bundle.js'
},
devtool: 'cheap-module-eval-source-map',
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader","postcss-loader"]
})
},
{
test: /\.less$/,
use: ["style-loader","css-loader","less-loader"]
},
{
test: /\.(png|jpg)$/,
loader: 'url-loader',
options: {
limit: 8129
}
}
]
},
devServer:{
historyApiFallback: true,
host:'0.0.0.0',
hot: true, //HMR模式
inline: true,//實(shí)時(shí)刷新
port: 8181 // 修改端口,一般默認(rèn)是8080
},
resolve: {
extensions: ['.js', '.jsx', '.css'],
modules: [path.resolve(__dirname, './src'), 'node_modules']
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new UglifyJsPlugin({
sourceMap: true
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: true
}),
new HtmlWebpackPlugin({
template:'./templateIndex.html'
}),
new ExtractTextPlugin({
filename: '[name].[hash].css',
disable: false,
allChunks: true,
}),
new CleanWebpackPlugin(['dist'])
],
}
module.exports = config;
// webpack里面配置的bundle.js需要手動(dòng)打包才會(huì)變化,目錄可以由自己指定;
// webpack-dev-server自動(dòng)檢測(cè)變化自動(dòng)打包的是開發(fā)環(huán)境下的bundle.js,打包路徑由contentBase決定,兩個(gè)文件是不一樣的.
3.postcss.config.js(Autoprefixer)
module.exports = {
plugins: {
'autoprefixer': {browsers: 'last 5 version'}
}
}
// 兼容最新的5個(gè)瀏覽器版本
4.新建.babelrc
{
"presets": ['es2015','react','stage-3']
}
5.index.html
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>React Project</title> </head> <body> <div id="content"></div> <script src="app.bundle.js"></script> </body> </html>
6.package.json
npm install 或 yarn -> 安裝模塊,npm run build -> 打包,npm start -> 啟動(dòng)localhost:8181
{
"name": "reactproject",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"jquery": "^3.1.1",
"react": "^15.3.2"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-plugin-syntax-async-functions": "^6.13.0",
"babel-plugin-transform-async-to-generator": "^6.16.0",
"babel-preset-es2015": "^6.14.0",
"babel-preset-react": "^6.11.1",
"babel-preset-stage-3": "^6.17.0",
"bootstrap": "^4.0.0-alpha.2",
"clean-webpack-plugin": "^0.1.16",
"css-loader": "^0.25.0",
"extract-text-webpack-plugin": "^3.0.0-rc.2",
"file-loader": "^0.9.0",
"html-webpack-plugin": "^2.29.0",
"jshint": "^2.9.3",
"jshint-loader": "^0.8.3",
"json-loader": "^0.5.4",
"less": "^2.7.1",
"less-loader": "^2.2.3",
"moment": "^2.15.1",
"node-sass": "^3.10.0",
"postcss-loader": "^2.0.6",
"react-bootstrap": "^0.30.5",
"react-dom": "^15.3.2",
"sass-loader": "^4.0.2",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"webpack": "^3.3.0",
"webpack-dev-server": "^2.5.1"
},
"scripts": {
"start": "webpack-dev-server --hot --inline --progress --colors --content-base .",
"build": "webpack --progress --colors"
},
"keywords": [
"reactcode"
],
"author": "xhh",
"license": "ISC"
}
7.main.js:入口文件
import React from 'react'
import { render } from 'react-dom';
import $ from 'jquery';
import Demo1 from './js/demo1.js';
// import Demo2 from './js/demo2.js';
render(<Demo1 title="這是提示" />, $('#content')[0]);
// render(<Demo2 myName="園中橋" sex="female"/>, $('#content')[0]);
8.templateIndex.html
打包后的模板index文件,插件html-webpack-plugin的template指定的目錄。
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Template Index html</title> </head> <body> <div id="content"></div> </body> </html>
9.demo
demo1.js
import React from 'react';
import '../css/demo1.css';
const arr = [
{
name:'name1',
tel:'12343456783'
},
{
name:'name2',
tel:'12343456784'
},
{
name:'name3',
tel:'12343456785'
}
];
export default class Demo1 extends React.Component {
constructor(props) {
super(props);
this.state = {
content: true,
value: 'inputText'
};
}
handleClick(){
this.setState({
content: !this.state.content
})
// this.refs.myInput.focus();
}
handleChange(event) {
this.setState({value: event.target.value});
}
renderArr() {
return arr.map((item,index)=>{
return <li key={index}>name:{item.name},tel:{item.tel}</li>
})
}
render(){
let btnStyle = {
border: '1px solid #ccc',
background:'#fff',
color: '#a106ce'
}
return (
/* 注釋 */
<div>
<button style={btnStyle} className="btn" type="button" onClick={()=>this.handleClick()}>change state</button><br/>
<p title={this.props.title} style={{ color:'#A349A4' }}>Hello { this.props.textCont}!</p>
<p>{this.state.content ? 'initial value' : 'later value'}</p>
{ /* 標(biāo)簽里面的注釋外面要用花括號(hào) */ }
<input type="text" value={this.state.value} ref="myInput" onChange={this.handleChange.bind(this)} />
<h4>{this.state.value}</h4>
<DemoChild><p>lalala</p></DemoChild>
<ul>
{ this.renderArr() }
</ul>
</div>
)
}
}
Demo1.propTypes = {
title: React.PropTypes.string.isRequired
}
Demo1.defaultProps = {
textCont: 'React'
}
class DemoChild extends React.Component {
constructor(props) {
super(props);
}
render(){
return (
<div>我是子組件{this.props.children}</div>
)
}
}
demo1.css
ul {
list-style: none;
padding: 0;
margin:0;
display: flex;
}
.btn:focus {
outline: none;
}
demo2.js:父子組件生命周期
import React, { Component, PropTypes } from 'react';
import '../css/demo2.css';
export default class Demo2 extends Component {
constructor(props){
super(props);
this.state = {
stateName: this.props.myName + ',你好',
count: 0,
}
console.log('init-constructor');
}
static get defaultProps() {
return {
myName: "xhh",
age: 25
}
}
doUpdateCount(){
this.setState({
count: this.state.count+1
})
}
componentWillMount() {
console.log('componentWillMount');
}
componentDidMount() {
console.log('componentDidMount')
}
componentWillReceiveProps(nextProps){
console.log('componentWillReceiveProps')
}
shouldComponentUpdate(nextProps, nextState){
console.log('shouldComponentUpdate');
// return nextProps.id !== this.props.id;
if(nextState.count > 10) return false;
return true;
}
componentWillUpdate(nextProps,nextState){
console.log('componentWillUpdate');
}
componentDidUpdate(prevProps, prevState){
console.log('componentDidUpdate');
}
componentWillUnmount(){
console.log('componentWillUnmount');
}
render(){
console.log('render');
return (
<div>
<p className="colorStyle">姓名:{this.props.myName}</p>
<p>問候:{this.state.stateName}</p>
<p>年齡:{this.props.age}</p>
<p>性別:{this.props.sex}</p>
<p>父元素計(jì)數(shù)是:{this.state.count}</p>
<button onClick={ this.doUpdateCount.bind(this) } style={{ padding: 5,backgroundColor: '#ccc' }}>點(diǎn)我開始計(jì)數(shù)</button>
<SubMyPropType count1={this.state.count} />
</div>
)
}
}
Demo2.propTypes = {
myName: PropTypes.string,
age: PropTypes.number,
sex: PropTypes.string.isRequired
}
class SubMyPropType extends Component {
componentWillMount() {
console.log('subMyPropType-componentWillMount');
}
componentDidMount() {
console.log('subMyPropType-componentDidMount')
}
componentWillReceiveProps(nextProps){
console.log('subMyPropType-componentWillReceiveProps')
}
shouldComponentUpdate(nextProps, nextState){
console.log('subMyPropType-shouldComponentUpdate');
if(nextProps.count1 > 5) return false;
return true;
}
componentWillUpdate(nextProps, nextState){
console.log('subMyPropType-componentWillUpdate');
}
componentDidUpdate(prevProps, prevState){
console.log('subMyPropType-componentDidUpdate');
}
componentWillUnmount(){
console.log('subMyPropType-componentWillUnmount');
}
render(){
console.log('subMyPropType-render');
return(
<p>子元素計(jì)數(shù)是:{this.props.count1}</p>
)
}
}
demo2.css
.colorStyle {
color: #0f0;
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
react-redux多個(gè)組件數(shù)據(jù)共享的方法
這篇文章主要介紹了react-redux多個(gè)組件數(shù)據(jù)共享的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
React將組件作為參數(shù)進(jìn)行傳遞的3種方法實(shí)例
其實(shí)react組件之間傳遞參數(shù)是比較簡(jiǎn)單的,組件傳入?yún)?shù)的一種方式,下面這篇文章主要給大家介紹了關(guān)于React將組件作為參數(shù)進(jìn)行傳遞的3種方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
阿里低代碼框架lowcode-engine自定義設(shè)置器詳解
這篇文章主要為大家介紹了阿里低代碼框架lowcode-engine自定義設(shè)置器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
再次談?wù)揜eact.js實(shí)現(xiàn)原生js拖拽效果引起的一系列問題
React 起源于 Facebook 的內(nèi)部項(xiàng)目,因?yàn)樵摴緦?duì)市場(chǎng)上所有 JavaScript MVC 框架,都不滿意,就決定自己寫一套,用來架設(shè) Instagram 的網(wǎng)站.本文給大家介紹React.js實(shí)現(xiàn)原生js拖拽效果,需要的朋友一起學(xué)習(xí)吧2016-04-04
React Form組件的實(shí)現(xiàn)封裝雜談
這篇文章主要介紹了React Form組件的實(shí)現(xiàn)封裝雜談,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05
React引入css的幾種方式及應(yīng)用小結(jié)
這篇文章主要介紹了React引入css的幾種方式及應(yīng)用小結(jié),操作styled組件的樣式屬性,可在組件標(biāo)簽上定義屬性、也可以通過attrs定義屬性,本文通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-03-03

