天天看點

一篇文章快速入門React架構

視訊教程

本文章在B站配有

課程目标

  • 了解最常用的React概念和相關術語,例如JSX,元件,屬性(Props),狀态(state)。
  • 建構一個非常簡單的React應用程式,以闡述上述概念。

最終效果

建立React應用

helloworld

(1)安裝node.js     

官網連結

(2)打開cmd 視窗 輸入   

npm install --g create-react-app 
npm install --g yarn           

(-g 代表全局安裝)

如果安裝失敗或較慢。需要換源,可以使用淘寶NPM鏡像,設定方法為:

npm config set registry https://registry.npm.taobao.org

,設定完成後,

重新執行

cnpm install --g create-react-app
cnpm install --g yarn           
安裝 creat-react-app 功能元件,該元件可以用來初始化一個項目, 即 按照一定的目錄結構,生成一個新項目    

(3)在你想建立項目的目錄下  例如 D:/project/ 打開cmd指令 輸入   

create-react-app react-tutorial           

去使用creat-react-app指令建立名字是react-tutorial的項目

安裝完成後,移至新建立的目錄并啟動項目

cd react-tutorial
yarn start           

一旦運作此指令,localhost:3000新的React應用程式将彈出一個新視窗。

項目目錄結構

一個/public和/src目錄,以及node_modules,.gitignore,README.md,和package.json。

在目錄

/public

中,重要檔案是

index.html

,其中一行代碼最重要

<div id="root"></div>           

該div做為我們整個應用的挂載點

/src

目錄将包含我們所有的React代碼。

要檢視環境如何自動編譯和更新您的React代碼,請找到檔案

/src/App.js

将其中的

<a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>           

修改為

<a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          和豆約翰 Learn React
        </a>           

儲存檔案後,您會注意到

localhost:3000

編譯并重新整理了新資料。

現在删除

/src

目錄中的所有檔案,我們将從頭開始建立自己的項目檔案。

開始我們的mini項目

1.建立檔案index.css

我們就拷貝

index.css

檔案的全部内容(css不是我們這次課程的重點).

2.建立檔案index.js

在index.js中,我們将導入React,ReactDOM和CSS檔案。

src / index.js

import React, { Component }  from 'react'
import ReactDOM from 'react-dom'
import './index.css'           

建立App元件,在render方法中傳回一個div(這裡是JSX文法)

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hello, React!</h1>
      </div>
    )
  }
}           

最後,我們将App渲染到根節點。

ReactDOM.render(<App />, document.getElementById('root'))           

index.js完整代碼

import React, { Component }  from 'react'
import ReactDOM from 'react-dom'
import './index.css'


class App extends Component {
    render() {
        return (
            <div className="App">
                <h1>Hello, React!</h1>
            </div>
        )
    }
}

ReactDOM.render(<App />, document.getElementById('root'))
           

在浏覽器輸入localhost:3000,您将看到“你好,React!

JSX:JavaScript + XML

如您所見,我們在React代碼中一直使用看起來像HTML的東西,但它并不是完全HTML。這是JSX,代表JavaScript XML。

使用JSX,我們可以編寫看起來像HTML的内容,也可以建立和使用我們自己的類似XML的标簽。

以下是JSX配置設定給變量的樣子:

const heading = <h1 className="site-heading">Hello, React</h1>           

編寫React并非必須使用JSX。在幕後,它正在運作createElement,它接受标簽,包含屬性象群組件的後代,并呈現相同的資訊。下面的代碼将具有與上面的JSX相同的輸出。

const heading = React.createElement('h1', { className: 'site-heading' }, 'Hello, React!')           

JSX實際上更接近JavaScript,而不是HTML,是以在編寫時需要注意一些關鍵差別。

  • className用于代替class添加CSS類(classJavaScript中的保留關鍵字)。
  • JSX中的屬性和方法為camelCase(駝峰表示法) - onclick将變為onClick。
  • 自閉合标簽必須以斜杠結尾-例如
  • JavaScript表達式也可以使用大括号(包括變量,函數和屬性)嵌入JSX内。
