React學習筆記1——評論框的實現


學習鏈接:http://reactjs.cn/react/docs/tutorial-zh-CN.html

實現功能:主要分兩個部分:1、評論列表的展示 2、評論框的輸入提交

一、組件

1、拆分組件

一個大容器CommentBox中包含CommetList和CommetForm,CommetList中又包含多個Commet組件

2、CommentBox組件

var CommentBox = React.createClass({
    render: function(){
    return(
      <div>
        <CommentList />
        <CommentForm />
      </div>
    )
  }
})
ReactDOM.render({
  <CommetBox />,
  document.getElementById('content')
})
//首先在CommentBox中添加兩個組件,然后將CommetBox渲染到頁面上
  1. React組件必須用大寫字母開頭,且標簽必須閉合,通過return函數返回的標簽也必須是閉合的。比如我將<CommentList/>和<CommentForm/>外面的div去掉,就會報錯
  2. React.createClass 是ES5形式的定義組件;后面又有了React.Component ,ES6形式的定義組件。(React定義組件的方法http://www.cnblogs.com/wonyun/p/5930333.html)
  3. ReactDOM.render({element, container, callback})渲染組件的方法,接收三個參數element 要渲染的組件,container渲染的組件要插入在DOM中的位置,callback回調函數,可選參數,傳入時會在組件渲染完成后調用
  4. render React生命周期中的初始化階段的一個函數,用來組裝組件的html結構,必須要有返回值,返回的也可以是null 或者false

3、CommentList組件

var CommetList= React.createClass({
    render: function(){
    return(
      <div>    //包含多個comment組件
        <Comment />
        <Comment />
      </div>
    )
  }
})

4、Comment組件

var Comment = React.createClass({
    render: function(){     return(       <div>             <h3>"this is author"</h3>    //展示作者
        <div>"this is comment text"</div>    //展示評論       </div>     )   } })

5、CommentForm組件

var CommentForm = React.createClass({
    render: function(){
    return(
      <form>         <input type='text' placeholder='enter your name'/>
        <input type='text' placeholder='say something ...'/>
        <input type='submit' value='submit'/>
      </form>
           )   } })

二、數據

1、簡介

React父子組件數據的傳遞可使用props和state。props屬性是組件與生俱來的不可以由組件自己修改,state狀態是事物自己的,可不斷變化。主要區分是組件在運行時需要修改的是state,此外所有的數據都可以是props

  屬性 狀態
是否能從父組件獲取初始值 T F
是否由父組件修改 T F
能否在組件內部設置默認值 T T
能否在組件內部修改 F T
能否設置子組件的初始值 T F
能否修改子組件的值 T F

 

 

 

 

 

 

(1)、this.props  用來訪問從父組件傳進來的數據

(2)、this.state  用來訪問動態更新的數據

(3)、this.setState()  將服務器獲取的數據更新到狀態中(更新CommetList中的數據)

(4)、父子組件之間的數據通信,父組件通過this.props將數據傳遞給子組件;子組件通過委托(delegate)即事件處理函數與父組件通信,子組件觸發函數,父組件處理。

2、獲取、更新數據

ReactDOM.render( 
  <CommetBox url='/api/comments', pollInterval={2000}>,  //這個請求地址是在server中設置好了,
  document.getElementById('content')
)
var CommentBox = React.createClass({
  loadCommentsFromServer: function(){    
    $.ajax({
      url: this.props.url,     //通過this.props獲取父組件中的屬性
      dataType: 'json',
      cache: false,
      success: function(data){
        this.setState({data:data})        //動態更新的關鍵是通過this.setState()設置狀態
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
 
   })
  },
  getInitialState:function(){
    return {data:[]}  
  },
  
  componentDidMount: function(){  
    this.loadCommentsFromServer();                      //這里通過設置定時器實時刷新數據,為了避免剛開始數據要在間隔時間后才出來的情況,所以先調用一次獲取數據
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },
  render: function(){
    return(
      <div>
        <CommentList data={this.state.data} />
        <CommentForm />
      </div>
    )
  }
})
var CommentList = React.creatClass({
  render: function(){
    var commnetNodes = this.props.data.map(function(comment){  //data的數據結構[ {"author": "Pete Hunt", "text": "This is one comment"}, {"author": "Jordan Walke", "text": "This is *another* comment"} ]
      return(
        <Comment key={comment.id} author={comment.author}>
          {commnet.text}
        </Comment>
      )
    })
    return(
      <div>
        {commentNodes}
      </div>
    )
  }
})

 

var Comment = React.createClass({
  return(
    <div>
      <h3>
        {this.props.author}
      </h3>
      <p>
        {this.children.text.toString()}
      </p>
    </div>
  )
})

 

涉及到的生命周期:

(1)getInitialState 生命周期初始化階段,初始化每個實例特有的狀態,在生命周期里只執行一次,必須返回一個對象或者null

(2)componentDidMount 生命周期初始化階段,在成功render並渲染完真實的DOM后react自動調用的方法,此時可以修改DOM。如果要在渲染后對DOM操作就是在這個階段里。

三、事件

子組件通過事件與父組件通信,子組件觸發,父組件處理。

1、添加評論,綁定事件

基本的操作在子組件CommentForm中完成

var CommentForm = React.createClass({
  getInitialState:function(){
    return({author:'',text:''})
  },
  handleAuthorChange: function(e){
    this.setState({author: e.target.value})    //通過this.setState()保證輸入實時更新狀態
  },
  handleTextChange: function(e){
    this.setState({text: e.target.value})
  },
  handleSubmit: function(e){            //提交事件,清空表單
    e.preventDefault();              //阻止提交表單的默認行為
    var author = this.state.author.trim();
    var text = this.state.text.trim();
    if (!author || !text) {
      return
    }
    this.setState({author:'',text:''})
  },
  
  render:function(){
    return(
      <form onSubmit={this.handleSubmit}>      //提交表單
      <input
        type='text'
        value={this.state.author}
        placeholder='your name'
        onChange = {this.handleAuthorChange}    //綁定事件
      />
      <input
        type='text'
        value={this.state.text}
        placeholder='enter something'
        onChange = {this.handleTextChange}         //綁定事件
      />
      <input type='submit' value='提交' />    
      </form>
      )
  }
})

2、提交更新評論  子組件傳遞數據給父組件

提交評論時需要刷新評論列表來包含這條評論。發送請求及刷新評論的操作在CommentBox(即父組件)中完成,原因是:CommentBox中有評論列表的狀態。現在需要把CommentForm(子組件)中的數據傳遞到CommentBox(父組件)中,子組件通過事件與父組件通信。所以在父組件中傳遞一個回調函數(handleCommetSubmit)到子組件中,子組件綁定這個函數傳值即可,這樣只要子組件CommentForm中的事件被觸發,父組件CommentBox中的回調函數handCommentSubmit就會被調用。

//CommentBox中
handleCommentSubmit: function(comment){ $.ajax({ url:this.props.url, dataType:'json', type:'POST', data: comment, success: function(data){ this.setState({data:data}) }.bind(this), error: function(xhr, status, err){ this.setState({data: comments}); console.log(this.props.url, status, err.toString()) }.bind(this) })
render: function(){
    return(
      <div>
        <CommentList data={this.state.data}/>
        <CommentForm onCommentSubmit={this.handleCommentSubmit}/> //傳遞回調函數給子組件
      </div>
      )
  }

//CommentForm中
  handleSubmit: function(e){
    e.preventDefault();
    var author = this.state.author.trim();
    var text = this.state.text.trim();
    if (!author || !text) {
      return
    }
    this.props.onCommentSubmit({author:author,text:text})    //綁定回調函數,則handleSubmit事件一觸發,回調函數就會被調用
    this.setState({author:'',text:''})
  },

四、優化

 1、更新太慢要等請求完成后頁面才會展示新的評論,手動添加新評論到列表中讓體驗更快一些

  handleCommentSubmit: function(comment) {
    var comments = this.state.data;
    comment.id = Date.now();
    var newComments = comments.concat([comment]);this.setState({data: newComments});
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      type: 'POST',
      data: comment,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        this.setState({data: comments});
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  }

2、插入的文本中如果有HTML標簽,我們是默認展示成輸入的樣子的,如點<a href='.....'>這里</a>可以跳轉哦。如果我們想要把這種樣子的評論真正的渲染成HTML,可以用到dangerouslySetInnerHTML

<span dangerouslySetInnerHTML={{ __html: this.props.children.toString()}}/>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM