React -- 簡易項目實戰

參考文獻css

1、建立項目

npx create-react-app myTest

建立完成後,項目下面主要有publicsrc文件,前者是用來存放靜態資源文件的,其中最主要的就是index.html文件,後者則是用來存放全部的react代碼的
項目搭建好後,切換進項目,執行npm start命令,便可在本地localhost:3000窗口打開項目html

2、修改app.js

運行完成後,咱們能夠頁面看見效果
打開src文件夾,裏面有個index.js和app.js文件,其中index.js是主入口文件,app.js就是頁面展現建議react組件,如今修改一下app.js裏面的東西,寫入Hello React !,而後保存看看頁面
書寫代碼有jsx和非jsx語法兩種格式:
jsxvue

const h1 = <h1 class="app-title">Hello React !</h1>

no-jsxreact

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

3、建立Table.js

如今新建一個table.js文件,來設計一個表格組件,並將這個組件添加到app.js組件中
新建組件注意事項
一、Component做爲一個組件引入了,不須要再執行React.Component
二、使用class繼承,元素必須在render()方法裏面返回
三、樣式類名書寫是className,不是class
四、必定要將組件導出export default componentName
五、react組件名必須大寫字母開頭
六、只能return一個根元素,不能return兩個根元素,也就是說renturn的標籤必須包裹在一個根標籤裏面,不能是兩個同級標籤es6

import React, { Component } from 'react'

class Table extends Component {
  render() {
    return (
      <table>
        <thead>
          <tr>
            <td>Name</td>
            <td>Job</td>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>李狗蛋</td>
            <td>程序猿</td>
          </tr>
          <tr>
            <td>王翠花</td>
            <td>攻城獅</td>
          </tr>
        </tbody>
      </table>
    )
  }
}
export default Table

組件寫好後,在app.js裏面引入組件並使用npm

import Table from './table.js'

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <h4>Hello React !</h4>
        <Table />
      </header>
    </div>
  );
}

而後保存查看頁面

看起來樣子有些醜,而後建立一個table.css文件,書寫一些樣式,讓table美觀一下,而後在table.js頁面引入css文件數組

import './table.css'

而後保存查看頁面
app

4、簡單組件

其實經過class建立的組件能夠稱之爲複雜組件,還能夠建立簡單組件,所謂的簡單組件,其實用相似函數的方式聲明組件,如今用簡單組件把table的頭部和軀體部分分別分離出來做爲一個單獨的小組件
簡單組件跟複雜組件的區別之一就是簡單組件不須要render()方法去置換一下return元素,直接返回react元素函數

// table.js
function TableHead(props) {
  return (
    <thead>
      <tr>
        <th>Name</th>
        <th>Job</th>
      </tr>
    </thead>
  )
}

function TableBody(props) {
  return (
    <tbody>
      <tr>
        <td>李狗蛋</td>
        <td>程序猿</td>
      </tr>
      <tr>
        <td>王翠花</td>
        <td>攻城獅</td>
      </tr>
    </tbody>
  )
}

調用this

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

保存查看頁面,發現頁面並無什麼變化,是同樣的

因此全部組件都是能夠相互嵌套的,並且簡單組件和複雜組件也是能夠相互嵌套的,並無的區別

5、組件通訊props

react中組件通訊跟vue有點相似,是經過props來接收數據傳遞,不一樣的是:
一、數據是全局保存在props對象裏面的,直接調用props對象就能夠獲取
二、數據傳遞也不須要經過v-bind來綁定參數,直接寫便可,只不過傳入參數使用{}包裹,而不是""
三、在簡單函數裏,props是做爲一個參數傳入的,因此直接經過props.key獲取,可是在class裏面,props是繼承於Compoent,須要經過super()方法,調用是經過this.props.key
由於全部組件都是在app.js裏面渲染的,因此如今要在app.js裏面建立數據傳遞過去,須要注意一點就是傳遞的數據必須建立在渲染組件元素的render()函數裏面,建立在render()方法以外,是沒有效果的,若是是簡單組件,就直接聲明一個數據數組
數據聲明好以後,直接在組件上傳遞

function App() {
  const Head = [
    { header: 'Name' },
    {header: 'Job'}
  ]
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <h4>Hello React !</h4>
        // 傳遞數據
        <Table Head={Head} />
      </header>
    </div>
  );
}

接下來就能夠在Table組件的render函數經過es6方法從props裏面拿到數據賦值給新聲明的變量,注意必須在render()方法裏面聲明獲取,簡單函數直接聲明獲取獲取