const name = 'Tania'
const heading = <h1>Hello, {name}</h1>           

JSX比在原生JavaScript中建立和添加元素更容易編寫和了解,這也是人們如此熱愛React的原因之一。

元件

到目前為止,我們已經建立了一個元件- App元件。React中的幾乎所有内容都由元件組成,這些元件可以是類元件或簡單元件。

大多數React應用程式都有許多小元件,所有内容都加載到主App元件中。

元件經常定義在單個js檔案中,

接下來讓我們更改項目。從index.js中删除App類:

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './index.css'

ReactDOM.render(<App />, document.getElementById('root'))           

我們将建立一個新檔案App.js,并将元件放入其中。

import React, { Component } from 'react'

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hello, React!</h1>
      </div>
    )
  }
}

export default App           

我們将元件導出為App并将其加載到中index.js。将元件分成檔案不是強制性的,但是如果不這樣做的話,應用程式将開始變得笨拙和混亂。

類元件

讓我們建立另一個元件。我們将建立一個表格。制作Table.js,并用以下資料填充。

src / Table.js

import React, { Component } from 'react'

class Table extends Component {
  render() {
    return (
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Job</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Charlie</td>
            <td>Janitor</td>
          </tr>
          <tr>
            <td>Mac</td>
            <td>Bouncer</td>
          </tr>
          <tr>
            <td>Dee</td>
            <td>Aspiring actress</td>
          </tr>
          <tr>
            <td>Dennis</td>
            <td>Bartender</td>
          </tr>
        </tbody>
      </table>
    )
  }
}

export default Table           

我們建立的該元件是一個自定義類元件。自定義元件名稱首字母大寫,以差別于正常HTML元素。回到App.js,我們可以先将表格元件導入,以加載表格元件:

src / App.js

import Table from './Table'           

然後将其加載到App類的render()函數中,在此之前我們已經有了“ Hello,React!”。還更改了外部容器的類名。

import React, { Component } from 'react'
import Table from './Table'

class App extends Component {
  render() {
    return (
      <div className="container">
        <Table />
      </div>
    )
  }
}

export default App           

現在,我們已經了解了什麼是自定義類元件。我們複用此元件。但是,由于資料已被寫死到其中,是以目前它并不太有用。

簡單元件

React中的另一種類型的元件是simple component,它是一個函數。該元件不使用class關鍵字。讓我們為Table元件制作兩個簡單的子元件-一個表頭和一個表主體。

我們将使用ES6箭頭表達式來建立這些簡單的元件。首先,表頭:

const TableHeader = () => {
  return (
    <thead>
      <tr>
        <th>Name</th>
        <th>Job</th>
      </tr>
    </thead>
  )
}           

然後是表主體。

const TableBody = () => {
  return (
    <tbody>
      <tr>
        <td>Charlie</td>
        <td>Janitor</td>
      </tr>
      <tr>
        <td>Mac</td>
        <td>Bouncer</td>
      </tr>
      <tr>
        <td>Dee</td>
        <td>Aspiring actress</td>
      </tr>
      <tr>
        <td>Dennis</td>
        <td>Bartender</td>
      </tr>
    </tbody>
  )
}           

現在,我們的Table.js檔案将如下所示。請注意,TableHeader和TableBody元件都在同一個檔案中,并由Table類元件使用。

import React, { Component } from 'react'

const TableHeader = () => {
    return (
        <thead>
        <tr>
            <th>Name</th>
            <th>Job</th>
        </tr>
        </thead>
    )
}

const TableBody = () => {
    return (
        <tbody>
        <tr>
            <td>Charlie</td>
            <td>Janitor</td>
        </tr>
        <tr>
            <td>Mac</td>
            <td>Bouncer</td>
        </tr>
        <tr>
            <td>Dee</td>
            <td>Aspiring actress</td>
        </tr>
        <tr>
            <td>Dennis</td>
            <td>Bartender</td>
        </tr>
        </tbody>
    )
}


