webpack2+React 实例demo

前端之家收集整理的这篇文章主要介绍了webpack2+React 实例demo前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

1.目录结构

文件在src目录下,打包后的文件在dist目录下。

2.webpack.config.js

说明:
1.涉及到的插件需要npm install安装;
2.html-webpack-plugin创建服务于 webpack bundle 的 HTML 文件
3.clean-webpack-plugin清除dist目录重复的文件
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,//实时刷新
      port: 8181 // 修改端口,一般默认是8080
  },resolve: {
      extensions: ['.js','.jsx','.css'],modules: [path.resolve(__dirname,'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需要手动打包才会变化,目录可以由自己指定;
// webpack-dev-server自动检测变化自动打包的是开发环境下的bundle.js,打包路径由contentBase决定,两个文件是不一样的.

3.postcss.config.js(Autoprefixer)

module.exports = {
  plugins: {
    'autoprefixer': {browsers: 'last 5 version'}
  }
}

// 兼容最新的5个浏览器版本

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 -> 启动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>
                    { /* 标签里面的注释外面要用花括号 */ }
                    <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>父元素计数是:{this.state.count}</p>
            <button onClick={ this.doUpdateCount.bind(this) } style={{ padding: 5,backgroundColor: '#ccc' }}>点我开始计数</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>子元素计数是:{this.props.count1}</p>
            ) 
    }
}

demo2.css

.colorStyle {
    color: #0f0;
}

猜你在找的React相关文章