React.js 小書 Lesson15 - 實(shí)戰(zhàn)分析:評論功能(二)


React.js 小書 Lesson15 - 實(shí)戰(zhàn)分析:評論功能(二)

本文作者:胡子大哈
本文原文:http://huziketang.com/books/react/lesson15

轉(zhuǎn)載請注明出處,保留原文鏈接以及作者信息

在線閱讀:http://huziketang.com/books/react


上一節(jié)我們構(gòu)建了基本的代碼框架,現(xiàn)在開始完善其他的內(nèi)容。

處理用戶輸入

我們從 ComponentInput 組件開始,學(xué)習(xí) React.js 是如何處理用戶輸入的。首先修改 ComponentInput.js,完善 ComponentInputrender 函數(shù)中的 HTML 結(jié)構(gòu):

import React, { Component } from 'react'

class CommentInput extends Component {
  render () {
    return (
      <div className='comment-input'>
        <div className='comment-field'>
          <span className='comment-field-name'>用戶名:</span>
          <div className='comment-field-input'>
            <input />
          </div>
        </div>
        <div className='comment-field'>
          <span className='comment-field-name'>評論內(nèi)容:</span>
          <div className='comment-field-input'>
            <textarea />
          </div>
        </div>
        <div className='comment-field-button'>
          <button>
            發(fā)布
          </button>
        </div>
      </div>
    )
  }
}

export default CommentInput

在瀏覽器中可以看到 ComponentInput 的結(jié)構(gòu)和樣式都已經(jīng)生效:

[圖片上傳失敗...(image-131ff0-1510226601202)]

因?yàn)檫€沒有加入處理邏輯,所以你輸入內(nèi)容,然后點(diǎn)擊發(fā)布是不會有什么效果的。用戶可輸入內(nèi)容一個是用戶名(username),一個是評論內(nèi)容(content),我們在組件的構(gòu)造函數(shù)中初始化一個 state 來保存這兩個狀態(tài):

...
class CommentInput extends Component {
  constructor () {
    super()
    this.state = {
      username: '',
      content: ''
    }
  }
  ...
}
...

然后給輸入框設(shè)置 value 屬性,讓它們的 value 值等于 this.state 里面相應(yīng)的值:

...
        <div className='comment-field'>
          <span className='comment-field-name'>用戶名:</span>
          <div className='comment-field-input'>
            <input value={this.state.username} />
          </div>
        </div>
        <div className='comment-field'>
          <span className='comment-field-name'>評論內(nèi)容:</span>
          <div className='comment-field-input'>
            <textarea value={this.state.content} />
          </div>
        </div>
...

可以看到接受用戶名輸入的 <input /> 和接受用戶評論內(nèi)容的 <textarea />value 值分別由 state.usernamestate.content 控制。這時候你到瀏覽器里面去輸入內(nèi)容看看,你會發(fā)現(xiàn)你什么都輸入不了。

這是為什么呢?React.js 認(rèn)為所有的狀態(tài)都應(yīng)該由 React.js 的 state 控制,只要類似于 <input />、<textarea />、<select /> 這樣的輸入控件被設(shè)置了 value 值,那么它們的值永遠(yuǎn)以被設(shè)置的值為準(zhǔn)。值不變,value 就不會變化。

例如,上面設(shè)置了 <input />valuethis.state.username,usernameconstructor 中被初始化為空字符串。即使用戶在輸入框里面嘗試輸入內(nèi)容了,還是沒有改變 this.state.username 是空字符串的事實(shí)。

所以應(yīng)該怎么做才能把用戶內(nèi)容輸入更新到輸入框當(dāng)中呢?在 React.js 當(dāng)中必須要用 setState 才能更新組件的內(nèi)容,所以我們需要做的就是:監(jiān)聽輸入框的 onChange 事件,然后獲取到用戶輸入的內(nèi)容,再通過 setState 的方式更新 state 中的 username,這樣 input 的內(nèi)容才會更新。

...
    <div className='comment-field-input'>
      <input
        value={this.state.username}
        onChange={this.handleUsernameChange.bind(this)} />
    </div>
...

上面的代碼給 input 加上了 onChange 事件監(jiān)聽,綁定到 this.handleUsernameChange 方法中,該方法實(shí)現(xiàn)如下:

...
  handleUsernameChange (event) {
    this.setState({
      username: event.target.value
    })
  }
...