class Table extends Component {
    render() {
        return (
            <table>
                <TableHeader />
                <TableBody />
            </table>
        )
    }
}

export default Table
           

運作結果不變。如您所見,元件可以嵌套在其他元件中,并且簡單和類元件可以混合使用。

一個類元件必須包含render(),并且return隻能傳回一個父元素。

作為總結,讓我們比較一個簡單的元件和一個類元件:.

const SimpleComponent = () => {
  return <div>Example</div>
}           
class ClassComponent extends Component {
  render() {
    return <div>Example</div>
  }
}           

props

我們的Table元件,資料是寫死的。關于React的重要問題之一是它如何處理資料,它使用屬性(props)和狀态(state)來處理資料。現在,我們将專注于使用props處理資料。

首先,讓我們從TableBody元件中删除所有資料。

const TableBody = () => {
    return (
        <tbody></tbody>
    )
}           

然後,将所有資料定義到一個對象數組中:

class App extends Component {
  render() {
    const characters = [
      {
        name: 'Charlie',
        job: 'Janitor',
      },
      {
        name: 'Mac',
        job: 'Bouncer',
      },
      {
        name: 'Dee',
        job: 'Aspring actress',
      },
      {
        name: 'Dennis',
        job: 'Bartender',
      },
    ]

    return (
      <div className="container">
        <Table />
      </div>
    )
  }
}           

接下來,我們将通過屬性characterData将資料傳遞給子元件Table,傳遞的資料是characters變量,由于它是JavaScript表達式,是以使用大括号括起來。

return (
  <div className="container">
    <Table characterData={characters} />
  </div>
)           

現在資料已經傳遞到Table元件,我們可以在Table元件通過this.props中通路到。

class Table extends Component {
  render() {
    const { characterData } = this.props

    return (
      <table>
        <TableHeader />
        <TableBody characterData={characterData} />
      </table>
    )
  }
}           

由于Table元件實際上由兩個較小的簡單元件組成,是以再次通過props 将其傳遞給子元件TableBody

我們将把props作為參數傳遞給簡單元件TableBody ,并通過數組的map方法将資料映射為jsx片段的集合。該jsx片段集合将包含在

rows

變量中,我們将其作為表達式傳回。

const TableBody = props => {
  const rows = props.characterData.map((row, index) => {
    return (
      <tr key={index}>
        <td>{row.name}</td>
        <td>{row.job}</td>
      </tr>
    )
  })

  return <tbody>{rows}</tbody>
}           

您會注意到我已經向每個表行添加了一個鍵索引。在React中建立清單時,應始終使用

,因為它們有助于識别每個清單項。我們還将在需要操縱清單項的時刻看到這是必要的。

props是将現有資料傳遞到React元件的有效方法,但是該元件無法更改props-它們是隻讀的。在下一節中,我們将學習如何使用狀态(state)來進一步控制React中的資料處理。

state

我們将表格資料存儲在數組變量中,并将其作為props傳遞。但是如果我們希望能夠從數組中删除一個項目,就做不到了。props,是一種單向資料流,子元件不能進行修改。但是有了state,我們就可以更新元件中的私有資料。

您可以将state視為可以在元件内增删改的而不必添加到資料庫的任何臨時資料-例如,在确認購買之前在購物車中添加和删除的購物車項目。state改變後,綁定state資料的視圖會自動更新。

首先,我們将建立一個state對象。

class App extends Component {
  state = {}
}           

在state對象中定義屬性,儲存我們所需的資料。

class App extends Component {
  state = {
    characters: [],
  }
}           

将我們之前建立的對象的整個數組移到中state.characters。

class App extends Component {
  state = {
   characters : [
            {
                name: 'Charlie',
                job: 'Janitor',
            },
            {
                name: 'Mac',
                job: 'Bouncer',
            },
            {
                name: 'Dee',
                job: 'Aspring actress',
            },
            {
                name: 'Dennis',
                job: 'Bartender',
            },
        ]
  }
}           

在App.js中,建立removeCharacter方法來删除一個項目

