<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        基于Webpack4和React hooks搭建項目的方法

        來源:懂視網 責編:小采 時間:2020-11-27 22:01:10
        文檔

        基于Webpack4和React hooks搭建項目的方法

        基于Webpack4和React hooks搭建項目的方法:面對日新月異的前端,我表示快學不動了:joy:。 Webpack 老早就已經更新到了 V4.x,前段時間 React 又推出了 hooks API。剛好春節在家里休假,時間比較空閑,還是趕緊把 React 技術棧這塊補上。 網上有很多介紹 hooks 知識點的文章,但都比較零碎,基本
        推薦度:
        導讀基于Webpack4和React hooks搭建項目的方法:面對日新月異的前端,我表示快學不動了:joy:。 Webpack 老早就已經更新到了 V4.x,前段時間 React 又推出了 hooks API。剛好春節在家里休假,時間比較空閑,還是趕緊把 React 技術棧這塊補上。 網上有很多介紹 hooks 知識點的文章,但都比較零碎,基本

        面對日新月異的前端,我表示快學不動了:joy:。 Webpack 老早就已經更新到了 V4.x,前段時間 React 又推出了 hooks API。剛好春節在家里休假,時間比較空閑,還是趕緊把 React 技術棧這塊補上。

        網上有很多介紹 hooks 知識點的文章,但都比較零碎,基本只能寫一些小 Demo 。還沒有比較系統的,全新的基于 hooks 進行搭建實際項目的講解。所以這里就從開發實際項目的角度,搭建起單頁面 Web App 項目的基本腳手架,并基于 hooks API 實現一個 react 項目模版。

        Hooks最吸引人的地方就是用 函數式組件 代替面向對象的 類組件 。此前的 react 如果涉及到狀態,解決方案通常只能使用 類組件 ,業務邏輯一復雜就容易導致組件臃腫,模塊的解藕也是個問題。而使用基于 hooks 的 函數組件 后,代碼不僅更加簡潔,寫起來更爽,而且模塊復用也方便得多,非常看好它的未來。

        webpack 4 的配置

        沒有使用 create-react-app 這個腳手架,而是從頭開始配置開發環境,因為這樣自定義配置某些功能會更方便些。下面這個是通用的配置 webpack.common.js 文件。

        const { resolve } = require('path');
        const HtmlWebpackPlugin = require('html-webpack-plugin');
        const CleanWebpackPlugin = require('clean-webpack-plugin');
        const { HotModuleReplacementPlugin } = require('webpack');
        
        module.exports = {
         entry: './src/index.js',//單入口
         output: {
         path: resolve(__dirname, 'dist'),
         filename: '[name].[hash].js'//
        輸出文件添加hash }, optimization: { // 代替commonchunk, 代碼分割 runtimeChunk: 'single', splitChunks: { cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all' } } } }, module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: ['babel-loader'] }, { test: /\.css$/, use: ['style-loader', 'css-loader'] }, { test: /\.scss$/, use: ['style-loader', { loader: 'css-loader', options: { importLoaders: 1, modules: true,//css modules localIdentName: '[name]___[local]___[hash:base64:5]' }, }, 'postcss-loader', 'sass-loader'] }, { /* 當文件體積小于 limit 時,url-loader 把文件轉為 Data URI 的格式內聯到引用的地方 當文件大于 limit 時,url-loader 會調用 file-loader, 把文件儲存到輸出目錄,并把引用的文件路徑改寫成輸出后的路徑 */ test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/, use: [{ loader: 'url-loader', options: { limit: 1000 } }] } ] }, plugins: [ new CleanWebpackPlugin(['dist']),//生成新文件時,清空生出目錄 new HtmlWebpackPlugin({ template: './public/index.html',//模版路徑 favicon: './public/favicon.png', minify: { //壓縮 removeAttributeQuotes:true, removeComments: true, collapseWhitespace: true, removeScriptTypeAttributes:true, removeStyleLinkTypeAttributes:true }, }), new HotModuleReplacementPlugin()//HMR ] };

        接著基于 webpack.common.js 文件,配置出開發環境的 webpack.dev.js 文件,主要就是啟動開發服務器。

        const merge = require('webpack-merge');
        const common = require('./webpack.common.js');
        
        module.exports = merge(common, {
         mode: 'development',
         devtool: 'inline-source-map',
         devServer: {
         contentBase: './dist',
         port: 4001,
         hot: true
         }
        });

        生成模式的 webpack.prod.js 文件,只要定義了 mode:'production' , webpack 4 打包時就會自動壓縮優化代碼。

        const merge = require('webpack-merge');
        const common = require('./webpack.common.js');
        
        module.exports = merge(common, {
         mode: 'production',
         devtool: 'source-map'
        });
        
        

        配置 package.js 中的 scripts

        {
         "scripts": {
         "start": "webpack-dev-server --open --config webpack.dev.js",
         "build": "webpack --config webpack.prod.js"
         }
        }
        

        Babel 的配置

        babel的 .babelrc 文件, css module 包這里推薦 babel-plugin-react-css-modules 。

        react-css-modules既支持全局的css(默認 className 屬性),同時也支持局部css module( styleName 屬性),還支持css預編譯器,這里使用的是 scss 。

        {
         "presets": [
         "@babel/preset-env",
         "@babel/preset-react"
         ],
         "plugins": [
         "@babel/plugin-proposal-class-properties",
         "@babel/plugin-transform-runtime",
         [
         "react-css-modules",
         {
         "exclude": "node_modules",
         "filetypes": {
         ".scss": {
         "syntax": "postcss-scss"
         }
         },
         "generateScopedName": "[name]___[local]___[hash:base64:5]"
         }
         ]
         ]
        }

        React 項目

        下面是項目基本的目錄樹結構,接著從入口開始一步步細化整個項目。

        ├ package.json
        ├ src
        │ ├ component // 組件目錄
        │ ├ reducer // reducer目錄
        │ ├ action.js
        │ ├ constants.js
        │ ├ context.js
        │ └ index.js
        ├ public // 靜態文件目錄
        │ ├ css
        │ └ index.html
        ├ .babelrc
        ├ webpack.common.js
        ├ webpack.dev.js
        └ webpack.prod.js
        

        狀態管理組件使用 redux , react-router 用于構建單頁面的項目,因為使用了 hooks API,所以不再需要 react-redux 連接狀態 state 。

        <Context.Provider value={{ state, dispatch }}>基本代替了 react-redux 的 ** `。

        // index.js
        import React, { useReducer } from 'react'
        import { render } from 'react-dom'
        import { HashRouter as Router, Route, Redirect, Switch } from 'react-router-dom'
        import Context from './context.js'
        import Home from './component/home.js'
        import List from './component/list.js'
        import rootReducer from './reducer'
        import '../public/css/index.css'
        
        const Root = () => {
         const initState = {
         list: [
         { id: 0, txt: 'webpack 4' },
         { id: 1, txt: 'react' },
         { id: 2, txt: 'redux' },
         ]
         };
         // useReducer映射出state,dispatch
         const [state, dispatch] = useReducer(rootReducer, initState);
         return <Context.Provider value={{ state, dispatch }}>
         <Router>
         <Switch>
         <Route exact path="/" component={Home} />
         <Route exact path="/list" component={List} />
         <Route render={() => (<Redirect to="/" />)} />
         </Switch>
         </Router>
         </Context.Provider>
        }
        render(
         <Root />,
         document.getElementById('root')
        )
        
        

        constants.js, action.js 和 reducer.js 與之前的寫法是一致的。

        // constants.js
        export const ADD_COMMENT = 'ADD_COMMENT'
        export const REMOVE_COMMENT = 'REMOVE_COMMENT'
        // action.js
        import { ADD_COMMENT, REMOVE_COMMENT } from './constants'
        
        export function addComment(comment) {
         return {
         type: ADD_COMMENT,
         comment
         }
        }
        
        export function removeComment(id) {
         return {
         type: REMOVE_COMMENT,
         id
         }
        }
        
        

        list.js

        import { ADD_COMMENT, REMOVE_COMMENT } from '../constants.js'
        
        const list = (state = [], payload) => {
         switch (payload.type) {
         case ADD_COMMENT:
         if (Array.isArray(payload.comment)) {
         return [...state, ...payload.comment];
         } else {
         return [...state, payload.comment];
         }
         case REMOVE_COMMENT:
         return state.filter(i => i.id != payload.id);
         default: return state;
         }
        };
        export default list

        reducer.js

        import { combineReducers } from 'redux'
        import list from './list.js'
        
        const rootReducer = combineReducers({
         list,
         //user
        });
        
        export default rootReducer
        
        

        最大區別的地方就是 component 組件,基于 函數式 ,內部的表達式就像是即插即用的插槽,可以很方便的抽取出通用的組件,然后從外部引用。相比之前的 面向對象 方式,我覺得 函數表達式 更受前端開發者歡迎。

      1. useContext 獲取全局的 state
      2. useRef 代替之前的 ref
      3. useState 代替之前的 state
      4. useEffect則可以代替之前的生命周期鉤子函數
      5. //監控數組中的參數,一旦變化就執行
        useEffect(() => { updateData(); },[id]);
        
        //不傳第二個參數的話,它就等價于每次componentDidMount和componentDidUpdate時執行
        useEffect(() => { updateData(); });
        
        //第二個參數傳空數組,等價于只在componentDidMount和componentWillUnMount時執行, 
        //第一個參數中的返回函數用于執行清理功能
        useEffect(() => { 
         initData(); 
         reutrn () => console.log('componentWillUnMount cleanup...'); 
        }, []);
        
        

        最后就是實現具體界面和業務邏輯的組件了,下面是其中的List組件

        // list.js
        import React, { useRef, useState, useContext } from 'react'
        import { bindActionCreators } from 'redux'
        import { Link } from 'react-router-dom'
        import Context from '../context.js'
        import * as actions from '../action.js'
        import Dialog from './dialog.js'
        import './list.scss'
        
        const List = () => {
         const ctx = useContext(Context);//獲取全局狀態state
         const { user, list } = ctx.state;
         const [visible, setVisible] = useState(false);
         const [rid, setRid] = useState('');
         const inputRef = useRef(null);
         const { removeComment, addComment } = bindActionCreators(actions, ctx.dispatch);
        
         const confirmHandle = () => {
         setVisible(false);
         removeComment(rid);
         }
        
         const cancelHandle = () => {
         setVisible(false);
         }
        
         const add = () => {
         const input = inputRef.current,
         val = input.value.trim();
         if (!val) return;
         addComment({
         id: Math.round(Math.random() * 1000000),
         txt: val
         });
         input.value = '';
         }
        
         return <>
         <div styleName="form">
         <h3 styleName="sub-title">This is list page</h3>
         <div>
         <p>hello, {user.name} !</p>
         <p>your email is {user.email} !</p>
         <p styleName="tip">please add and remove the list item !!</p>
         </div>
         <ul> {
         list.map(l => <li key={l.id}>{l.txt}<i className="icon-minus" title="remove item" onClick={() => {
         setVisible(true);
         setRid(l.id);
         }}></i></li>)
         } </ul>
         <input ref={inputRef} type="text" />
         <button onClick={add} title="add item">Add Item</button>
         <Link styleName="link" to="/">redirect to home</Link>
         </div>
         <Dialog visible={visible} confirm={confirmHandle} cancel={cancelHandle}>remove this item ?</Dialog>
         </>
        }
        
        export default List;

        項目代碼

        https://github.com/edwardzhong/webpack_react

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        基于Webpack4和React hooks搭建項目的方法

        基于Webpack4和React hooks搭建項目的方法:面對日新月異的前端,我表示快學不動了:joy:。 Webpack 老早就已經更新到了 V4.x,前段時間 React 又推出了 hooks API。剛好春節在家里休假,時間比較空閑,還是趕緊把 React 技術棧這塊補上。 網上有很多介紹 hooks 知識點的文章,但都比較零碎,基本
        推薦度:
        標簽: 基于 React webpack
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 中文字幕在线观看亚洲视频| 亚洲一区精品无码| 亚洲乱码卡一卡二卡三| 91精品国产免费久久国语麻豆| 国产亚洲综合网曝门系列| 好吊妞788免费视频播放| 亚洲国产人成在线观看| 欧美好看的免费电影在线观看 | 成年人免费视频观看| 亚洲人成7777影视在线观看| www.免费在线观看| 亚洲熟妇无码一区二区三区导航| 成年性羞羞视频免费观看无限| 亚洲熟妇自偷自拍另欧美| 亚洲?V无码成人精品区日韩| 亚洲最新永久在线观看| 日本免费xxxx| 亚洲成AV人片高潮喷水| 亚洲国产精品成人网址天堂| 两个人日本WWW免费版| 亚洲综合在线观看视频| 在人线av无码免费高潮喷水| 国产成人亚洲精品青草天美| 三级片免费观看久久| 亚洲Av永久无码精品三区在线| 99精品视频免费观看| 亚洲中文字幕无码久久2020| 伊在人亚洲香蕉精品区麻豆| 99精品全国免费观看视频..| 亚洲一区二区三区在线观看蜜桃 | 亚洲av麻豆aⅴ无码电影| 黄 色一级 成 人网站免费| 亚洲黄色免费网站| 日韩免费视频一区| 国产偷伦视频免费观看| 亚洲日本久久久午夜精品| 久久夜色精品国产亚洲av| 美女视频黄免费亚洲| 国产精品hd免费观看| 亚洲一区电影在线观看| 国产AV无码专区亚洲AV手机麻豆|