ReactJS入門

標簽:前端開發 ReactJS


官網
官網中文鏡像(推薦)
阮一峰老師的教程
菜鳥網的教程
一看就懂的ReactJS入門教程(語法有點過期了)

關鍵庫:
react.js; react-dom.js; browser.min.js;


前言: ReactJS產生的原因背景

在Web開發中,我們總需要將變化的數據實時反應到UI上,這時就需要對DOM進行操作。而復雜或頻繁的DOM操作通常是性能瓶頸產生的原因(如何進行高性能的復雜DOM操作通常是衡量一個前端開發人員技能的重要指標)。React為此引入了虛擬DOM(Virtual DOM)的機制:在瀏覽器端用Javascript實現了一套DOM API。基于React進行開發時所有的DOM構造都是通過虛擬DOM進行,每當數據變化時,React都會重新構建整個DOM樹,然后React將當前整個DOM樹和上一次的DOM樹進行對比,得到DOM結構的區別,然后僅僅將需要變化的部分進行實際的瀏覽器DOM更新。而且React能夠批處理虛擬DOM的刷新,在一個事件循環(Event Loop)內的兩次數據變化會被合并,例如你連續的先將節點內容從A變成B,然后又從B變成A,React會認為UI不發生任何變化,而如果通過手動控制,這種邏輯通常是極其復雜的。盡管每一次都需要構造完整的虛擬DOM樹,但是因為虛擬DOM是內存數據,性能是極高的,而對實際DOM進行操作的僅僅是Diff部分,因而能達到提高性能的目的。這樣,在保證性能的同時,開發者將不再需要關注某個數據的變化如何更新到一個或多個具體的DOM元素,而只需要關心在任意一個數據狀態下,整個界面是如何Render的。
如果你像在90年代那樣寫過服務器端Render的純Web頁面那么應該知道,服務器端所要做的就是根據數據Render出HTML送到瀏覽器端。如果這時因為用戶的一個點擊需要改變某個狀態文字,那么也是通過刷新整個頁面來完成的。服務器端并不需要知道是哪一小段HTML發生了變化,而只需要根據數據刷新整個頁面。換句話說,任何UI的變化都是通過整體刷新來完成的。而React將這種開發模式以高性能的方式帶到了前端,每做一點界面的更新,你都可以認為刷新了整個頁面。至于如何進行局部更新以保證性能,則是React框架要完成的事情。


1.代碼生成標簽,插入到指定位置

jsx/babel語言 JS,HTML混寫

<body>  
   <div id="example"></div>  
   <script type="text/babel">     
    ReactDOM.render(
       <h2>Hello,world</h2>, 
      document.getElementById('example')
    );  
    </script>
</body>

div#example 作為容器存放生成的元素,
生成元素:ReactDOM.render(<tag>{codehere}</tag>, container);

注意:語句結尾可以不加分號,不會出錯,有些語句加了分號之后就會出錯,因此加分號要小心。


2.自定義標簽(組件)

<script type="text/babel"> 
var MyTag = React.createClass({  
    render:function(){ return<h1>{this.props.name}</h1> }  
 }); //this.props.xxx 調用自定義屬性;
ReactDOM.render(<MyTag name="zhe" />, document.getElementById('example') );  
</script> 

自定義標簽要一定要用在render中,直接用在html無效。
后面demo為了方便就不寫ReactDOM.render()了,實際練習時要加上
注意類名一定要首字母大寫,createClass參數是一個對象,
添加組件屬性,有一個地方需要注意,對于要調用class屬性與for屬性,屬性名不能直接寫 class 或者for,這是因為 class 和 for 是 JavaScript 的保留字。用className="" htmlFor=""代替,這樣css一樣可以.class找到該元素


3.可嵌套子元素的自定義標簽

<script type="text/babel">
var MyList = React.createClass({  
     render:function(){ 
         return( 
          <ul>{ React.Children.map(this.props.children,
                 function(child){return<li>{child}</li>} ) }</ul>
         )} //注意大小寫,props.children 用于獲取子元素
});

// 使用
// <MyList> 
//  <span>item1</span> 
//  <span>item2</span>
//</MyList> 

</script>

一種映射的方法:array.map(function(item){console.log(item)})遍歷array每次輸出一個item。
另外如果數組是一系列標簽,可以寫在容器標簽內自動展開,如<div>{array}</div>
React.Children.map該方法遍歷children,而不用理會children因size不同(0,1,1+)而返回的不同類型(undefine,object, array)


4. 組件的參數檢查與默認值

<script type="text/babel">
var MyTag = React.createClass({   
    getDefaultProps: function(){ return {title:"hello"}  }, //默認值   
    propTypes: {title: React.PropTypes.string.isRequired }, //表示title是必須,并且是字符串  
    render: function(){ return<h1>{this.props.title}</h1>} 
});

//<MyTag title={123} /> 控制臺報錯,但一樣會顯示在頁面

</script>



5. 獲取組件內部標簽的DOM節點

內部標簽定義一個ref屬性,組件使用this.refs.xxx內獲取節點

