详解webpack2+React 实例demo
程序员文章站
2022-05-14 19:10:02
1.目录结构
源文件在src目录下,打包后的文件在dist目录下。
2.webpack.config.js
说明:
1.涉及到的插件需要npm in...
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; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: js实现canvas图片与img图片的相互转换的示例
下一篇: 详解vue axios中文文档