在這個方法中,我們通過 event.target.value 獲取 <input /> 中用戶輸入的內(nèi)容,然后通過 setState 把它設(shè)置到 state.username 當(dāng)中,這時候組件的內(nèi)容就會更新,inputvalue 值就會得到更新并顯示到輸入框內(nèi)。這時候輸入已經(jīng)沒有問題了:

[圖片上傳失敗...(image-b1ad5-1510226601202)]

類似于 <input />、<select />、<textarea> 這些元素的 value 值被 React.js 所控制、渲染的組件,在 React.js 當(dāng)中被稱為受控組件(Controlled Component)。對于用戶可輸入的控件,一般都可以讓它們成為受控組件,這是 React.js 所推崇的做法。另外還有非受控組件,這里暫時不提及。

同樣地,讓 <textarea /> 成為受控組件:

...
  handleContentChange (event) {
    this.setState({
      content: event.target.value
    })
  }
...
      <div className='comment-field'>
        <span className='comment-field-name'>評論內(nèi)容:</span>
        <div className='comment-field-input'>
          <textarea
            value={this.state.content}
            onChange={this.handleContentChange.bind(this)} />
        </div>
      </div>
...

向父組件傳遞數(shù)據(jù)

當(dāng)用戶在 CommentInput 里面輸入完內(nèi)容以后,點(diǎn)擊發(fā)布,內(nèi)容其實(shí)是需要顯示到 CommentList 組件當(dāng)中的。但這兩個組件明顯是單獨(dú)的、分離的組件。我們再回顧一下之前是怎么劃分組件的:

[圖片上傳失敗...(image-cd9ac0-1510226601202)]

可以看到,CommentApp 組件將 CommentInputCommentList 組合起來,它是它們倆的父組件,可以充當(dāng)橋接兩個子組件的橋梁。所以當(dāng)用戶點(diǎn)擊發(fā)布按鈕的時候,我們就將 CommentInput 的 state 當(dāng)中最新的評論數(shù)據(jù)傳遞給父組件 CommentApp ,然后讓父組件把這個數(shù)據(jù)傳遞給 CommentList 進(jìn)行渲染。

CommentInput 如何向 CommentApp 傳遞的數(shù)據(jù)?父組件 CommentApp 只需要通過 props 給子組件 CommentInput 傳入一個回調(diào)函數(shù)。當(dāng)用戶點(diǎn)擊發(fā)布按鈕的時候,CommentInput 調(diào)用 props 中的回調(diào)函數(shù)并且將 state 傳入該函數(shù)即可。

先給發(fā)布按鈕添加事件:

...
      <div className='comment-field-button'>
        <button
          onClick={this.handleSubmit.bind(this)}>
          發(fā)布
        </button>
      </div>
...

用戶點(diǎn)擊按鈕的時候會調(diào)用 this.handleSumit 方法:

...
  handleSubmit () {
    if (this.props.onSubmit) {
      const { username, content } = this.state
      this.props.onSubmit({username, content})
    }
    this.setState({ content: '' })
  }
...

handleSumit 方法會判斷 props 中是否傳入了 onSubmit 屬性。有的話就調(diào)用該函數(shù),并且把用戶輸入的用戶名和評論數(shù)據(jù)傳入該函數(shù)。然后再通過 setState 清空用戶輸入的評論內(nèi)容(但為了用戶體驗(yàn),保留輸入的用戶名)。

修改 CommentApp.js ,讓它可以通過傳入回調(diào)來獲取到新增評論數(shù)據(jù):

class CommentApp extends Component {
  handleSubmitComment (comment) {
    console.log(comment)
  }

  render() {
    return (
      <div className='wrapper'>
        <CommentInput
          onSubmit={this.handleSubmitComment.bind(this)} />
        <CommentList />
      </div>
    )
  }
}

CommentApp 中給 CommentInput 傳入一個 onSubmit 屬性,這個屬性值是 CommentApp 自己的一個方法 handleSubmitComment。這樣 CommentInput 就可以調(diào)用 this.props.onSubmit(…) 把數(shù)據(jù)傳給 CommenApp。

現(xiàn)在在 CommentInput 中輸入完評論內(nèi)容以后點(diǎn)擊發(fā)布,就可以看到 CommentApp 在控制臺打印的數(shù)據(jù):

[圖片上傳失敗...(image-b81115-1510226601202)]

這樣就順利地把數(shù)據(jù)傳遞給了父組件,接下來我們開始處理評論列表相關(guān)的邏輯。

下一節(jié)中我們將介紹《React.js 小書 Lesson16 - 實(shí)戰(zhàn)分析:評論功能(三)》。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容