react雜記

React

webpack+react (hello world)

項目結構:
    src:
        app.js
        main.js
    package.json
    webpack_dev_config.js

須要安裝包:
    yarn add react react-dom --save

app.jscss

import React, {component} from 'react';
class App extends Component {
    render(){
        return (
            <div>
                hello world
            </div>
        )
    }
}
export default App

注意:html

return 最外一層的div不能破壞,內容所有寫在div裏面

瀏覽器不識別jsx,因此用babel來轉換
見webpack_dev_config.js中的配置
網頁地址:
    https://babeljs.cn/docs/setup/#installation

main.js(導入根組件,並渲染根組件)node

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
ReactDOM.render(
    <App />, document.getElementById('root'));

注意:react

若是App.js的導出是
    export App
則引入時應該是
    import {App} from 'xxxxx'

webpack_dev_config.jswebpack

配置babel:git

https://babeljs.cn/
https://babeljs.cn/docs/setup/#installation //詳情看這個

1.  安裝包
    yarn add babel-loader babel-core --dev 
    //轉es6      
    yarn add babel-preset-env --dev
    //轉換jsx,並添加 "react" 到你的 .babelrc 的 presets 數組中。
    yarn add babel-preset-react --dev

開發階段:es6

網址:

    https://github.com/jantimon/html-webpack-plugin

結合webpack-dev-server 配合 html-webpack-plugin

1.  安裝包
    yarn add webpack html-webpack-plugin webpack-dev-server --dev

代碼:github

var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './src/main.js',
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: "babel-loader"
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './template.html', 
            filename: 'index.html'
        })
    ]
}

package.jsonweb

配置scripts
    
    "scripts": {
        "dev": "webpack-dev-server --progress --open --config webpack_dev_config.js --prot 6008"
    }

.babelrcnpm

{
    "presets": [
        "env",
        "react"
    ]
}

腳手架

參考地址:
    https://doc.react-china.org/docs/installation.html

npm install -g create-react-app
create-react-app my-app

熱更新(非腳手架項目)

參考地址:
    https://github.com/gaearon/react-hot-loader
1.  
    yarn add react-hot-loader --dev
    yarn add babel-polyfill --dev

2.  
    // .babelrc
    {
      "presets": [
            ["env",
            {
                "modules": false
            }],
            "react"
        ],
      "plugins": ["react-hot-loader/babel"]
    }
    
3.  
    https://webpack.js.org/guides/hot-module-replacement/#enabling-hmr

4.  
    // webpack.config.js
    module.exports = {
      entry: ['babel-polyfill', 'react-hot-loader/patch', './main.js'],
    }
    Note: Make sure to set the output.publicPath property to "/" as well. Otherwise hot reloading won't work as expected for nested routes.

5.
    // main.js
    import React from 'react'
    import ReactDOM from 'react-dom'
    import { AppContainer } from 'react-hot-loader'
    import App from './containers/App'
    
    const render = Component => {
      ReactDOM.render(
        <AppContainer>
          <Component />
        </AppContainer>,
        document.getElementById('root'),
      )
    }
    
    render(App)
    
    // Webpack Hot Module Replacement API
    if (module.hot) {
      module.hot.accept('./containers/App', () => {
        render(App)
      })
    }

    Note: To make this work, you'll need to opt out of Babel transpiling ES2015 modules by changing the Babel ES2015 preset to be ["es2015", { "modules": false }]

6.  
    "scripts": {
        "dev": "webpack-dev-server --progress --open --config webpack_config_dev.js --port 6008 --hotOnly"
    }

熱更新(腳手架生成的項目)

只須要在根目錄下運行npm run eject,目錄結構會改變

https://github.com/gaearon/react-hot-loader

Migrating from create-react-app裏面跟着作三步

React對css、less、sass處理

