1、搭建webpack4.x環境css
1.建立工程文件夾(ReactDemo)html
2.在工程文件夾下,快速初始化項目node
npm init -y // 建立一個package.json文件
3.在工程文件夾下,建立源碼文件夾(src)和編譯打包文件夾(dist)react
4.在源碼文件夾下,建立index.html和入口index.js文件webpack
5.在工程文件夾下,安裝webpackgit
npm i webpack webpack-cli -D
6.在工程文件夾下,建立webpack.config.js文件github
// 向外暴露一個配置對象 module.exports = { mode: 'development' // development:打包文件不壓縮 production:打包文件壓縮 }
7.配置package.json文件web
{ "name": "ReactDemo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^4.39.3", "webpack-cli": "^3.3.8" } }
8.在工程文件夾下,執行打包,會在dist文件夾下生成main.jschrome
npm run dev
2、工具使用npm
1.配置實時打包
npm i webpack-dev-server -D
{ "name": "ReactDemo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack-dev-server --open --port 3000 --hot" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^4.39.3", "webpack-cli": "^3.3.8", "webpack-dev-server": "^3.8.0" } }
注:--open:自動打開瀏覽器(谷歌),--port:指定端口,--hot:熱打包,--host:指定地址
2.配置將html頁面加載到內存中
npm i html-webpack-plugin -D
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') // 建立一個插件實例對象 const htmlPlugin = new HtmlWebpackPlugin({ template: path.join(__dirname, './src/index.html'), // 源文件路徑 filename: 'index.html' // 生成內存中首頁的名稱 }) // 向外暴露一個配置對象 // 由於 webpack 是基於Node構建的;因此 webpack 支持全部Node API 和語法 // 那些 特性 Node 支持呢?Node是基於Chrome V8引擎實現的Javascript運行環境,若是 chrome 瀏覽器支持哪些,則 Node 就支持哪些; module.exports = { mode: 'development', // development production plugins: [ htmlPlugin ] }
3、配置React
1.引入包,react用於建立虛擬DOM和生命週期,react-dom用於將虛擬DOM渲染到頁面
npm i react react-dom -S
2.配置index.js文件
import React from 'react' import ReactDOM from 'react-dom' // 1.建立虛擬DOM元素 // parm1:字符串,元素名稱 // parm2:對象或null,元素屬性 // parm3:子節點(虛擬DOM或文本節點) // ... // parmn:子節點 // <h1 id="header">首頁</h1> const h1 = React.createElement('h1', {id: 'header'}, '首頁,哈哈') // 2.渲染虛擬DOM // parm1:虛擬DOM // parm2:掛在節點 ReactDOM.render(h1, document.getElementById('app'))
3.配置識別JSX。安裝babel,添加.babelrc配置文件,配置webpack.config.js,修改index.js
npm i babel-core@6.26.3 babel-loader@7.1.2 babel-plugin-transform-runtime@6.26.0 -D npm i babel-preset-env@1.7.0 babel-preset-stage-0@6.24.1 -D
npm i babel-preset-react@6.24.1 -D
{ "presets": ["env", "stage-0", "react"], "plugins": ["transform-runtime"] }
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') // 建立一個插件實例對象 const htmlPlugin = new HtmlWebpackPlugin({ template: path.join(__dirname, './src/index.html'), // 源文件路徑 filename: 'index.html' // 生成內存中首頁的名稱 }) // 向外暴露一個配置對象 // 由於 webpack 是基於Node構建的;因此 webpack 支持全部Node API 和語法 // webpack默認只能處理.js後綴名的文件,須要配置規則 module.exports = { mode: 'development', // development production plugins: [ htmlPlugin ], // 全部第三方模塊的配置規則 module: { rules: [ {test: /\.js|jsx$/, use: ['babel-loader'], exclude: /node_modules/} ] } } // 如下的寫法不行,這是ES6中向外導出模塊的API,與之對應的是import ** from '標識符' // export default {}
import React from 'react' import ReactDOM from 'react-dom' // 1.建立虛擬DOM元素 // parm1:字符串,元素名稱 // parm2:對象或null,元素屬性 // parm3:子節點(虛擬DOM或文本節點) // ... // parmn:子節點 // <div>歡迎</div> const div = React.createElement('div', null, '歡迎') const divJsx = <div>歡迎JSX</div> // <h1 id="header">首頁</h1> const h1 = React.createElement('h1', {id: 'header'}, '首頁,哈哈', div, divJsx) // 2.渲染虛擬DOM // parm1:虛擬DOM // parm2:掛在節點 ReactDOM.render(divJsx, document.getElementById('app'))
4.React語法之引用變量
import React from 'react' import ReactDOM from 'react-dom' // 1.建立虛擬DOM元素 // parm1:字符串,元素名稱 // parm2:對象或null,元素屬性 // parm3:子節點(虛擬DOM或文本節點) // ... // parmn:子節點 // <div>歡迎</div> const div = React.createElement('div', null, '歡迎') // <h1 id="header">首頁</h1> const h1 = React.createElement('h1', {id: 'header'}, '首頁,哈哈', div) const a = "歡迎JSX" const divJsx = <div>{a}</div> // 2.渲染虛擬DOM // parm1:虛擬DOM // parm2:掛在節點 ReactDOM.render(divJsx, document.getElementById('app'))
5.React語法之引用變量數組使用map
import React from 'react' import ReactDOM from 'react-dom' // 1.建立虛擬DOM元素 // parm1:字符串,元素名稱 // parm2:對象或null,元素屬性 // parm3:子節點(虛擬DOM或文本節點) // ... // parmn:子節點 // <div>歡迎</div> const div = React.createElement('div', null, '歡迎') // <h1 id="header">首頁</h1> const h1 = React.createElement('h1', {id: 'header'}, '首頁,哈哈', div) const a = "歡迎JSX" const b = ['sad', 'da', 'daszc', 'dafc'] const divJsx = <div> {a} <hr /> {b.map(item => <div key={item}>{item}</div>)} </div> // 2.渲染虛擬DOM // parm1:虛擬DOM // parm2:掛在節點 ReactDOM.render(divJsx, document.getElementById('app'))
5.React語法之注意事項
6.React語法之建立組件
import React from 'react' import ReactDOM from 'react-dom' // 1.建立虛擬DOM元素 // parm1:字符串,元素名稱 // parm2:對象或null,元素屬性 // parm3:子節點(虛擬DOM或文本節點) // ... // parmn:子節點 // <div>歡迎</div> const div = React.createElement('div', null, '歡迎') // <h1 id="header">首頁</h1> const h1 = React.createElement('h1', {id: 'header'}, '首頁,哈哈', div) const a = "歡迎來到JSX" const b = ['sad', 'da', 'daszc', 'dafc'] // 建立組件方式一 function Hello() { return (<div className="container"> {a} <hr /> {"建立組件方式一"} <hr /> {b.map(item => <div key={item}>{item}</div>)} </div>) } // 建立組件方式二 class He extends React.Component{ render() { return (<div className="container"> {a} <hr /> {"建立組件方式二"} <hr /> {b.map(item => <div key={item}>{item}</div>)} </div>) } } // 2.渲染虛擬DOM // parm1:虛擬DOM // parm2:掛在節點 ReactDOM.render( <div className="continer"> <Hello /> <hr /> <He /> </div>, document.getElementById('app'))
7.React語法之給主鍵傳值(只讀)
import React from 'react' import ReactDOM from 'react-dom' // 1.建立虛擬DOM元素 // parm1:字符串,元素名稱 // parm2:對象或null,元素屬性 // parm3:子節點(虛擬DOM或文本節點) // ... // parmn:子節點 // <div>歡迎</div> const div = React.createElement('div', null, '歡迎') // <h1 id="header">首頁</h1> const h1 = React.createElement('h1', {id: 'header'}, '首頁,哈哈', div) const a = "歡迎來到JSX" const b = ['sad', 'da', 'daszc', 'dafc'] const c = { name: 'pascall', age: 20, sex: 'man' } // 建立組件方式一 function Hello(props) { return (<div className="container"> {a} <hr /> {"建立組件方式一: 接收值(只讀):{name=" + props.name + ",age=" + props.age + ",sex=" + props.sex + "}"} <hr /> {b.map(item => <div key={item}>{item}</div>)} </div>) } // 建立組件方式二 class He extends React.Component{ render() { return (<div className="container"> {a} <hr /> {"建立組件方式二: 接收值(只讀):{name=" + this.props.name + ",age=" + this.props.age + ",sex=" + this.props.sex + "}"} <hr /> {b.map(item => <div key={item}>{item}</div>)} </div>) } } // 2.渲染虛擬DOM // parm1:虛擬DOM // parm2:掛在節點 ReactDOM.render( <div className="continer"> <Hello {...c} /> <hr /> <He {...c} /> </div>, document.getElementById('app'))
8.React語法之組件內部屬性state建立和獲取
import React from 'react' export default class Hi extends React.Component{ // 構造器 constructor(props) { super(props) this.state = { name: 'god' } } render() { return (<div className="container"> {"建立組件方式二"} <br /> {"獲取props值(只讀):{name=" + this.props.name + ",age=" + this.props.age + ",sex=" + this.props.sex + "}"} {"獲取state值(讀寫):" + this.state.name} </div>) } }
9.React語法之組件內部屬性state修改
import React from 'react' export default class Hi extends React.Component{ // 構造器 constructor(props) { super(props) this.state = { name: 'god', seg: 0 } } handleClink() { this.setState({ seg: this.state.seg + 1, name: this.state.name.substring(0, 3) + this.state.seg }) } render() { return (<div className="container"> {"建立組件方式二"} <br /> {"獲取props值(只讀):{name=" + this.props.name + ",age=" + this.props.age + ",sex=" + this.props.sex + "}"} {"獲取state值(讀寫):" + this.state.name} <br /> <button onClick={this.handleClink.bind(this)}>修改state值</button> </div>) } }
10.React語法之組件內部css樣式
方式一:行內樣式
import React from 'react' export default class Hi extends React.Component{ // 構造器 constructor(props) { super(props) this.state = { name: 'god', seg: 0 } } handleClink() { this.setState({ seg: this.state.seg + 1, name: this.state.name.substring(0, 3) + this.state.seg }) } render() { return (<div className="container-style-2"> {"建立組件方式二"} <br /> {"獲取props值(只讀):{name=" + this.props.name + ",age=" + this.props.age + ",sex=" + this.props.sex + "}"} {"獲取state值(讀寫):" + this.state.name} <br /> <button onClick={this.handleClink.bind(this)} style={{color: 'red'}}>修改state值</button> </div>) } }
方式二:外聯樣式(css, less)
npm i style-loader css-loader less less-loader sass-loader node-loader -D
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') // 建立一個插件實例對象 const htmlPlugin = new HtmlWebpackPlugin({ template: path.join(__dirname, './src/index.html'), // 源文件路徑 filename: 'index.html' // 生成內存中首頁的名稱 }) // 向外暴露一個配置對象 // 由於 webpack 是基於Node構建的;因此 webpack 支持全部Node API 和語法 // webpack默認只能處理.js後綴名的文件,須要配置規則 module.exports = { mode: 'development', // development production plugins: [ htmlPlugin ], // 全部第三方模塊的配置規則 module: { rules: [ {test: /\.js|jsx$/, use: ['babel-loader'], exclude: /node_modules/}, {test: /\.css$/, use: [ 'style-loader', 'css-loader' ]}, {test: /\.scss$/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: { localIdentName: '[path][name]-[local]-[hash:base64:5]', }, }, }, 'sass-loader'], exclude: /node_modules/}, {test: /\.less$/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: { localIdentName: '[path][name]-[local]-[hash:base64:5]', }, }, }, 'less-loader'], exclude: /node_modules/} ] }, // 配置省略後綴名和路徑別名 resolve: { // 默認.js, .json extensions: [".js", ".jsx", ".json"], alias: { '@': path.join(__dirname, "./src") } } }
import React from 'react' import hi from '@/css/hi.less' export default class Hi extends React.Component{ // 構造器 constructor(props) { super(props) this.state = { name: 'god', seg: 0 } } handleClink() { this.setState({ seg: this.state.seg + 1, name: this.state.name.substring(0, 3) + this.state.seg }) } render() { return (<div className={hi.containerStyle2}> {"建立組件方式二"} <br /> {"獲取props值(只讀):{name=" + this.props.name + ",age=" + this.props.age + ",sex=" + this.props.sex + "}"} <div className={hi.content}>{"獲取state值(讀寫):" + this.state.name}</div> <br /> <button onClick={this.handleClink.bind(this)}>修改state值</button> </div>) } }
.containerStyle2{
.content{
color: red
}
}
// hi.less // :local:會被模塊化,隱式使用,因此不用顯示使用 // :local(.containerStyle2)與.containerStyle2效果一致 // :global:不會被模塊化 :local(.containerStyle2){ :global(.content){ color: red } }
import React from 'react' import hi from '@/css/hi.less' export default class Hi extends React.Component{ // 構造器 constructor(props) { super(props) this.state = { name: 'god', seg: 0 } } handleClink() { this.setState({ seg: this.state.seg + 1, name: this.state.name.substring(0, 3) + this.state.seg }) } render() { return (<div className={hi.containerStyle2}> {"建立組件方式二"} <br /> {"獲取props值(只讀):{name=" + this.props.name + ",age=" + this.props.age + ",sex=" + this.props.sex + "}"} <div className='content'>{"獲取state值(讀寫):" + this.state.name}</div> <br /> <button onClick={this.handleClink.bind(this)}>修改state值</button> </div>) } }
npm i bootstrap@3.4.1 -S
npm i url-loader file-loader -D
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') // 建立一個插件實例對象 const htmlPlugin = new HtmlWebpackPlugin({ template: path.join(__dirname, './src/index.html'), // 源文件路徑 filename: 'index.html' // 生成內存中首頁的名稱 }) // 向外暴露一個配置對象 // 由於 webpack 是基於Node構建的;因此 webpack 支持全部Node API 和語法 // webpack默認只能處理.js後綴名的文件,須要配置規則 module.exports = { mode: 'development', // development production plugins: [ htmlPlugin ], // 全部第三方模塊的配置規則 module: { rules: [ {test: /\.js|jsx$/, use: ['babel-loader'], exclude: /node_modules/}, {test: /\.ttf|woff|woff2|eot|svg|jpg|png|gif$/, use: ['url-loader']}, {test: /\.css$/, use: ['style-loader', 'css-loader']}, {test: /\.scss$/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: { localIdentName: '[path][name]-[local]-[hash:base64:5]', }, }, }, 'sass-loader'], exclude: /node_modules/}, {test: /\.less$/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: { localIdentName: '[path][name]-[local]-[hash:base64:5]', }, }, }, 'less-loader'], exclude: /node_modules/} ] }, // 配置省略後綴名和路徑別名 resolve: { // 默認.js, .json extensions: [".js", ".jsx", ".json"], alias: { '@': path.join(__dirname, "./src") } }
import React from 'react' import hi from '@/css/hi.less' import 'bootstrap/dist/css/bootstrap.css' export default class Hi extends React.Component{ // 構造器 constructor(props) { super(props) this.state = { name: 'god', seg: 0 } } handleClink() { this.setState({ seg: this.state.seg + 1, name: this.state.name.substring(0, 3) + this.state.seg }) } render() { return (<div className={hi.containerStyle2}> {"建立組件方式二"} <br /> {"獲取props值(只讀):{name=" + this.props.name + ",age=" + this.props.age + ",sex=" + this.props.sex + "}"} <div className='content'>{"獲取state值(讀寫):" + this.state.name}</div> <br /> <button onClick={this.handleClink.bind(this)} className="btn btn-primary">修改state值</button> </div>) } }
11.React語法之組件事件
import React from 'react' import hi from '@/css/hi.less' import 'bootstrap/dist/css/bootstrap.css' export default class Hi extends React.Component{ // 構造器 constructor(props) { super(props) this.state = { name: 'god', seg: 0, nickName: [ {id: 1, name: 'sa'}, {id: 2, name: 'da'}, {id: 3, name: 'adac'}, {id: 4, name: 'asx'} ] } } handleClink() { console.log(this) this.setState({ seg: this.state.seg + 1, name: this.state.name.substring(0, 3) + this.state.seg }) } handleClinkNickName(item) { console.log("state nickName: {id=" + item.id + ",name=" + item.name + "}") } render() { return (<div className={hi.containerStyle2}> {"建立組件方式二"} <hr /> {"獲取props值(只讀):{name=" + this.props.name + ",age=" + this.props.age + ",sex=" + this.props.sex + "}"} <div className='content'>{"獲取state值(讀寫):" + this.state.name}</div> <hr /> <button onClick={this.handleClink.bind(this)} className="btn btn-primary">修改state值</button> <hr /> {this.state.nickName.map(item =>{ return (<div key={item.id}> {item.name} <button onClick={this.handleClinkNickName.bind(this, item)} className="btn btn-primary"> 獲取本item值 </button> </div>) })} </div>) } }
12.webpack語法之組件抽離成獨立文件,在src下建立hello文件夾,並在其下建立Hello.jsx和Hi.jsx文件,修改index.js
// Hello.jsx import React from 'react' // 建立組件方式一 export default function Hello(props) { return (<div className="container"> {"建立組件方式一: 接收值(只讀):{name=" + props.name + ",age=" + props.age + ",sex=" + props.sex + "}"} </div>) }
// Hi.jsx import React from 'react' export default class Hi extends React.Component{ render() { return (<div className="container"> {"建立組件方式二: 接收值(只讀):{name=" + this.props.name + ",age=" + this.props.age + ",sex=" + this.props.sex + "}"} </div>) } }
import React from 'react' import ReactDOM from 'react-dom' // 建立組件方式一二 import Hello from './hello/Hello.jsx' import Hi from './hello/Hi.jsx' // 1.建立虛擬DOM元素 // parm1:字符串,元素名稱 // parm2:對象或null,元素屬性 // parm3:子節點(虛擬DOM或文本節點) // ... // parmn:子節點 // <div>歡迎</div> const div = React.createElement('div', null, '歡迎') // <h1 id="header">首頁</h1> const h1 = React.createElement('h1', {id: 'header'}, '首頁,哈哈', div) const a = "歡迎來到JSX" const b = ['sad', 'da', 'daszc', 'dafc'] const c = { name: 'pascall', age: 20, sex: 'man' } // 2.渲染虛擬DOM // parm1:虛擬DOM // parm2:掛在節點 ReactDOM.render( <div className="continer"> <Hello {...c} /> <hr /> <Hi {...c} /> </div>, document.getElementById('app'))
13.webpack語法之配置省略後綴名(webpack.config.js)
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') // 建立一個插件實例對象 const htmlPlugin = new HtmlWebpackPlugin({ template: path.join(__dirname, './src/index.html'), // 源文件路徑 filename: 'index.html' // 生成內存中首頁的名稱 }) // 向外暴露一個配置對象 // 由於 webpack 是基於Node構建的;因此 webpack 支持全部Node API 和語法 // webpack默認只能處理.js後綴名的文件,須要配置規則 module.exports = { mode: 'development', // development production plugins: [ htmlPlugin ], // 全部第三方模塊的配置規則 module: { rules: [ {test: /\.js|jsx$/, use: ['babel-loader'], exclude: /node_modules/} ] }, // 配置省略後綴名 resolve: { // 默認.js, .json extensions: [".js", ".jsx", ".json"] } }
import React from 'react' import ReactDOM from 'react-dom' // 建立組件方式一二 import Hello from './hello/Hello' import Hi from './hello/Hi' // 1.建立虛擬DOM元素 // parm1:字符串,元素名稱 // parm2:對象或null,元素屬性 // parm3:子節點(虛擬DOM或文本節點) // ... // parmn:子節點 // <div>歡迎</div> const div = React.createElement('div', null, '歡迎') // <h1 id="header">首頁</h1> const h1 = React.createElement('h1', {id: 'header'}, '首頁,哈哈', div) const a = "歡迎來到JSX" const b = ['sad', 'da', 'daszc', 'dafc'] const c = { name: 'pascall', age: 20, sex: 'man' } // 2.渲染虛擬DOM // parm1:虛擬DOM // parm2:掛在節點 ReactDOM.render( <div className="continer"> <Hello {...c} /> <hr /> <Hi {...c} /> </div>, document.getElementById('app'))
14.webpack語法之配置路徑別名
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') // 建立一個插件實例對象 const htmlPlugin = new HtmlWebpackPlugin({ template: path.join(__dirname, './src/index.html'), // 源文件路徑 filename: 'index.html' // 生成內存中首頁的名稱 }) // 向外暴露一個配置對象 // 由於 webpack 是基於Node構建的;因此 webpack 支持全部Node API 和語法 // webpack默認只能處理.js後綴名的文件,須要配置規則 module.exports = { mode: 'development', // development production plugins: [ htmlPlugin ], // 全部第三方模塊的配置規則 module: { rules: [ {test: /\.js|jsx$/, use: ['babel-loader'], exclude: /node_modules/} ] }, // 配置省略後綴名和路徑別名 resolve: { // 默認.js, .json extensions: [".js", ".jsx", ".json"], alias: { '@': path.join(__dirname, "./src") } } }
import React from 'react' import ReactDOM from 'react-dom' // 建立組件方式一二 import Hello from '@/hello/Hello' import Hi from '@/hello/Hi' // 1.建立虛擬DOM元素 // parm1:字符串,元素名稱 // parm2:對象或null,元素屬性 // parm3:子節點(虛擬DOM或文本節點) // ... // parmn:子節點 // <div>歡迎</div> const div = React.createElement('div', null, '歡迎') // <h1 id="header">首頁</h1> const h1 = React.createElement('h1', {id: 'header'}, '首頁,哈哈', div) const a = "歡迎來到JSX" const b = ['sad', 'da', 'daszc', 'dafc'] const c = { name: 'pascall', age: 20, sex: 'man' } // 2.渲染虛擬DOM // parm1:虛擬DOM // parm2:掛在節點 ReactDOM.render( <div className="continer"> <Hello {...c} /> <hr /> <Hi {...c} /> </div>, document.getElementById('app'))