從零開始React:一檔 React環境搭建,語法規則,基礎使用

Mr.奇淼發表於2019-02-13

手挽手帶你學React入門第一期,帶你熟悉React的語法規則,消除對JSX的恐懼感,由於現在開發中都是使用ES6語法開發React,所以這次也使用ES6的模式進行教學,如果大家對ES6不熟悉的話,先去看看class相關內容吧,這裡我也慢慢帶大家一步一步學會React。

視訊教程

視訊大家移步我的個人部落格:www.henrongyi.top,掘金放不上來呢

什麼是React

React是Facebook的一群變態們開發的一個特別牛X的框架。它實際上是一個虛擬DOM,然後在這個DOM中,要用什麼元件就能飛速載入進來,不要的時候,馬上給刪咯(實際上就是個前端框架,都是這麼個意思,VUE,NG都是,只不過他們的資料流向不同而已,React區別就在於,單向資料流。),React 扮演著 MVC 結構中 V 的角色,後面我會用到基於FLUX架構的Redux讓我們的整個專案變成MVC架構。總之,React也是hie牛X的。

React的好處都有啥

React是一款非常牛X的前端框架,它的衍生物React-Native可以讓你開發接近原生體驗的NativeApp,它適合的範圍相當廣泛,前端,後端,手機端,都有很好的相容性。總而言之,hie牛X。

React基礎入門

現在的開發中React專案實際上都是使用ES6語法來編寫,並且,我們現在有很多成熟的腳手架可以使用(create-react-app,dva等),不過國際慣例,我們要從最基礎的用法開始編寫。我們採用ES6寫法來進行教學,同時使用webpack工具,這裡會用到很多相關配置,大家可以在這個過程中體驗ES6的精妙。

開始HelloWord

配置基礎webpack環境

這裡大家可以不去深入理解,先跟著我一步一步配置出來

開始之前,大家可以去官網:reactjs.org/ 下載最新的React(當前版本v16.7.0) 中文地址:react.docschina.org/

由於我們不使用腳手架,所以我們需要先建立我們自己的webpack包,第一步

mkdir helloReact
cd helloReact
複製程式碼

首先大家命令列輸入

webpack v
複製程式碼

如果正常出現版本號 並且是 3.6.0版本,那麼我們就可以按照教程繼續走下去了 如果沒有的話 那麼我們就需要命令列繼續

cnpm i webpack@3.6.0 -S -g

複製程式碼

到這裡應該可以正常使用webpack了

接下來 我們命令列輸入

npm init -y  // 這實際上是 初始化一個專案 並且全部預設 當然如果你想看看裡面有啥的話 就把-y拿掉就好了
npm i  //這裡是把webpack依賴安裝到本包內部
npm i webpack-dev-server@2.11.1 --save-dev //安裝本地執行伺服器
npm i webpack-cli --save-dev //依賴腳手架
複製程式碼

執行完成以後,我們會得到一個package.json檔案 開啟看看

