JavaScript

超轻量级php框架startmvc

详解webpack2+React 实例demo

更新时间:2020-06-04 09:18:01 作者:startmvc
1.目录结构源文件在src目录下,打包后的文件在dist目录下。2.webpack.config.js说明:1.涉及到的

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, './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;
}

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

webpack2 React 实例 webpack2 React demo