React.js 小书 Lesson15 - 实战分析:评论功能(二)
- 作者:胡子大哈
- 原文鏈接:?http://huziketang.com/books/react/lesson15
- 轉載請注明出處,保留原文鏈接和作者信息。
上一節(jié)我們構建了基本的代碼框架,現(xiàn)在開始完善其他的內(nèi)容。
處理用戶輸入
我們從?ComponentInput?組件開始,學習 React.js 是如何處理用戶輸入的。首先修改?ComponentInput.js,完善?ComponentInput?的?render?函數(shù)中的 HTML 結構:
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?的結構和樣式都已經(jīng)生效:
因為還沒有加入處理邏輯,所以你輸入內(nèi)容,然后點擊發(fā)布是不會有什么效果的。用戶可輸入內(nèi)容一個是用戶名(username),一個是評論內(nèi)容(content),我們在組件的構造函數(shù)中初始化一個?state?來保存這兩個狀態(tài):
... class CommentInput extends Component {constructor () {super()this.state = {username: '', content: '' } } ... } ...然后給輸入框設置?value?屬性,讓它們的?value?值等于?this.state?里面相應的值:
...<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.username?和?state.content?控制。這時候你到瀏覽器里面去輸入內(nèi)容看看,你會發(fā)現(xiàn)你什么都輸入不了。
這是為什么呢?React.js 認為所有的狀態(tài)都應該由 React.js 的 state 控制,只要類似于?<input />、<textarea />、<select />?這樣的輸入控件被設置了?value?值,那么它們的值永遠以被設置的值為準。值不變,value?就不會變化。
例如,上面設置了?<input />?的?value?為?this.state.username,username?在?constructor?中被初始化為空字符串。即使用戶在輸入框里面嘗試輸入內(nèi)容了,還是沒有改變?this.state.username?是空字符串的事實。
所以應該怎么做才能把用戶內(nèi)容輸入更新到輸入框當中呢?在 React.js 當中必須要用?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?方法中,該方法實現(xiàn)如下:
...handleUsernameChange (event) {this.setState({username: event.target.value})} ...在這個方法中,我們通過?event.target.value?獲取?<input />?中用戶輸入的內(nèi)容,然后通過?setState?把它設置到?state.username?當中,這時候組件的內(nèi)容就會更新,input?的?value?值就會得到更新并顯示到輸入框內(nèi)。這時候輸入已經(jīng)沒有問題了:
類似于?<input />、<select />、<textarea>?這些元素的?value?值被 React.js 所控制、渲染的組件,在 React.js 當中被稱為受控組件(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ù)
當用戶在?CommentInput?里面輸入完內(nèi)容以后,點擊發(fā)布,內(nèi)容其實是需要顯示到?CommentList?組件當中的。但這兩個組件明顯是單獨的、分離的組件。我們再回顧一下之前是怎么劃分組件的:
可以看到,CommentApp?組件將?CommentInput?和?CommentList?組合起來,它是它們倆的父組件,可以充當橋接兩個子組件的橋梁。所以當用戶點擊發(fā)布按鈕的時候,我們就將?CommentInput?的 state 當中最新的評論數(shù)據(jù)傳遞給父組件?CommentApp?,然后讓父組件把這個數(shù)據(jù)傳遞給?CommentList?進行渲染。
CommentInput?如何向?CommentApp?傳遞的數(shù)據(jù)?父組件?CommentApp?只需要通過?props?給子組件?CommentInput?傳入一個回調(diào)函數(shù)。當用戶點擊發(fā)布按鈕的時候,CommentInput?調(diào)用?props?中的回調(diào)函數(shù)并且將?state?傳入該函數(shù)即可。
先給發(fā)布按鈕添加事件:
...<div className='comment-field-button'><buttononClick={this.handleSubmit.bind(this)}> 發(fā)布 </button> </div> ...用戶點擊按鈕的時候會調(diào)用?this.handleSubmit?方法:
...handleSubmit () {if (this.props.onSubmit) {const { username, content } = this.statethis.props.onSubmit({username, content}) } this.setState({ content: '' }) } ...handleSubmit?方法會判斷?props?中是否傳入了?onSubmit?屬性。有的話就調(diào)用該函數(shù),并且把用戶輸入的用戶名和評論數(shù)據(jù)傳入該函數(shù)。然后再通過?setState?清空用戶輸入的評論內(nèi)容(但為了用戶體驗,保留輸入的用戶名)。
修改?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)容以后點擊發(fā)布,就可以看到?CommentApp在控制臺打印的數(shù)據(jù):
這樣就順利地把數(shù)據(jù)傳遞給了父組件,接下來我們開始處理評論列表相關的邏輯。
因為第三方評論工具有問題,對本章節(jié)有任何疑問的朋友可以移步到?React.js 小書的論壇?發(fā)帖,我會回答大家的疑問。
轉載于:https://www.cnblogs.com/huzidaha/p/7813407.html
總結
以上是生活随笔為你收集整理的React.js 小书 Lesson15 - 实战分析:评论功能(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL中的long text
- 下一篇: 随笔② Java中的关键字 --- fi