自己寫的 React, Webpack 練習,
練習了以下 webpack loader:
sass-loader :
用來處理編譯 sass 檔案。
css-loader :
用來處理 css 檔案。
style-loader :
用來將 css 寫進網頁中 (不用在網頁中另寫 <link rel="stylesheet" href="xxx.css" />)。
image-webpack-loader :
用來處理圖片檔案,有圖片壓縮等功能。
url-loader :
用來將圖片的 url 寫進網頁中,內部使用了 file-loader,所以可使用 file-loader 的選項參數,
有能把圖片的 url 轉成 base64 url 的等功能。
mini-css-extract-plugin :
用來把處理好的 css 輸出成最後版本 css 檔案的功能,
網頁要使用 css 需自行加入 css style include, Ex:
<link rel="stylesheet" href="xxx.css" />)
實作了一個簡易的 tab 選單當範例來練習:
1. 有三個選單 tab,分別對應三個內容 (暫稱 content),內容中有各自的文字及各放置了不同的圖片。
2. 當滑鼠滑入 tab 中時 (mouseenter) ,下方會切換到對應的 Content。
檔案結構如下圖所示:
重要的程式碼如下 (以下根目錄以從 package.json 檔所在位置,也就是 WebContent 資料夾算起):
/index.html :
<!DOCTYPE html> <html> <head> </head> <body> <div id="root"></div> <script src="dist/js/index_bundle.js"></script> </body> </html>/dev/js/index.jsx :
import React from "react" import ReactDOM from "react-dom" import {Main} from "./components/Main.jsx" import "@projectDirPath/dev/css/style.scss" ReactDOM.render(<Main/>, document.getElementById("root"));/dev/js/components/Main.jsx :
import React from "react" import {Tab} from "./Tab.jsx" import {Content} from "./Content.jsx" import dogImgSrc from "@projectDirPath/dev/img/dog.jpg" import catImgSrc from "@projectDirPath/dev/img/cat.jpg" import bananaCatImgSrc from "@projectDirPath/dev/img/bananaCat.jpg" function Main(){ const [itemList, setItemList] = React.useState([ { title: "title1", desc: "desc1", img: dogImgSrc, isActive: true }, { title: "title2", desc: "desc2", img: catImgSrc, isActive: false }, { title: "title3", desc: "desc3", img: bananaCatImgSrc, isActive: false } ]); function setItemActive(index){ var updatedItemList = itemList.map((item, i) => { item.isActive = (i == index); return item; }); setItemList(updatedItemList); } return ( <React.Fragment> <div className="tab"> { itemList.map((item, index) => { return <Tab item={item} key={index} index={index} setItemActive={setItemActive}/>; }) } </div> <div className="content"> { itemList.map((item, index) => { return <Content item={item} key={index}/>; }) } </div> </React.Fragment> ) } export {Main}/dev/js/components/Content.jsx :
import React from "react" function Content({item}){ return ( <div className={item.isActive ? "active" : ""}>{item.desc}<img src={item.img}/></div> ); } export {Content}/dev/js/components/Tab.jsx :
import React from "react" function Tab({item, index, setItemActive}){ function handleMouseEnter(){ setItemActive(index); } return ( <div className={item.isActive ? "active" : ""} onMouseEnter={handleMouseEnter}>{item.title}</div> ); } export {Tab}/dev/css/style.scss :
.tab { div { display: inline-block; width: 30%; height: 100px; background-color: green; background-color: yellow; border-bottom: 3px solid black; } div.active { background-color: yellow; border-left: 3px solid black; border-right: 3px solid black; border-top: 3px solid black; border-bottom: 3px solid yellow; } } .content { background-color: yellow; border-left: 3px solid black; border-right: 3px solid black; border-bottom: 3px solid black; div { display: none; padding: 3px; } div.active { display: block; } img { width : 30%; } }
webpack.config.js:
var path = require('path'); //const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { entry : "./dev/js/index.jsx", output : { path : path.resolve(__dirname, "dist"), filename : "js/index_bundle.js", publicPath : "dist/" }, resolve: { alias: { '@projectDirPath': __dirname } }, watch : false, devtool : 'source-map', mode : "development", //"production", module : { rules : [ { test : /\.jsx?$/, use : { loader : 'babel-loader', options : { presets : [ '@babel/preset-react', '@babel/preset-env' ] } } }, { test: /\.(png|jpg|gif|jpe?g|svg)$/, use: [ { loader: 'url-loader', options: { limit: 50 * 1024, outputPath: "img" } }, "image-webpack-loader" ] },/* { test : /\.css$/, use : ["style-loader", "css-loader"] },*/ { test: /\.s[ac]ss$/, use: [ "style-loader", //MiniCssExtractPlugin.loader, "css-loader", "sass-loader" ] }] } //, plugins: [new MiniCssExtractPlugin()] }
package.json
{ "name": "reacttest", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "webpack", "runServer": "lite-server" }, "author": "", "license": "ISC", "devDependencies": { "@babel/core": "^7.7.5", "@babel/preset-env": "^7.7.5", "@babel/preset-react": "^7.7.4", "babel-loader": "^8.0.6", "css-loader": "^5.0.1", "file-loader": "^6.2.0", "image-webpack-loader": "^7.0.1", "lite-server": "^2.6.1", "mini-css-extract-plugin": "^1.3.3", "node-sass": "^5.0.0", "sass-loader": "^10.1.0", "style-loader": "^2.0.0", "url-loader": "^4.1.1", "webpack": "^4.41.2", "webpack-cli": "^3.3.10" }, "dependencies": { "react": "^16.12.0", "react-dom": "^16.12.0", "react-redux": "^7.2.2", "redux": "^4.0.5" } }
原始碼分享下載:
參考:
沒有留言 :
張貼留言