{
  "dependencies": {
    "webpack": "^3.6.0"  //依賴包和版本
  },
  "name": "helloreact", //專案名
  "version": "1.0.0",  // 版本號
  "main": "index.js",  //入口檔案
  "scripts": {  //npm run 加這裡面的key就可以快速執行命令列
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",  // 作者
  "license": "ISC",
  "description": "" //簡介
}
複製程式碼

這裡面實際上是我們專案的一些基礎資訊

我們需要自己配置webpack和babel 這裡我們需要建立兩個檔案 這裡面我們要設定入口檔案,輸出檔案,babel,webpackServer等等,這裡不做太詳細的介紹 大家可以直接複製程式碼,後面可能會開專門的webpack視訊課程。 小小的介紹一下這些都是幹什麼用的 babel-core 呼叫Babel的API進行轉碼 babel-loader babel-preset-es2015 用於解析 ES6 babel-preset-react 用於解析 JSX babel-preset-stage-0 用於解析 ES7 提案 命令列輸入

npm install --save-dev babel-core babel-loader@7.1.5 babel-preset-es2015 babel-preset-react babel-preset-stage-0
複製程式碼

接下來我們在helloReact 資料夾中建立 webpack.config.js 檔案

// webpack.config.js 直接複製即可 
const path = require("path");
module.exports = {
   /*入口*/
   entry: path.join(__dirname, 'src/index.js'),
    
   /*輸出到dist資料夾,輸出檔名字為bundle.js*/
   output: {
       path: path.join(__dirname, './dist'),
       filename: 'bundle.js'
   },
    /*src資料夾下面的以.js結尾的檔案,要使用babel解析*/
    /*cacheDirectory是用來快取編譯結果,下次編譯加速*/
    module: {
        rules: [{
            test: /\.js$/,
            use: ['babel-loader?cacheDirectory=true'],
            include: path.join(__dirname, 'src')
        }]
    },
    plugins : [],
    devServer : {
        disableHostCheck: true,
        inline: true,
        port:9527,
        contentBase: path.join(__dirname, "/"),
    }
}

複製程式碼

接下來我們在helloReact 資料夾中建立 .babelrc 檔案

{
    "presets": [
      "es2015",
      "react",
      "stage-0"
    ],
    "plugins": []
  }
複製程式碼

然後我們在package.json檔案的script中新增

//package.json
{
  "dependencies": {
    "webpack": "^3.6.0"
  },
  "name": "helloreact",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "server": "webpack-dev-server",
    "build": "webpack",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^2.11.1"
  }
}


複製程式碼

這些配置完了,我們就在helloReact mkdir src 並且在src中建立 index.js檔案 在 根路徑 helloReact下建立 index.html 因為這裡我們要用到 react了 所以需要命令列安裝一下 react

cnpm install --save react react-dom
複製程式碼

html檔案如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
</body>
<script src="bundle.js"></script>
</html>

複製程式碼

js 檔案如下


import React from 'react';  //es6 引入react
import ReactDom from 'react-dom'; //es6 引入reactReacrDom

ReactDom.render(  //ReactDom渲染<div>hello React</div> 這個html標籤 到 id='app'這個標籤下
    <div>Hello React!</div>, document.getElementById('app'));

複製程式碼

一切都寫完了 我們執行服務 npm run server 來看一眼

如果你看到螢幕顯示出 Hello React! 那麼恭喜你 環境配置完了 我們們可以開始學習 React 了

如果你配置了半天還沒配置成功

到我的github下載程式碼吧。。。github.com/piexlmax/he…

React的Hello World

我們看到上面的程式碼


import React from 'react';  //es6 引入react
import ReactDom from 'react-dom'; //es6 引入reactReacrDom

ReactDom.render(  //ReactDom渲染<div>hello React</div> 這個html標籤 到 id='app'這個標籤下
    <div>Hello React!</div>, document.getElementById('app'));

複製程式碼

這是一個簡單的渲染 是不是根本看不到 React的元件化模式呢?

所以這裡 我們需要寫一個根部元件,以後的元件都放跟元件裡面,這個JS就理所當然成了一個入口檔案了

這裡 我們在 src下面建立一個app.js檔案

app.js

import React, {Component} from 'react';
// 這裡我們引入 react 和 react的Component 
// 建立 Hello 這個class(class屬於ES6內容) 然後繼承 Component 我們就成功地建立了一個 react元件

export default class App extends Component {
    render() {
        return (
            <div>
                Hello,World!
            </div>
        )
    }
}
複製程式碼

index.js 我們需要改寫為這樣

import React from 'react';
import ReactDom from 'react-dom';

import App from './app.js'  //引入我們的根元件App
ReactDom.render( //把App 渲染到 id=app的dom中
    <App/>, document.getElementById('app'));
複製程式碼

到這裡 我們已經實現了一個真正意義上的Hello World了!

傳說中的jsx

開始玩React了,那就必須要用到jsx語法,什麼是jsx呢?

JSX是一種JavaScript的語法擴充套件。JSX與模板語言相似,但它具有JavaScript的全部功能。JSX會被編譯為React.createElement()方法呼叫,將返回名為“React elements”的普通JavaScript物件。

上面程式碼裡我們看到 我們的html實際上是在js中的render函式中書寫的,是一個React擴充套件,允許我們編寫看起來像 HTML的JavaScript 。

切記 自定義元件一定要大寫字母開頭 return加括號 並且左括號要和return在同一行 只能return一個標籤,其餘內容都要在這個標籤內部

