2014-06-16 38 views
20

我正在嘗試將zurb顯示與表單合併爲反應組件。到目前爲止,下面的代碼可以正確地顯示模式窗體:如何使react.js與zurb一起玩好顯示模式表單

ModalForm = React.createClass({ 
    handleSubmit: function(attrs) { 
    this.props.onSubmit(attrs); 
    return false; 
    }, 

    render: function(){ 
    return(
     <div> 
     <a href="#" data-reveal-id="formModal" className="button">Add new</a> 
     <div id="formModal" className="reveal-modal" data-reveal> 
      <h4>Add something new</h4> 
      <Form onSubmit={this.handleSubmit} /> 
      <a className="close-reveal-modal">&#215;</a> 
     </div> 
     </div> 
    ); 
    } 
}); 

Form成分是非常標準:

Form = React.createClass({ 
    handleSubmit: function() { 
    var body = this.refs.body.getDOMNode().value.trim(); 
    if (!body) { 
     return false; 
    } 
    this.props.onSubmit({body: body}); 
    this.refs.body.getDOMNode().value = ''; 
    return false; 
    }, 
    render: function(){ 
    return(
     <form onSubmit={this.handleSubmit}> 
     <textarea name="body" placeholder="Say something..." ref="body" /> 
     <input type="submit" value="Send" className="button" /> 
     </form> 
    ); 
    } 
}); 

問題:當我渲染模式窗體組件內的表單組件和輸入內容的形式輸入,則我在控制檯異常處看到Uncaught object。這是一個堆棧:

Uncaught object 
    invariant 
    ReactMount.findComponentRoot 
    ReactMount.findReactNodeByID 
    getNode 
    ... 

如果我只是直接在父組件中渲染表單組件,那麼一切正常。請有人幫忙嗎?

+0

我有同樣的問題 - 我的猜測是,基金會的情態動詞的操縱DOM和響應不能跟蹤。 – dbau

+1

@dbau,你是對的。 – Voldy

+1

我做了一個plunk來展示bug - http://plnkr.co/edit/Z6y5dI?p=preview。我也在幾個地方問過:https://github.com/facebook/react/issues/1703和 https://groups.google.com/forum/#!topic/reactjs/qaG_qRMo29o – dbau

回答

12

總之,你做錯了這是而不是反應中的錯誤。

如果您使用任何類型的修改反應組件的dom節點的插件,那麼它會以某種方式破壞事物。

你應該做的是使用反應本身和互補的CSS來定位你想要的模態對話框。

我會建議創建一個組件,它使用react的statics組件屬性來定義幾個包裝renderComponent的函數,給你一個很好的乾淨的函數調用來顯示或隱藏反應對話框。以下是我過去使用過的一些例子。注意:它確實使用jQuery,但是如果你不想使用jQuery代碼,你可以用標準的js api調用替換jQ,如elementById等。

window.MyDialog = React.createClass({ 
    propTypes: { 
     title:  React.PropTypes.string.isRequired, 
     content: React.PropTypes.string.isRequired 
    }, 
    statics: { 

     // open a dialog with props object as props 
     open: function(props) { 
      var $anchor = $('#dialog-anchor'); 
      if (!$anchor.length) { 
       $anchor = $('<div></div>') 
        .prop('id', 'dialog-anchor'); 
        .appendTo('body'); 
      } 
      return React.renderComponent(
       MyDialog(props), 
       $anchor.get(0) 
      ); 
     }, 

     // close a dialog 
     close: function() { 
      React.unmountComponentAtNode($('#dialog-anchor').get(0)); 
     } 
    }, 

    // when dialog opens, add a keyup event handler to body 
    componentDidMount: function() { 
     $('body').on('keyup.myDialog', this.globalKeyupHandler); 
    }, 

    // when dialog closes, clean up the bound keyup event handler on body 
    componentWillUnmount: function() { 
     $('body').off('keyup.myDialog'); 
    }, 

    // handles keyup events on body 
    globalKeyupHandler: function(e) { 
     if (e.keyCode == 27) { // ESC key 

      // close the dialog 
      this.statics.close(); 
     } 
    }, 

    // Extremely basic dialog dom layout - use your own 
    render: function() { 
     <div className="dialog"> 
      <div className="title-bar"> 
       <div className="title">{this.props.title}</div> 
        <a href="#" className="close" onClick={this.closeHandler}> 
       </div> 
      </div> 
      <div className="content"> 
       {this.props.content} 
      </div> 
     </div> 
    } 
}); 

然後,通過調用打開一個對話框:

MyDialog.open({title: 'Dialog Title', content: 'My dialog content'});

而且隨着

MyDialog.close()

對話框一貫重視新的DOM節點直屬體關閉id'對話錨'。如果你打開一個對話框,當它已經打開時,它會根據新的道具更新dom(或者如果它們是相同的話)。

當然,將對話內容作爲道具參數傳遞並不是特別有用。我通常在下面擴展爲解析markdown - > html的內容,或者在提供url作爲道具時,通過組件內的ajax請求獲取一些html。

我知道上面的代碼並不是你正在尋找的,但我不認爲有一個好的方法可以讓一個dom修改插件與反應一起工作。你永遠不能認爲反應組件的dom表示是靜態的,因此它不能被第三方插件成功操縱。我誠實地想,如果你想以這種方式使用反應,你應該重新評估你爲什麼使用框架。

這就是說,我認爲上面的代碼是一個對話框的好起點,在這個對話框中所有的操作都發生在組件內部,而最終的反應就是所有的!

注意:代碼是從內存中寫得非常快,而且實際上沒有在當前窗體中測試過,所以很抱歉如果有一些小的語法錯誤或什麼的。

+7

雖然我明白你說的是正確的,但它並沒有真正回答這個問題。基金會的目的是讓您不必爲自己喜歡的樣板材料推出自己的組件。看看是否有辦法實現這個工作,即使它不是「正確的方式」,也會很有趣。只是我的兩分錢。 – pech0rin

5

這裏是如何做的邁克,但使用ZF顯示模式:

var Dialog = React.createClass({ 
    statics: { 
    open: function(){ 
     this.$dialog = $('#my-dialog'); 

     if (!this.$dialog.length) { 
     this.$dialog = $('<div id="my-dialog" class="reveal-modal" data-reveal role="dialog"></div>') 
      .appendTo('body'); 
     } 

     this.$dialog.foundation('reveal', 'open'); 

     return React.render(
     <Dialog close={this.close.bind(this)}/>, 
     this.$dialog[0] 
    ); 
    }, 
    close: function(){ 
     if(!this.$dialog || !this.$dialog.length) { 
     return; 
     } 

     React.unmountComponentAtNode(this.$dialog[0]); 
     this.$dialog.foundation('reveal', 'close'); 
    }, 
    }, 
    render : function() { 
    return (
     <div> 
     <h1>This gets rendered into the modal</h1> 
     <a href="#" className="button" onClick={this.props.close}>Close</a> 
     </div> 
    ); 
    } 
}); 
相關問題