var MyInput = React.createClass({
    clickEvent:function(){ this.refs.tagInside.focus() }, //clickEvent的名字可隨意   
    render:function(){ return(
       <div>
         <input type="text" ref="tagInside"/>
         <input type="button" value="focus" onClick={this.clickEvent} />
       </div> )  
     }
});


6. 組件的狀態this.state

標記組件的狀態,用于改變顯示的文字,樣式等。

var MyInput = React.createClass({
    getInitialState: function(){ return { liked: false } },//定義應有的狀態與初始化,用鍵值對形式   
    clickEvent:function() { this.setState({liked: !this.state.liked }) },//this.setState({}) 改變狀態值   
    render:function() { 
       var text =this.state.liked ? "liked" : "unliked"; 
       return<input type="button" value={text} onClick={this.clickEvent} />    
    }
});

每次setState后都會自動調用render,因此可以改變樣式。
注意this.state與this.props的區別,state可以在交互中改變,可讀可寫,props定義了了就不能改變,只讀。


7. 獲取表單的輸入

輸入表單屬于交互,改變this.state

var MyInput = React.createClass({
    getInitialState: function() { return {value: "default"} },   
    changeEvent:function(e) { this.setState({value: e.target.value}) },   
    render:functiion(){ return( 
      <div>  
        <input type="text" value={text} onChange={this.changeEvent} />    
        <p> {text}</p> 
      </div> )  
    } //注意大小寫
});

因為每次改變狀態都會調用render,因此如果input里的value設為常數,那么輸入文本就不會顯示改變


8. 組件的生命周期

分為 mounting: 已插入到真實的DOM中;
updating:被渲染中;
unmounting 已經移出真實的DOM
有兩種回調函數:will 在進入某一步前調用,did進入某一步后調用,共5個

componentWillMount();
componentDidMount();
componentWillUpdate(oNextProps, oNextState);
componentDidUpdate(oPrevProps, oPrevState);
componentWillUnmount();

這個比較復雜,還是看官網比較好:https://facebook.github.io/react/docs/working-with-the-browser.html#component-lifecycle


9. AJAX

componentDidMount 中可以用jQuery.get() 實現,React 本身沒有任何依賴,完全可以不用jQuery,而使用其他庫。

<script type="text/babel">
var UserGist = React.createClass({
  getInitialState: function() {
    return {
      username: '',
      lastGistUrl: ''
    };
  },

  componentDidMount: function() {
    $.get(this.props.source, function(result) {
      var lastGist = result[0];
      if (this.isMounted()) {
        this.setState({
          username: lastGist.owner.login,
          lastGistUrl: lastGist.html_url
        });
      }
    }.bind(this));
  },

  render: function() {
    return (
      <div>
        {this.state.username}'s last gist is <a href={this.state.lastGistUrl}>here</a>.
      </div>
    );
  }
});

ReactDOM.render(
  <UserGist source="https://api.github.com/users/octocat/gists" />,
  document.body
);
</script>

10. 傳入promise對象

<script type="text/babel">
    var RepoList = React.createClass({
        getInitialState: function() {return {loading:true, data:null, error:null}},
        componentDidMount: function() {
            this.props.promise.then(
                value => this.setState({loading:false, data:value}),
                error => this.setState({loading:false, error:error})
            )
        },
        render: function(){
            if (this.state.loading) {
                return <span>loading...</span>
            } else if (this.state.error) {
                return <span>Error: {this.state.error.message} </span>
            } else {
                var repos = this.state.data.items;
                var list = repos.map(function(repo){
                    return (
                        <li> 
                            <a href={repo.html_url}> {repo.name} </a>
                             ({repo.stargazers_count} stars) <br/> 
                             {repo.description}
                        </li> ) 
                })
            }
            return (<div>
                      <h1>Most Popular JavaScript Projects in Github</h1>
                      <ol>{list}</ol>
                    </div>)

        }

    })

    ReactDOM.render(
        <RepoList promise={$.getJSON('https://api.github.com/search/repositories?q=javascript&sort=stars')} />,
        document.getElementById("example")
    )
    </script>

總結

上面是react的簡單用法,更多更詳細的解釋請看官方文檔。
react還可以配合flux框架使用,接下來可以學習這方面的相關知識。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 作者:雲霏霏原文地址:http://www.cnblogs.com/yunfeifei/ 現在最熱門的前端框架有A...
    IT程序獅閱讀 1,562評論 1 38
  • React 入門實例教程 轉載(加入了自己的一些東西,推薦看原文):一看就懂的ReactJs入門教程(精華版) ...
    驀然之間的閱讀 413評論 0 0
  • react簡介 react是由Fecebook開發的UI庫,它的核心思想開發reactJS的組件可以重復調用,易于...
    小_b6d4閱讀 485評論 0 0
  • 在React這股目前最熱前端框架之風刮來之前,一直在Cocos2d-html5游戲和半路出家的Android應用的...
    hahafei閱讀 379評論 0 2
  • 今夜 相思寄明月 將你念 一輩子 擇你一人 即為一生 選擇 只為圓最初的夢 還軍旅一次遠征
    大呂同志閱讀 266評論 8 10