export default class App extends Component {
    render() {
        return (
            <div>
                Hello,World!
            </div>
        )
    }
}
複製程式碼

像是這樣一段程式碼,實際上我們真正使用的時候,已經經過了一次編譯,編譯過後它長這樣。

export default class App extends React.Component {
  render() {
    return (
      React.createElement(
        'div',
        'Hello,World!'
      )
    );
  }
}
複製程式碼

下面的這一段程式碼是不是就不容易理解了?這實際上是js可以幫我們去書寫dom的程式碼。 在React中JSX你可以理解為我們可以在js中寫HTML程式碼了 更通俗一點


export default class App extends Component {
    // 方法 生命週期 state 等
    render() {
        return (
        //    HTML模板
        )
    }
}

複製程式碼

React的基本使用方法

state

我們之前學過VUE,VUE中每個元件的資料存在自己的data中,那麼在React中,資料存在哪裡呢?沒錯狀態state中。 由於我們這裡用的是ES6的class 所以 我們子類constructor中必須先呼叫super才能引用this。 所以我們這裡應該這麼寫state

export default class App extends Component {
    constructor(){
        super()
        this.state={
            hello:"hello World"
        }
    }
    render() {
        return (
            <div>
                {this.state.hello}
            </div>
        )
    }
}
複製程式碼

這裡我們可以看出,我們想要在render中使用js 就需要用一個{} 這裡面的內容同樣可以書寫簡單的js表示式。

rander函式中使用state和JS表示式

export default class App extends Component {
    constructor(){
        super()
        this.state={
            hello:"hello World"
        }
    }
    render() {
        return (
            <div>
                <ul>
                    <li>展示state中的資料:{this.state.hello}</li>
                    <li>三元,短路等,這裡用三元示例{this.state.hello?"存在hello":"不存在hello"}</li>
                    <li>簡單計算{1+1}</li>
                    <li>JS表示式{Math.floor(Math.random()*10)}</li>
                </ul>
            </div>
        )
    }
}
複製程式碼

方法的宣告以及修改state

聲名方法我們有兩種模式,一種是直接書寫 方法名(引數){程式碼段}模式,這樣的模式在呼叫的時候需要手動bind(this) 還有一種就是使用es6的箭頭函式,讓其this指向自身

修改state資料需要呼叫 this.setState()方法 內部接收一個物件 要修改哪個key 就在物件內部填寫這個key,並且後面的值就是你要修改的內容,如果,key在state中不存在,則會在state中增加這個key

export default class App extends Component {
    constructor(){
        super()
        this.state={
            hello:"hello World"
        }
    }
    bye(){
        this.setState({
            hello:"bye world"
        })
    }
    byebye=()=>{
        this.setState({
            helloo:"bye world"
        })
    }
    render() {
        return (
            <div>
                <ul>
                    <li>非箭頭函式:{this.state.hello}</li>
                    <li>箭頭函式:{this.state.helloo}</li>
                </ul>
                <button onClick={this.bye.bind(this)}>無箭頭</button>  
                {/* 這裡使用bind來繫結this 如果傳參的話this.bye.bind(this,引數1,引數2) */} 
                <button onClick={()=>{this.byebye()}}>箭頭函式</button>
                 {/* 這裡是箭頭函式的預設屬性來搞定了this問題 如果傳參的話()=>{this.byebye(引數1,引數2)*/}}
            </div>
        )
    }
}
複製程式碼

這裡需要注意,只有觸發了state的變化,才會導致元件的重新渲染

迴圈語句,條件語句的使用

大家在vue中使用v-for 就能夠完成迴圈生成元件這樣的操作了,在react中我們應該怎麼做呢?

迴圈語句 我們說過 jsx 裡面是可以自由自在地使用js的 一般情況下我們使用map迴圈

在迴圈的時候,每一個return出來的標籤都需要新增 key={鍵值} “鍵值”是建立元素陣列時需要包含的特殊字串屬性。鍵值可以幫助React識別哪些元素被更改,新增或刪除。因此你應當給陣列中的每一個元素賦予一個確定的標識