class Table extends Component {
  render() {
    // 拿取元素
    const {Head} = this.props
    return (
      <table>
        <TableHead Head={Head} />
        <TableBody />
      </table>
    )
  }
}

接下里就是列表渲染表格頭部了,注意react裏面列表渲染時經過map()方法實現的,由於map()方法返回的是一個結果數組
須要注意的是每個循環建立的react元素必須賦予一個key值,這是惟一標識符,同一個react元素裏不能相同

const TableHead = (props) => {
  const myHead = props.Head.map((item, index) => {
    return <th key={index}>{item.header}</th>
  })
  return (
    <thead>
      <tr>
        {myHead}
      </tr>
    </thead>
  )
}

而後保存查看頁面,發現頁面結構數據並無變化,也沒有報錯

同理咱們能夠把body數據也能夠賦予過去

const Body = [
    {
      name: '李狗蛋',
      job: '程序猿',
    },
    {
      name: '王翠花',
      job: '攻城獅',
    },
    {
      name: '二狗子',
      job: '加班狗',
    }
  ]
<Table Head={Head} Body={Body} />

弄好以後,保存查看頁面結果

6、數據修改state

經過props能夠傳遞數據,可是這個數據傳過去後是不可變的,沒法進行操做,因此須要經過state來聲明數據,這樣數據就能夠經過this.setState()方法來進行相關操做
如今咱們建立一個state對象,把先前的數據所有移到這個對象裏面

const state = {
    Head: [
      { header: 'Name' },
      {header: 'Job'}
    ],
    Body: [
      {
        name: '李狗蛋',
        job: '程序猿',
      },
      {
        name: '王翠花',
        job: '攻城獅',
      },
      {
        name: '二狗子',
        job: '加班狗',
      }
    ]
  }

在Table組件依然是經過this.props獲取這個數據
如今咱們須要操做這個數組,來進行數組的內容的添加和刪除,首先咱們執行刪除操做,在app.js聲明一個刪除數據的方法,用來執行刪除,這個方法是根據index來刪除
刪除函數

removeTr = index => {
    const { Body } = this.state
    this.setState({
      Body: Body.filter((item, ind) => {
        return ind !== index
      })
    })
  }

弄好以後,把數據經過props傳遞過去,而後回到Table組件,在body裏面新增一行,執行方法

function TableBody(props) {
  const myBody = props.Body.map((item, index) => {
    return <tr key={index}>
      <td>{item.name}</td>
      <td>{item.job}</td>
      <td>
        <button onClick={() => props.removeTr(index)}>Delete</button>
      </td>
  </tr>
  })
  return (
    <tbody>
      {myBody}
    </tbody>
  )
}

注意
這裏踩了一個坑,經過事件執行方法時,必定要經過一個函數去執行props裏傳過來的方法,不然好像會自動執行
這樣咱們點擊刪除按鈕,就會將當前的數組索引做爲參數傳過去,而後經過filter()方法過濾掉index相同的數組項,返回其餘數組項,實現刪除效果

7、新增數據

在作邏輯操做以前,咱們須要新建一個新增數據的表單組件
Form.js

import React, { Component } from 'react'

class Form extends Component {
  constructor(props) {
    super(props)
    // 初始化input的value值
    this.initValue = {
      name: '',
      job: '',
    }
    // 將初始化值賦值給state
    this.state = this.initValue
  }
  // input標籤內容改變時執行
  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value,
    })
  }
  // 點擊提交按鈕時執行的操做
  submitForm = () => {
    // 這個方法是app.js那邊傳過來的,這個須要把用戶輸入的數據傳過去
    this.props.handleSubmit(this.state)
    // 重置input的value值
    this.setState(this.initValue)
  }
  render() {
    const {name, job} = this.state
    return (
      <form>
        <label>
          Name:
        </label>
        <input type="text" value={name} name="name" onChange={this.handleChange} /><br />
        <label>
          Job:
        </label>
        <input type="text" value={job} name="job" onChange={this.handleChange} /><br />
        <input type="button" value="新增" onClick={this.submitForm} />
      </form>
    )
  }
  }

app.js

handleSubmit = (valObj) => {
    // 經過解構的方式,把傳過來的數據添加到Body數組裏,
    this.setState({
      Body: [...this.state.Body, valObj]
    })
  }
相關文章
相關標籤/搜索