1.  直接在標籤裏經過style寫
    1.  <div style={{color:'red'}}>
            hello world123
        </div>
        <span style={{ fontSize : 16 + "px"}}>Hello, yoona</span>;
    2.  放在單獨的對象中
        const style = {
            color: 'green'
        }
        <div style={style}>
            hello world 
        </div>      

2.  經過外部樣式來寫
    import  'xxxx.css/xxx.less/xxx.sass'
    //須要安裝loader
    // style-loader css-loader less-loader sass-loader node-sass(這個用cnpm裝)
    //yarn add style-loader css-loader --dev

    <div className="xxxx">
            hello world123
    </div>


注意:
    在jsx中,屬性名稱後面的值,兩種狀況,一種字符串,一種{}

組件-----有狀態組件,無狀態組件

組件的數據來源於兩部分
    1.  父組件
    2.  本身內部數據

無狀態組件:
    本身內部沒有數據,數據來源於父組件

有狀態組件:
    便可有父組件數據,也能夠有本身內部數據

無狀態組件

語法:

    import React from 'react'
    function Hello (){
        return (
            <div>123</div>
        )
    }
    export default Hello
    
傳值:

    傳值方:
        經過屬性名稱=值的方式傳遞
        <Hello name="abc" age={10}></Hello>

    接收方:
        function Hello (props){
            return (
                <div>123,{props.name}</div>
            )
        }

注意:
    父組件傳過來的值只能展現,不能直接修改

有狀態組件

語法:

    class Welcome extends React.Component {
      render() {
        return <h1>Hello, {this.props.name}</h1>;
      }
    }

傳值:

    傳值方:
        經過屬性名稱=值的方式傳遞
        <Hello name="abc" age={10}></Hello>

    接收方:
        經過{this.props.name}

私有的值:
    constructor(){
        super()
        this.state = {
            name: 'tom'
        }
    }
    使用: {this.state.name}   

默認值(es7):
    包:babel-preset-stage-0
    .babelrc中添加"stage-0"

    static defaultProps = {
        initCount: 300
    }

調用函數

<button onClick={()=>{this.clickme()}}>點我</button>

clickme(){
    console.log(1)
}

<button onClick={this.clickme()}>點我</button>
這種綁定是拿不到this的

改變內部數據

this.setStatus({
    name: "yoona"
})

prop-types檢查類型 15.0+以後

import PropTypes from 'prop-types'

static propTypes = {
    initCount: PropTypes.number/string
}

生命週期

componentWillMount(){}
render(){}
componentDidMount(){}
componentWillReceiveProps(){}
shouldComponentUpdate(){
    return true
}
componentWillUpdate(){}
componentDidUpdate(){}

集成 Ant-Design

參考地址:
    https://ant.design/docs/react/introduce-cn

1.  安裝
    yarn add antd

2.  import { DatePicker } from 'antd'; 

3.  import 'antd/dist/antd.css';  // or 'antd/dist/antd.less'

按需導入:
    1.  // .babelrc or babel-loader option
        {
          "plugins": [
            ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }] // `style: true` 會加載 less 文件
          ]
        }
        而後只需從 antd 引入模塊便可,無需單獨引入樣式

        參考地址:https://github.com/ant-design/babel-plugin-import

    2.  手動按需導入
        import DatePicker from 'antd/lib/date-picker';
        // 加載 JS
        import 'antd/lib/date-picker/style/css';      
        // 加載 CSS

react-router-dom

參考地址:
    https://reacttraining.com/react-router/web/example/basic

yarn add react-router-dom --save

fetch-jsonp

yarn add fetch-jsonp --save

import fetchJsonp from 'fetch-jsonp'

getFilmList(){
     const url =  `https://api.douban.com/v2/movie/${this.state.filmType}`
     fetchJsonp(url).then(response=>response.json()).then(data=>{
         this.setState({
             isLoading: false,
             filmList: data.subjects
         })
     }).catch(e=> console.log('error',e))
}

改變數據時:

componentWillReceiveProps(props){
    this.setState({
        filmType: props.match.params.filmTypes,
        isLoading: true
    },()=>{
        this.getFilmList()
    })
}

render裏面須要遍歷時用{}

render() {
    if(this.state.isLoading){
        return <Spin tip="加載中...">
            <Alert
            message="正在加載中"
            description="哥正在拼命加載中,請稍後"
            type="info"
            />
        </Spin>
    }else{
        return (
            <div style={{display:'flex',flexWrap:'wrap',textAlign:'center'}}>
            {
                this.state.filmList.map((item,i)=>{
                    return <div key={i} onClick={()=>{this.goMovieDetail(item.id)}} className="movieItem" style={everyMovieItemStyle}>
                        <img style={{height:378}} src={item.images.small} alt=""/>
                        <p><strong>{item.title}</strong></p>
                        <p><strong>電影類型:{item.genres.join(',')}</strong></p>
                        <p><strong>上映年份:{item.year}</strong></p>
                        <div>評分:<Rate disabled defaultValue={item.rating.average / 2} /></div>
                    </div>
                })
            }
        </div>
        )
    }
}

改變導航

//經過編程式導航跳轉到電影詳情組件中去
goMovieDetail(movieId){
    this.props.history.push(`/movie/detail/${movieId}`)
}

//返回到上一級
goBack() {
    this.props.history.goBack()
}

webpack打包

參考地址(性能優化):
    https://doc.react-china.org/docs/optimizing-performance.html

webpack指南里面:    
    https://doc.webpack-china.org/guides/production/
    
1.  新建一個配置文件webpack_config_prod.js
2.  熱重載要幹掉
3.  壓縮js
    new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV: JSON.stringify('production')
        }
    }),
    new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            comments: false     
    })
4.  壓縮html
    參考網址:
        https://github.com/jantimon/html-webpack-plugin
        https://github.com/kangax/html-minifier#options-quick-reference

    new HtmlWebpackPlugin({
        template: './template.html', 
        filename: 'index.html',
        minify: {
            collapseWhitespace: true,
            removeComments: true,
            minifyCSS: true,
            minifyJS: true
        }
    })

5.  output

        const path = require('path');
        output: {
            path:path.resolve(__dirname, "dist"),
            filename: "bundle.js"
        }
    
6.  清除原先的dist
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    new CleanWebpackPlugin(['dist'])

7.  配置package.json
    "build": "webpack --progress --config webpack_config_prod.js"

優化打包:
    
    抽離第三方包

    1.  抽離圖片
        {
            test: /\.(png|jpg|gif)$/,
            use: [
                {
                    loader: 'url-loader',
                    options: {
                        limit: 4000,//大於4kb就抽離出去
                        name:"images/[name]-[hash:5].[ext]"
                    }
                }
            ]
        }

    2.  明確第三方庫
        https://doc.webpack-china.org/plugins/commons-chunk-plugin/

        entry: {
            quanjiatong:['react','react-dom','react-router-dom'],
            fetchJsonp:['fetch-jsonp'],
            bundle:'./src/main.js' 
        }
        output: {
            path:path.resolve(__dirname, "dist"),
            filename: "js/[name].js"
        }
        new webpack.optimize.CommonsChunkPlugin({
                name: ['quanjiatong','fetchJsonp'],
                minChunks: Infinity,
        })

    3.  抽離對三方樣式
        https://github.com/webpack-contrib/extract-text-webpack-plugin

        yarn add extract-text-webpack-plugin --dev

        //抽離第三方樣式的包
        const ExtractTextPlugin = require("extract-text-webpack-plugin");
                    
        {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
              fallback: "style-loader",
              use: [
                    {
                        loader: 'css-loader',
                        options: {
                            minimize: true //壓縮css
                        }
                    }
                ]
            })
          }
        
        new ExtractTextPlugin("styles.css"),

服務器反向代理

之後補充
相關文章
相關標籤/搜索