国产精品爱久久久久久久小说,女人扒开腿让男人桶到爽 ,亚洲欧美国产双大乳头,国产成人精品综合久久久久,国产精品制服丝袜无码,免费无码精品黄av电影,黑色丝袜无码中中文字幕,乱熟女高潮一区二区在线

            react全家桶從0搭建一個完整的react項目(react-router4、redux、redux-saga)

            2021-5-31    前端達人

            react全家桶從0到1(最新)

            本文從零開始,逐步講解如何用react全家桶搭建一個完整的react項目。文中針對react、webpack、babel、react-route、redux、redux-saga的核心配置會加以講解,通過這個項目,可以系統的了解react技術棧的主要知識,避免搭建一次后面就忘記的情況。

            代碼庫:https://github.com/teapot-py/react-demo

            首先關于主要的npm包版本列一下:

            1. react@16.7.0
            2. webpack@4.28.4
            3. babel@7+
            4. react-router@4.3.1
            5. redux@4+

            從webpack開始

            思考一下webpack到底做了什么事情?其實簡單來說,就是從入口文件開始,不斷尋找依賴,同時為了解析各種不同的文件加載相應的loader,最后生成我們希望的類型的目標文件。

            這個過程就像是在一個迷宮里尋寶,我們從入口進入,同時我們也會不斷的接收到下一處寶藏的提示信息,我們對信息進行解碼,而解碼的時候可能需要一些工具,比如說鑰匙,而loader就像是這樣的鑰匙,然后得到我們可以識別的內容。

            回到我們的項目,首先進行項目的初始化,分別執行如下命令

            mkdir react-demo // 新建項目文件夾
            cd react-demo // cd到項目目錄下
            npm init // npm初始化 
            
            • 1
            • 2
            • 3

            引入webpack

            npm i webpack --save
            touch webpack.config.js 
            
            • 1
            • 2

            對webpack進行簡單配置,更新webpack.config.js

            const path = require('path');
            
            module.exports = {
              entry: './app.js', // 入口文件
              output: {
                path: path.resolve(__dirname, 'dist'), // 定義輸出目錄
                filename: 'my-first-webpack.bundle.js'  // 定義輸出文件名稱
              }
            }; 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10

            更新package.json文件,在scripts中添加webpack執行命令

            "scripts": {
              "dev": "./node_modules/.bin/webpack --config webpack.config.js"
            } 
            
            • 1
            • 2
            • 3

            如果有報錯請按提示安裝webpack-cli

            npm i webpack-cli 
            
            • 1

            執行webpack

            npm run dev 
            
            • 1

            如果在項目文件夾下生成了dist文件,說明我們的配置是沒有問題的。

            接入react

            安裝react相關包

            npm install react react-dom --save 
            
            • 1

            更新app.js入口文件

            import React from 'react
            import ReactDom from 'react-dom';
            import App from './src/views/App';
            
            ReactDom.render(<App />, document.getElementById('root')); 
            
            • 1
            • 2
            • 3
            • 4
            • 5

            創建目錄 src/views/App,在App目錄下,新建index.js文件作為App組件,index.js文件內容如下:

            import React from 'react';
            
            class App extends React.Component {
            
                constructor(props) {
                    super(props);
                }
            
                render() {
                    return (<div>App Container</div>);
                }
            }
            export default App; 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13

            在根目錄下創建模板文件index.html

            <!DOCTYPE html>
            <html>
            <head>
                <title>index</title>
                <meta charset="utf-8">
                <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
            </head>
            <body>
                <div id="root"></div>
            </body>
            </html> 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11

            到了這一步其實關于react的引入就OK了,不過目前還有很多問題沒有解決

            1. 如何解析JS文件的代碼?
            2. 如何將js文件加入模板文件中?

            Babel解析js文件

            Babel是一個工具鏈,主要用于在舊的瀏覽器或環境中將ECMAScript2015+的代碼轉換為向后兼容版本的JavaScript代碼。

            安裝babel-loader,@babel/core,@babel/preset-env,@babel/preset-react

            npm i babel-loader@8 @babel/core @babel/preset-env @babel/preset-react -D 
            
            • 1
            1. babel-loader:使用Babel轉換JavaScript依賴關系的Webpack加載器, 簡單來講就是webpack和babel中間層,允許webpack在遇到js文件時用bable來解析
            2. @babel/core:即babel-core,將ES6代碼轉換為ES5。7.0之后,包名升級為@babel/core。@babel相當于一種官方標記,和以前大家隨便起名形成區別。
            3. @babel/preset-env:即babel-preset-env,根據您要支持的瀏覽器,決定使用哪些transformations / plugins 和 polyfills,例如為舊瀏覽器提供現代瀏覽器的新特性。
            4. @babel/preset-react:即 babel-preset-react,針對所有React插件的Babel預設,例如將JSX轉換為函數.

            更新webpack.config.js

             module: {
                rules: [
                  {
                    test: /\.js$/, // 匹配.js文件
                    exclude: /node_modules/,
                    use: {
                      loader: 'babel-loader'
                    }
                  }
                ]
              } 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11

            根目錄下創建并配置.babelrc文件

            {
              "presets": ["@babel/preset-env", "@babel/preset-react"]
            } 
            
            • 1
            • 2
            • 3

            配置HtmlWebPackPlugin

            這個插件最主要的作用是將js代碼通過

            npm i html-webpack-plugin -D 
            
            • 1

            webpack新增HtmlWebPackPlugin配置

            至此,我們看一下webpack.config.js文件的完整結構

            const path = require('path');
            
            const HtmlWebPackPlugin = require('html-webpack-plugin');
            
            module.exports = {
              entry: './app.js',
              output: {
                path: path.resolve(__dirname, 'dist'),
                filename: 'my-first-webpack.bundle.js'
              },
              mode: 'development',
              module: {
                rules: [
                  {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    use: {
                      loader: 'babel-loader'
                    }
                  }
                ]
              },
              plugins: [
                new HtmlWebPackPlugin({
                  template: './index.html',
                  filename: path.resolve(__dirname, 'dist/index.html')
                })
              ]
            }; 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29

            執行 npm run start,生成 dist文件夾

            當前目錄結構如下
            目錄結構

            可以看到在dist文件加下生成了index.html文件,我們在瀏覽器中打開文件即可看到App組件內容。

            配置 webpack-dev-server

            webpack-dev-server可以極大的提高我們的開發效率,通過監聽文件變化,自動更新頁面

            安裝 webpack-dev-server 作為 dev 依賴項

            npm i webpack-dev-server -D 
            
            • 1

            更新package.json的啟動腳本

            “dev": "webpack-dev-server --config webpack.config.js --open" 
            
            • 1

            webpack.config.js新增devServer配置

            devServer: {
              hot: true, // 熱替換
              contentBase: path.join(__dirname, 'dist'), // server文件的根目錄
              compress: true, // 開啟gzip
              port: 8080, // 端口
            },
            plugins: [
              new webpack.HotModuleReplacementPlugin(), // HMR允許在運行時更新各種模塊,而無需進行完全刷新
              new HtmlWebPackPlugin({
                template: './index.html',
                filename: path.resolve(__dirname, 'dist/index.html')
              })
            ] 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13

            引入redux

            redux是用于前端數據管理的包,避免因項目過大前端數據無法管理的問題,同時通過單項數據流管理前端的數據狀態。

            創建多個目錄

            1. 新建src/actions目錄,用于創建action函數
            2. 新建src/reducers目錄,用于創建reducers
            3. 新建src/store目錄,用于創建store

            下面我們來通過redux實現一個計數器的功能

            安裝依賴

            npm i redux react-redux -D 
            
            • 1

            在actions文件夾下創建index.js文件

            export const increment = () => {
              return {
                type: 'INCREMENT',
              };
            }; 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6

            在reducers文件夾下創建index.js文件

            const initialState = {
              number: 0
            };
            
            const incrementReducer = (state = initialState, action) => {
              switch(action.type) {
                case 'INCREMENT': {
                  state.number += 1
                  return { ...state }
                  break
                };
                default: return state;
              }
            };
            export default incrementReducer; 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15

            更新store.js

            import { createStore } from 'redux';
            import incrementReducer from './reducers/index';
            
            const store = createStore(incrementReducer);
            
            export default store; 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7

            更新入口文件app.js

            import App from './src/views/App';
            import ReactDom from 'react-dom';
            import React from 'react';
            import store from './src/store';
            import { Provider } from 'react-redux';
            
            ReactDom.render(
                <Provider store={store}>
                    <App />
                </Provider>
            , document.getElementById('root')); 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11

            更新App組件

            import React from 'react';
            import { connect } from 'react-redux';
            import { increment } from '../../actions/index';
            
            class App extends React.Component {
            
                constructor(props) {
                    super(props);
                }
            
                onClick() {
                    this.props.dispatch(increment())
                }
            
                render() {
                    return (
                        <div>
                            <div>current number: {this.props.number} <button onClick={()=>this.onClick()}>點擊+1</button></div>
            
                        </div>
                    );
                }
            }
            export default connect(
                state => ({
                    number: state.number
                })
            )(App); 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28

            點擊旁邊的數字會不斷地+1

            引入redux-saga

            redux-saga通過監聽action來執行有副作用的task,以保持action的簡潔性。引入了sagas的機制和generator的特性,讓redux-saga非常方便地處理復雜異步問題。
            redux-saga的原理其實說起來也很簡單,通過劫持異步action,在redux-saga中進行異步操作,異步結束后將結果傳給另外的action。

            下面就接著我們計數器的例子,來實現一個異步的+1操作。

            安裝依賴包

            npm i redux-saga -D 
            
            • 1

            新建src/sagas/index.js文件

            import { delay } from 'redux-saga'
            import { put, takeEvery } from 'redux-saga/effects'
            
            export function* incrementAsync() {
              yield delay(2000)
              yield put({ type: 'INCREMENT' })
            }
            
            export function* watchIncrementAsync() {
              yield takeEvery('INCREMENT_ASYNC', incrementAsync)
            } 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11

            解釋下所做的事情,將watchIncrementAsync理解為一個saga,在這個saga中監聽了名為INCREMENT_ASYNC的action,當INCREMENT_ASYNC被dispatch時,會調用incrementAsync方法,在該方法中做了異步操作,然后將結果傳給名為INCREMENT的action進而更新store。

            更新store.js

            在store中加入redux-saga中間件

            import { createStore, applyMiddleware } from 'redux';
            import incrementReducer from './reducers/index';
            import createSagaMiddleware from 'redux-saga'
            import { watchIncrementAsync } from './sagas/index'
            
            const sagaMiddleware = createSagaMiddleware()
            const store = createStore(incrementReducer, applyMiddleware(sagaMiddleware));
            sagaMiddleware.run(watchIncrementAsync)
            export default store; 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9

            更新App組件

            在頁面中新增異步提交按鈕,觀察異步結果

            import React from 'react';
            import { connect } from 'react-redux';
            import { increment } from '../../actions/index';
            
            class App extends React.Component {
            
                constructor(props) {
                    super(props);
                }
            
                onClick() {
                    this.props.dispatch(increment())
                }
            
                onClick2() {
                    this.props.dispatch({ type: 'INCREMENT_ASYNC' })
                }
            
                render() {
                    return (
                        <div>
                            <div>current number: {this.props.number} <button onClick={()=>this.onClick()}>點擊+1</button></div>
                            <div>current number: {this.props.number} <button onClick={()=>this.onClick2()}>點擊2秒后+1</button></div>
                        </div>
                    );
                }
            }
            export default connect(
                state => ({
                    number: state.number
                })
            )(App); 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32

            觀察結果我們會發現如下報錯:

            這是因為在redux-saga中用到了Generator函數,以我們目前的babel配置來說并不支持解析generator,需要安裝@babel/plugin-transform-runtime

            npm install --save-dev @babel/plugin-transform-runtime 
            
            • 1

            這里關于babel-polyfill、和transfor-runtime做進一步解釋

            babel-polyfill

            Babel默認只轉換新的JavaScript語法,而不轉換新的API。例如,Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局對象,以及一些定義在全局對象上的方法(比如Object.assign)都不會轉譯。如果想使用這些新的對象和方法,必須使用 babel-polyfill,為當前環境提供一個墊片。

            babel-runtime

            Babel轉譯后的代碼要實現源代碼同樣的功能需要借助一些幫助函數,而這些幫助函數可能會重復出現在一些模塊里,導致編譯后的代碼體積變大。
            Babel 為了解決這個問題,提供了單獨的包babel-runtime供編譯模塊復用工具函數。
            在沒有使用babel-runtime之前,庫和工具包一般不會直接引入 polyfill。否則像Promise這樣的全局對象會污染全局命名空間,這就要求庫的使用者自己提供 polyfill。這些 polyfill一般在庫和工具的使用說明中會提到,比如很多庫都會有要求提供 es5的polyfill。
            在使用babel-runtime后,庫和工具只要在 package.json中增加依賴babel-runtime,交給babel-runtime去引入 polyfill 就行了;
            詳細解釋可以參考

            babel presets 和 plugins的區別

            Babel插件一般盡可能拆成小的力度,開發者可以按需引進。比如對ES6轉ES5的功能,Babel官方拆成了20+個插件。
            這樣的好處顯而易見,既提高了性能,也提高了擴展性。比如開發者想要體驗ES6的箭頭函數特性,那他只需要引入transform-es2015-arrow-functions插件就可以,而不是加載ES6全家桶。
            但很多時候,逐個插件引入的效率比較低下。比如在項目開發中,開發者想要將所有ES6的代碼轉成ES5,插件逐個引入的方式令人抓狂,不單費力,而且容易出錯。
            這個時候,可以采用Babel Preset。
            可以簡單的把Babel Preset視為Babel Plugin的集合。比如babel-preset-es2015就包含了所有跟ES6轉換有關的插件。

            更新.babelrc文件配置,支持genrator

            {
              "presets": ["@babel/preset-env", "@babel/preset-react"],
              "plugins": [
                [
                  "@babel/plugin-transform-runtime",
                  {
                    "corejs": false,
                    "helpers": true,
                    "regenerator": true,
                    "useESModules": false
                  }
                ]
              ]
            } 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14


            點擊按鈕會在2秒后執行+1操作。

            引入react-router

            在web應用開發中,路由系統是不可或缺的一部分。在瀏覽器當前的URL發生變化時,路由系統會做出一些響應,用來保證用戶界面與URL的同步。隨著單頁應用時代的到來,為之服務的前端路由系統也相繼出現了。而react-route則是與react相匹配的前端路由。

            引入react-router-dom

            npm install --save react-router-dom -D 
            
            • 1

            更新app.js入口文件增加路由匹配規則

            import App from './src/views/App';
            import ReactDom from 'react-dom';
            import React from 'react';
            import store from './src/store';
            import { Provider } from 'react-redux';
            import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
            
            const About = () => <h2>頁面一</h2>;
            const Users = () => <h2>頁面二</h2>;
            
            ReactDom.render(
                <Provider store={store}>
                    <Router>
                        <Switch>
                            <Route path="/" exact component={App} />
                            <Route path="/about/" component={About} />
                            <Route path="/users/" component={Users} />
                        </Switch>
                    </Router>
                </Provider>
            , document.getElementById('root')); 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21

            更新App組件,展示路由效果

            import React from 'react';
            import { connect } from 'react-redux';
            import { increment } from '../../actions/index';
            import { Link } from "react-router-dom";
            
            class App extends React.Component {
            
                constructor(props) {
                    super(props);
                }
            
                onClick() {
                    this.props.dispatch(increment())
                }
            
                onClick2() {
                    this.props.dispatch({ type: 'INCREMENT_ASYNC' })
                }
            
                render() {
                    return (
                        <div>
                            <div>react-router 測試</div>
                            <nav>
                                <ul>
                                <li>
                                    <Link to="/about/">頁面一</Link>
                                </li>
                                <li>
                                    <Link to="/users/">頁面二</Link>
                                </li>
                                </ul>
                            </nav>
            
                            <br/>
                            <div>redux & redux-saga測試</div>
                            <div>current number: {this.props.number} <button onClick={()=>this.onClick()}>點擊+1</button></div>
                            <div>current number: {this.props.number} <button onClick={()=>this.onClick2()}>點擊2秒后+1</button></div>
                        </div>
                    );
                }
            }
            export default connect(
                state => ({
                    number: state.number
                })
            )(App); 
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
            • 24
            • 25
            • 26
            • 27
            • 28
            • 29
            • 30
            • 31
            • 32
            • 33
            • 34
            • 35
            • 36
            • 37
            • 38
            • 39
            • 40
            • 41
            • 42
            • 43
            • 44
            • 45
            • 46
            • 47
            • 48


            點擊列表可以跳轉相關路由

            總結

            至此,我們已經一步步的,完成了一個簡單但是功能齊全的react項目的搭建,下面回顧一下我們做的工作

            1. 引入webpack
            2. 引入react
            3. 引入babel解析react
            4. 接入webpack-dev-server提高前端開發效率
            5. 引入redux實現一個increment功能
            6. 引入redux-saga實現異步處理
            7. 引入react-router實現前端路由

            麻雀雖小,五臟俱全,希望通過最簡單的代碼快速的理解react工具鏈。其實這個小項目中還是很多不完善的地方,比如說樣式的解析、Eslint檢查、生產環境配置,雖然這幾項是一個完整項目不可缺少的部分,但是就demo項目來說,對我們理解react工具鏈可能會有些干擾,所以就不在項目中加了。

            后面會新建一個分支,把這些完整的功能都加上,同時也會對當前的目錄結構進行優化。



            藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

            截屏2021-05-13 上午11.41.03.png


            部分借鑒自:csdn  作者:鄭清

            原文鏈接:

            分享此文一切功德,皆悉回向給文章原作者及眾讀者.
            免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

            藍藍設計www.dzxscac.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

            日歷

            鏈接

            個人資料

            藍藍設計的小編 http://www.dzxscac.cn

            存檔

            主站蜘蛛池模板: 日韩精品电影在线观看| 热99re久久精品| 9色视频| 亚洲中文字幕日产无码成人片| 国产精品久久久久成人| 国产在线一| 午夜在线视频免费观看| 爱爱一区| 韩国毛片基地| 一区二区三区av波多野结衣| 中文字幕人妻一区| 精品久久久久国产| 女人扒开屁股桶爽30分钟| 中国娇小与黑人巨大交| 欧美巨乳在线观看| 国产高清女同学巨大乳在线观看| 巨爆中文字幕巨爆区爆乳| 少妇精品偷拍高潮白浆| 国产成人综合在线观看不卡| 成年女人爽到高潮喷视频 | 精精国产xxxx视频在线| 亚洲依依成人亚洲社区| 在线视频观看一区| 四虎成人精品永久网站| 国产美女被遭强高潮免费一视频| 成人高清在线| 一级少妇片| 国产乱人伦真实精品视频 | 日本一卡二卡3卡四卡网站精品| 成人午夜福利院在线观看| 91av免费在线观看| 久久久久久久久艹| 国产在线视欧美亚综合| 亚洲 暴爽 av人人爽日日碰| 人人模人人干| 又粗又猛又黄又爽无遮挡| 成人午夜高潮免费视频| av老司机在线| 午夜视频网站在线观看| 中文字幕av无码人妻| 日本一卡2卡3卡4卡5卡精品视频|