removeCharacter = index => {
  const { characters } = this.state

  this.setState({
    characters: characters.filter((character, i) => {
      return i !== index
    }),
  })
}           
您必須使用this.setState()來修改數組。簡單地将新值應用到this.state.property将不起作用。

現在,我們必須将該函數傳遞給元件。我們會将removeCharacter函數作為屬性傳遞給Table。

src/App.js

render() {
  const { characters } = this.state

  return (
    <div className="container">
      <Table characterData={characters} removeCharacter={this.removeCharacter} />
    </div>
  )
}           

由于Table元件,并不需要自己的state資料對象,是以,我們将它改造成簡單元件,并将removeCharacter函數繼續向TableBody 子元件傳遞:

src/Table.js

const Table = props => {
  const { characterData, removeCharacter } = props

  return (
    <table>
      <TableHeader />
      <TableBody characterData={characterData} removeCharacter={removeCharacter} />
    </table>
  )
}           

在TableBody元件中,我們将鍵/索引作為參數傳遞,因為removeCharacter函數知道要删除的項目索引。我們建立一個按鈕并将其onClick事件綁定removeCharacter函數;

<tr key={index}>
  <td>{row.name}</td>
  <td>{row.job}</td>
  <td>
    <button onClick={() => props.removeCharacter(index)}>Delete</button>
  </td>
</tr>           
onClick事件必須綁定為傳回該removeCharacter()方法的函數,否則removeCharacter()将嘗試不等按鈕點選而自動運作。

新增表格資料

現在我們已經将資料存儲在App.js元件的state對象中,并且可以從state對象中删除任何項目。但是,如何向state對象中添加資料呢?我們将通過一個表單元件來實作這個需求。

首先,state.characters中删除所有寫死資料:

class App extends Component {
  state = {
    characters: [],
  }
}           

建立新檔案Form.js。

import React, { Component } from 'react'

class Form extends Component {
  initialState = {
    name: '',
    job: '',
  }

  state = this.initialState
}           
以前,React類元件有必要包括一個constructor(),但是現在不再需要。

此表單的目标是Form每次更改表單中的字段時都會更新本元件(Form)的state,并且在我們送出表單時,所有資料都将傳遞給App元件的state,然後Table元件會自動更新。

首先定義input控件的onChange事件處理函數:

src / Form.js

handleChange = event => {
  const { name, value } = event.target

  this.setState({
    [name]: value,
  })
}           

Form元件的render函數實作如下:

render() {
  const { name, job } = this.state;

  return (
    <form>
      <label htmlFor="name">Name</label>
      <input
        type="text"
        name="name"
        id="name"
        value={name}
        onChange={this.handleChange} />
      <label htmlFor="job">Job</label>
      <input
        type="text"
        name="job"
        id="job"
        value={job}
        onChange={this.handleChange} />
    </form>
  );
}

export default Form;           

在App.js,導入Form:

import Form from './Form';

return (
  <div className="container">
    <Table characterData={characters} removeCharacter={this.removeCharacter} />
    <Form />
  </div>
)           

最後一步是實作送出該資料并更新父元件狀态。我們将建立一個名為

handleSubmit()

的函數,該函數将使用[ES6擴充運算符]文法來更新狀态。

handleSubmit = character => {
  this.setState({ characters: [...this.state.characters, character] })
}           

確定我們将其作為參數傳遞給

Form

<Form handleSubmit={this.handleSubmit} />           

現在,在

Form

中,我們将建立一個名為

submitForm()

的方法,該方法将調用傳進來的handleSubmit函數,并将

Form

的state作為

character

參數傳遞。它還将

Form

的state重置為初始狀态,以在表單送出後清除表單資訊。

submitForm = () => {
  this.props.handleSubmit(this.state)
  this.setState(this.initialState)
}           

最後,我們将在Form.js中添加一個送出按鈕以送出表單,點選将調用我們剛定義的

submitForm

函數。

<input type="button" value="Submit" onClick={this.submitForm} />           

就是這樣!該應用程式已完成。

完整代碼