export default class App extends Component {
    constructor(){
        super()
        this.state={
            arr:[{text:"qm"},{text:"奇淼"},{text:"大帥逼"}]
        }
    }
    
    render() {
        return (
            <div>
            {/* 我們說過 jsx 裡面是可以自由自在地使用js的 這裡我們來玩一個迴圈生成li */}
                <ul>
                   {this.state.arr.map((item,key)=>{
                       return(<li key={key}>{item.text}</li>)
                   })}
                </ul>
            </div>
        )
    }
}

複製程式碼

判斷語句 判斷語句我們一般使用短路表示式 三元表示式來展示我們想要展示的內容,但是如果需要複雜的條件判斷,那麼我們最好是寫一個自執行函式,然後再函式體內你就可以為所欲為了,記住一定要return你想要得到的dom標籤。

export default class App extends Component {
    constructor(){
        super()
        this.state={
            arr:[{text:"qm"},{text:"奇淼"},{text:"大帥逼"}]
        }
    }
    
    render() {
        return (
            <div>
            {/*簡單的三元和短路例項*/}
            {this.state.arr.length==3?<div>我是三元判斷的三個</div>:<div>我是三元判斷的不是三個</div>}
            {this.state.arr.length==3&&<div>我是短路判斷的三個</div>}
            {/* 我們說過 jsx 內部支援簡單的表示式 如果我們使用 if條件句的話 會導致報錯*/}
                {/*
                    if(this.state.arr.length==3){
                        return(<div>有三個</div>)
                    }
                */}
            {/* 我們說過 jsx 這已經是js程式碼段而不是簡單語句了,我們簡單判斷可以使用三元或者短路表示式來進行,但是複雜一點的,我們可以使用如下方法*/}
            {(()=>{
                if(this.state.arr.length==3){
                    return(<div>陣列有三個元素</div>)
                }else{
                    return(<div>陣列有不是三個元素</div>)
                }
            })()}
            </div>
        )
    }
}

複製程式碼

迴圈判斷巢狀 有些時候我們需要根據特定條件去迴圈,然後渲染出篩選過後的資料,這時候就需要迴圈和判斷巢狀使用了,其實也相當簡單,我們的迴圈實際上是一個簡單的js表示式,內部的function中可以隨意書寫js,記得return就好了

export default class App extends Component {
    constructor(){
        super()
        this.state={
            arr:[{text:"qm"},{text:"奇淼"},{text:"大帥逼"}]
        }
    }
    
    render() {
        return (
            <div>
                {this.state.arr.map((item,key)=>{
                    if(key%2==0){
                        return(<div key={key}>我是可以餘2的{item.text}</div>)
                    }else{
                        return(<div key={key}>我是不能餘2的{item.text}</div>)
                    }
                })}
            </div>
        )
    }
}

複製程式碼

獲取DOM(Refs)

有些時候我們不得不去操作DOM,那這時候 我們需要用到 ref 屬性

React支援一個可以附加到任何元件的特殊屬性ref。ref屬性可以是一個字串或一個回撥函式。當ref屬性是一個回撥函式時,函式接收底層DOM元素或類例項(取決於元素的型別)作為引數。這使你可以直接訪問DOM元素或元件例項。

另外這裡應該注意 不要過度使用 Refs。

export default class App extends Component {
    constructor(){
        super()
        this.state={
            arr:[{text:"qm"},{text:"奇淼"},{text:"大帥逼"}]
        }
    }
    
    render() {
        return (
            <div>
                {this.state.arr.map((item,key)=>{
                    if(key%2==0){
                        return(<div ref="link" key={key}>我是可以餘2的{item.text}</div>)
                        {/* 這樣我們可以通過 this.refs.link 獲取到這個dom 並且操作dom了 */}
                    }else{
                        return(<div key={key}>我是不能餘2的{item.text}</div>)
                    }
                })}
            </div>
        )
    }
}

複製程式碼

總結

到這裡我們已經學會了React的基本元件內部的操作了,React相對於Vue來說更加靈活,但是唯一的缺點是資料流是單向的,必須通過setState來修改,對於處理表單來說會有些麻煩,不過有些UI框架,外掛幫我們處理了這些大麻煩。寫寫玩玩吧React還是比較簡單的。

相關文章