日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
聊聊React開發(fā)的一些坑(一)

[[404350]]

一、項目生成

  • create-react-app saucxs-web 生成項目
  • cd saucxs-web 進入項目
  • yarn start 啟動項目

二、項目部署

  • 本地開發(fā) yarn start
  • 線上部署 yarn build

三、參考文檔

  • react 英文文檔[1]
  • create-react-app[2]
  • ant UI庫的配置參考[3]
  • react-router 英文[4]
  • react-router 中文[5]

四、配置項

1、Ant Design UI庫引入

  • yarn add antd 安裝UI庫
  • yarn add babel-plugin-import 實現(xiàn)按需引入

package.json/babel 中增加如下內(nèi)容:

 
 
 
  1. "plugins": [ 
  2.     [ 
  3.         "import", 
  4.         { 
  5.             "libraryName": "antd", 
  6.             "libraryDirectory": "es", 
  7.             "style": "css" 
  8.         } 
  9.     ] 

組件使用 如下:

 
 
 
  1. import React, { Component } from 'react'; 
  2. import { Button } from 'antd' 
  3. import 'antd/dist/antd.css' 
  4. class App extends Component { 
  5.   render() { 
  6.     return ( 
  7.         松寶寫代碼 
  8.     ); 
  9.   } 
  10. export default App; 

此時可以使用UI庫的默認樣式

2、自定義Ant Design UI庫樣式

  • 安裝 less 和 less-loader
  • 使用命令 yarn run eject 暴露配置文件
  • 在 webpack.config.dev.js 與 webpack.config.prod.js 中做如下修改:

創(chuàng)建 antModifyVars.js 文件

 
 
 
  1. 'use strict'; 
  2. const modifyVars = { 
  3.   'primary-color': '#E26A6A', 
  4. module.exports = modifyVars; 

創(chuàng)建 less 相關(guān)變量,參考默認sass的配置:

 
 
 
  1. // style files regexes 
  2. const cssRegex = /\.css$/; 
  3. const cssModuleRegex = /\.module\.css$/; 
  4. const sassRegex = /\.(scss|sass)$/; 
  5. const sassModuleRegex = /\.module\.(scss|sass)$/; 
  6. // 增加less部分 
  7. const lessRegex = /\.less/; 
  8. const lessModuleRegex = /\.module\.less$/; 

在 module.rules 的 oneOf 下, 仿照sass追加一下代碼:

 
 
 
  1. // Opt-in support for LESS (using .less extensions). 
  2. // Chains the less-loader with the css-loader and the style-loader 
  3. // to immediately apply all styles to the DOM. 
  4. // By default we support LESS Modules with the 
  5. // extensions .module.scss or .module.sass 
  6.     test: lessRegex, 
  7.     exclude: lessModuleRegex, 
  8.     use: getStyleLoaders({ importLoaders: 2 }, 'less-loader'), 
  9. }, 
  10. // Adds support for CSS Modules, but using SASS 
  11. // using the extension .module.scss or .module.sass 
  12.     test: lessModuleRegex, 
  13.     use: getStyleLoaders( 
  14.     { 
  15.         importLoaders: 2, 
  16.         modules: true, 
  17.         getLocalIdent: getCSSModuleLocalIdent, 
  18.     }, 
  19.     'less-loader'), 
  20. }, 

在 getStyleLoaders 中,處理 less-loader

 
 
 
  1. // dev下的配置 
  2. if (preProcessor) { 
  3.     let loader = {loader: require.resolve(preProcessor)} 
  4.     if (preProcessor === "less-loader") { 
  5.         loader.options.modifyVars = modifyVars 
  6.         loader.options.javascriptEnabled = true 
  7.     } 
  8.     loaders.push(loader); 
  9. // prod下的配置 
  10. if (preProcessor) { 
  11.     let loader = { 
  12.          loader: require.resolve(preProcessor), 
  13.          options: { 
  14.             sourceMap: shouldUseSourceMap, 
  15.         }, 
  16.     } 
  17.     if (preProcessor === "less-loader") { 
  18.         loader.options.modifyVars = modifyVars 
  19.         loader.options.javascriptEnabled = true 
  20.     } 
  21.     loaders.push(loader); 
  22.   } 

3、ES6 API支持,引入polyfills

增加低版本瀏覽器、IE瀏覽器對ES6API的支持,IE9,IE9+

方法一,安裝 yarn add react-app-polyfill

 
 
 
  1. // src/index.js中的【第一行】引入對IE9及更高版本的支持 
  2. import 'react-app-polyfill/ie9'; 
  3. // 其他支持,如:對IE11及更高版本的支持 
  4. import 'react-app-polyfill/ie11'; 

方法二,安裝 yarn add babel-polyfill

 
 
 
  1. // webpack.base.conf.js中引入: 
  2. require("babel-polyfill") 
  3. // webpack.base.conf.js中配置: 
  4. entry: { app: ['babel-polyfill', './src/main.js'] } 

4、引入 react-router-dom 路由

  • react-router-dom 依賴 react-router,所以使用npm安裝依賴的時候,只需要安裝相應(yīng)環(huán)境下的庫即可,不用再顯式安裝react-router。
  • 由于需要權(quán)限配置,所以增加AuthorizedRoute.js控制權(quán)限

5、配置別名,@ 指向 src 目錄

webpack.base.conf.js 與 webpack.base.conf.js的配置一致,如下:

 
 
 
  1. 定義resolvePath方法,新版中resolve名稱被占用 
  2. function resolvePath (dir) { 
  3.   return path.join(__dirname, '..', dir) 
  4. // resolve.alias中增加別名配置: 
  5. '@': resolvePath('src') 

6、引入 axios

在package.json底部增加以下代碼解決跨域問題

 
 
 
  1. // 新版本需要借助http-proxy-middleware,在src下創(chuàng)建setupProxy.js,內(nèi)容: 
  2. // 會自動引用,不需要額外的配置 
  3. const proxy = require('http-proxy-middleware') 
  4. module.exports = function (app) { 
  5.   app.use( 
  6.     proxy( 
  7.       '/api', { 
  8.         target: 'http://**********', 
  9.         changeOrigin: true 
  10.       } 
  11.     ) 
  12.   ) 
  13. // 定義多個入口: 
  14. module.exports = function (app) { 
  15.   app.use(proxy('/api', { target: 'http://localhost:7001' })); 
  16.   app.use(proxy('/api2', { target: 'http://localhost:7001' })); 

7、樣式處理

使用react-css-modules實現(xiàn)組件內(nèi)部樣式與外部分離,使用方式:

 
 
 
  1. import React from 'react' 
  2. import CSSModules from 'react-css-modules'; 
  3. import { Button } from 'antd' 
  4. import styles from './Header.module.scss' 
  5. class Header extends React.Component { 
  6.   render () { 
  7.     return ( 
  8.       
     
  9.         松寶寫代碼 
  10.       
 
  •     ) 
  •   } 
  • export default CSSModules(Header, styles) 
  •  注意:

    • 由于最新版create-react-app已經(jīng)實現(xiàn)配置,無需再修改webpack配置文件
    • 上述方法可實現(xiàn),同時使用antd樣式、全局樣式、組件私有樣式
    • 特別注意組件私有樣式文件的命名[name].module.scss

    8、針對create-react-app 2.1.1之前的版本,引入 stylus

    • 安裝 stylus 和 stylus-loader
    • 使用命令 yarn run eject 暴露配置文件
    • 在 webpack.config.dev.js 與webpack.config.prod.js 的 module/rules/oneOf 中修改一下代碼:
     
     
     
    1.     test: /\.(css|styl)$/, 
    2.         use: [ 
    3.             require.resolve('style-loader'), 
    4.             { 
    5.                 loader: require.resolve('css-loader'), 
    6.                 options: { 
    7.                   importLoaders: 1, 
    8.                 }, 
    9.             }, 
    10.             { 
    11.                 loader: require.resolve('postcss-loader'), 
    12.                 options: { 
    13.                     // Necessary for external CSS imports to work 
    14.                     // https://github.com/facebookincubator/create-react-app/issues/2677 
    15.                     ident: 'postcss', 
    16.                     sourceMap: true, 
    17.                     plugins: () => [ 
    18.                         require('postcss-flexbugs-fixes'), 
    19.                         autoprefixer({ 
    20.                             browsers: [ 
    21.                             '>1%', 
    22.                             'last 4 versions', 
    23.                             'Firefox ESR', 
    24.                             'not ie < 9', // React doesn't support IE8 anyway 
    25.                         ], 
    26.                         flexbox: 'no-2009', 
    27.                     }), 
    28.                 ], 
    29.             }, 
    30.         }, 
    31.         { 
    32.             loader: require.resolve('stylus-loader'), 
    33.             options: { 
    34.                 sourceMap: true, 
    35.             } 
    36.         }, 
    37.     ], 
    38. }, 

    五、開發(fā)過程中遇到的問題

    1、warning提示:no-op

    參考內(nèi)容[6]

    問題描述

    warning:Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method

    名次解釋 no-op

    Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component.

    也就是不能在卸載的組件中進行狀態(tài)更新操作,如異步請求、事件、定時器等,在componentWillUnmount生命周期中都應(yīng)該進行相應(yīng)的取消處理

    對于事件、定時器,只需要在componentWillUnmount方法中,進行取消事件監(jiān)聽或者清除定時器的操作即可

    以下方案均針對異步操作帶來的問題進行處理。

    方案一:使用一個變量[_isMounted]來控制是否更新狀態(tài)

     
     
     
    1. import React from 'react' 
    2. class newComponent extends React.Component { 
    3.   _isMounted = false 
    4.   componentDidMount() { 
    5.     this._isMounted = true 
    6.     axios 
    7.       .get('https://hn.algolia.com/api/v1/search?query=react') 
    8.       .then(result => 
    9.       if (!this._isMounted) return 
    10.         this.setState({ 
    11.           news: result.data.hits, 
    12.         }), 
    13.       ) 
    14.   } 
    15.   componentWillUnmount() { 
    16.     // 取消事件監(jiān)聽、清除定時器、控制異步請求 
    17.     this._isMounted = false 
    18.   } 
    19.   render() { 
    20.     return ( 
    21.       ... 
    22.     ) 
    23.   } 
    24. export default newComponent 

    方案二:比較粗暴的方式,直接更改setState函數(shù)

     
     
     
    1. import React from 'react' 
    2. class newComponent extends React.Component { 
    3.   componentWillUnmount() { 
    4.     // 取消事件監(jiān)聽、清除定時器、控制異步請求 
    5.     this.setState = () => { 
    6.       return 
    7.     } 
    8.   } 
    9.   render() { 
    10.     return ( 
    11.       ... 
    12.     ) 
    13.   } 
    14. export default newComponent 

    方案三,可直接取消接口請求,如axios的CancelToken

    2、react-router4.0版本中,不同場景下的路由跳轉(zhuǎn)

    參考[7]

    方案一,官方推薦,使用withRouter

     
     
     
    1. import React from 'react' 
    2. import { withRouter } from 'react-router-dom' 
    3. class NewComponent extends React.Component { 
    4.   AFunction() { 
    5.     this.props.history.push('/path') 
    6.   } 
    7.   render() { 
    8.     return ( 
    9.       ... 
    10.     ) 
    11.   } 
    12. export default withRouter(NewComponent) 

    方案二,不推薦,使用context

     
     
     
    1. import React from 'react' 
    2. import PropTypes from 'prop-types' 
    3. import { withRouter } from 'react-router-dom' 
    4. class NewComponent extends React.Component { 
    5.   static contextTypes = { 
    6.     router: PropTypes.object 
    7.   } 
    8.   constructor(props, context) { 
    9.      super(props, context); 
    10.   } 
    11.   AFunction() { 
    12.     this.context.router.history.push('/path') 
    13.   } 
    14.   render() { 
    15.     return ( 
    16.       ... 
    17.     ) 
    18.   } 
    19. export default NewComponent 

    方案三,使用history

    在真實的業(yè)務(wù)場景中,經(jīng)常需要在非react組件中使用路由跳轉(zhuǎn),如:接口統(tǒng)一處理場景下,用戶登錄失效時,跳轉(zhuǎn)至登錄頁面。

    由于react-router4.0中提供的BrowserRouter組件默認創(chuàng)建了history,并且未暴露出來,在非react中使用history會出現(xiàn)不起作用的情況

    因此:可不使用BrowserRouter組件,自行創(chuàng)建一個history,如下:

    ?創(chuàng)建history

     
     
     
    1. // src/history.js 一定要放在src的根目錄下 
    2. import createHistory from 'history/createBrowserHistory' 
    3. const history = createHistory() 
    4. export default history 

    ?配置router

     
     
     
    1. // src/index.js  注意router上的history 
    2. import { Router, Link, Route } from 'react-router-dom' 
    3. import history from './history' 
    4. ReactDOM.render( 
    5.    
    6.      
    7.       ... 
    8.      
    9.   , 
    10.   document.getElementById('root'), 

    ?其他地方使用,如接口統(tǒng)一處理層

     
     
     
    1. import history from '@/history'; 
    2. export function addProduct(props) { 
    3.   return dispatch => 
    4.     axios.post('xxx', props, config) 
    5.       .then(response => { 
    6.         history.push('/cart') 
    7.       }) 

    引用鏈接

    [1] react 英文文檔: https://reactjs.org/docs/getting-started.html

    [2] create-react-app: https://facebook.github.io/create-react-app/docs/getting-started

    [3] ant UI庫的配置參考: https://blog.csdn.net/qwe502763576/article/details/83242823

    [4] react-router 英文: https://reacttraining.com/react-router/web/example/basic

    [5] react-router 中文: http://router.happyfe.com/web/guides/quick-start

    [6] 參考內(nèi)容: https://www.robinwieruch.de/react-warning-cant-call-setstate-on-an-unmounted-component/

    [7] 參考: https://github.com/brickspert/blog/issues/3


    網(wǎng)頁題目:聊聊React開發(fā)的一些坑(一)
    網(wǎng)站路徑:http://www.5511xx.com/article/djojesc.html