详解webpack2+React 实例demo


Posted in Javascript onSeptember 11, 2017

1.目录结构

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

详解webpack2+React 实例demo

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, './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需要手动打包才会变化,目录可以由自己指定;
// 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;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS 加入收藏夹的代码(主流浏览器通用)
May 13 Javascript
解析window.open的使用方法总结
Jun 19 Javascript
解决js数据包含加号+通过ajax传到后台时出现连接错误
Aug 01 Javascript
超链接的禁用属性Disabled使用示例
Jul 31 Javascript
jquery代码实现简单的随机图片瀑布流效果
Apr 20 Javascript
如何在Linux上安装Node.js
Apr 01 Javascript
node.js中debug模块的简单介绍与使用
Apr 25 Javascript
Node.js中的http请求客户端示例(request client)
May 04 Javascript
vue实现图书管理demo详解
Oct 17 Javascript
vue 刷新之后 嵌套路由不变 重新渲染页面的方法
Sep 13 Javascript
vue src动态加载请求获取图片的方法
Oct 17 Javascript
jquery实现简单每周轮换的日历
Sep 10 jQuery
react-native 完整实现登录功能的示例代码
Sep 11 #Javascript
Layui table 组件的使用之初始化加载数据、数据刷新表格、传参数
Sep 11 #Javascript
Vuejs 页面的区域化与组件封装的实现
Sep 11 #Javascript
js封装成插件的步骤方法
Sep 11 #Javascript
vue.js移动端app之上拉加载以及下拉刷新实战
Sep 11 #Javascript
Chrome调试折腾记之JS断点调试技巧
Sep 11 #Javascript
JS中的Replace()传入函数时的用法详解
Sep 11 #Javascript
You might like
php中用date函数获取当前时间有误的解决办法
2013/08/02 PHP
Drupal7 form表单二次开发要点与实例
2014/03/02 PHP
php统计文章排行示例
2014/03/04 PHP
PHP中exec函数和shell_exec函数的区别
2014/08/20 PHP
PHP正则匹配日期和时间(时间戳转换)的实例代码
2016/12/14 PHP
用PHP做了一个领取优惠券活动的示例代码
2019/07/05 PHP
Yii2.0框架模型多表关联查询示例
2019/07/18 PHP
用JavaScript和注册表脚本实现右键收藏Web页选中文本
2007/01/28 Javascript
JS中操作JSON总结
2020/12/06 Javascript
javascript抽象工厂模式详细说明
2014/12/16 Javascript
javaScript实现可缩放的显示区效果代码
2015/10/26 Javascript
基于JavaScript实现瀑布流布局(二)
2016/01/26 Javascript
JavaScript的instanceof运算符学习教程
2016/06/08 Javascript
利用原生js和jQuery实现单选框的勾选和取消操作的方法
2016/09/04 Javascript
jquery编写日期选择器
2017/03/16 Javascript
微信小程序 检查接口状态实例详解
2017/06/23 Javascript
Vue动态组件实例解析
2017/08/20 Javascript
浅谈实现vue2.0响应式的基本思路
2018/02/13 Javascript
解析JS在获取当前月的最后一天遇到的坑
2019/08/30 Javascript
ES6中的Javascript解构的实现
2020/10/30 Javascript
Python中获取对象信息的方法
2015/04/27 Python
Python中的random.uniform()函数教程与实例解析
2019/03/02 Python
Python自动化之数据驱动让你的脚本简洁10倍【推荐】
2019/06/04 Python
python:按行读入,排序然后输出的方法
2019/07/20 Python
在pycharm中debug 实时查看数据操作(交互式)
2020/06/09 Python
python报错TypeError: ‘NoneType‘ object is not subscriptable的解决方法
2020/11/05 Python
Python requests HTTP验证登录实现流程
2020/11/05 Python
Dune London官网:英国著名奢华鞋履品牌
2017/11/30 全球购物
澳大利亚排名第一的狂热牛仔品牌:ONETEASPOON
2018/11/20 全球购物
农民工工资发放承诺书
2014/03/31 职场文书
委托书范文
2014/04/02 职场文书
2014年社区综治工作总结
2014/11/17 职场文书
《日月潭》教学反思
2016/02/20 职场文书
坚持不是死撑,更重要的是心态
2019/08/19 职场文书
基于python的matplotlib制作双Y轴图
2021/04/20 Python
springboot 自定义配置 解决Boolean属性不生效
2022/03/18 Java/Android