facebook開源前端UI框架React初探


最近最火的前端UI框架非React莫屬了。趕緊找時間了解一下。

項目地址:http://facebook.github.io/react/

官方的介紹:A JavaScript library for building user interfaces (前端UI的js框架)

具有三個特點:

Just the UI

Lots of people use React as the V in MVC. Since React makes no assumptions about the rest of your technology stack, it's easy to try it out on a small feature in an existing project. (一般人們將React用於實現前端MVC中的view中,因為React並不假定你使用的其它前端技術堆棧,所以很容易在已經存在的項目中試用。)

Virtual DOM

React abstracts away the DOM from you, giving a simpler programming model and better performance. React can also render on the server using Node, and it can power native apps using React Native. (使用React我們並不直接操作瀏覽器中的DOM,React引入了虛擬DOM的概念,我們使用js代碼直接生成虛擬DOM節點,然后React負責將虛擬DOM節點到實際DOM節點的轉換,這樣的話,使前端UI編程更加的簡單而且性能更好。)

Data flow

React implements one-way reactive data flow which reduces boilerplate and is easier to reason about than traditional data binding.(React實現單向的數據流,從而減少了傳統數據綁定的模板文件,而且更加容易理解)

其實我自己的理解是:React是一個將前端UI組件化的框架,它可以將頁面上的各種UI實現為一個一個的組件,我們向組件傳入數據,React負責生成對應的UI,然后進行渲染。實現方式是虛擬DOM和單向數據流,虛擬DOM提供了更好的性能,因為比如一個UI組件包含多個html標簽元素,如果我們需要修改其中的幾個標簽中的數據的話,就會對DOM操作幾次(比如使用jquey),然而使用虛擬DOM,我們是先在內存中生成整個UI組件,然后一次性將虛擬DOM轉換渲染到實際DOM,所以對實際DOM的操作只有一次。單向數據流是指沒有數據的雙向綁定,數據只從Model向View傳送,每次更新都是使用一個全新的UI組件替換頁面上舊的UI組件,更加的簡單。

其實React最大特點是:UI組件化和UI整體替換的更新方式,然后才是性能更好,更加簡單。組件化就容易維護,方便重用。

實例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="build/react.js"></script>
<script src="build/JSXTransformer.js"></script>
</head>
<body>
  <div id="example"></div>
  
<script type="text/jsx">
React.render(
    <h1>Hello, world!</h1>,
    document.getElementById('example')
);
</script>
</body>
</html>

上面代碼導入React的js庫react.js,而JSXTransformer.js是將頁面上 type="text/jsx" 的代碼轉換成 text/javascript 代碼的轉換庫。轉換可以再瀏覽器端進行,也可以使用Nodejs再服務端進行。實際項目運行都是在服務端進行轉換。我們先看下在瀏覽器端進行轉換的效果:

可以看到React成功渲染出了一個UI組件,但是下面提示我們應該先在服務端預編譯 jsx 腳步。

然后我們再看服務端轉換預編譯 jsx 方法:

安裝Node.js:到 https://nodejs.org/ 下載對應平台的安裝文件:node-v0.12.2-x86.msi

我是win7 64位,雙擊一路下一步安裝完成。配置系統路徑,將 D:\nodejs 加入 path, 新建系統變量:NODE_PATH,值為:D:\nodejs\node_modules\

安裝 react-tools: npm install react-tools

安裝成功如下圖:

再預編譯 jsx 腳本之前,我們將它提取出來,單獨放入一個文件:helloworld.js

React.render(
  <h1>Hello, world!</h1>,
  document.getElementById('example')
);

然后調用react-tool中的 jsx 腳本來編譯:

上面將 當前目錄下的 jsxfile 文件夾中的所有的 jsx 腳本編譯到 當前目前下的 result 文件夾下,編譯之后的代碼為:

React.render(
  React.createElement("h1", null, "Hello, world!"),
  document.getElementById('example')
);

React.createElement("h1", null, "Hello, world!") 表示生產一個 h1 標簽,內容為 "Hello, world!",然后React.render(),將生產的h1標簽渲染插入到document.getElementById('example')節點下去。最后的helloworld.html的內容為:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="build/react.js"></script>
</head>
<body>
    <div id="example"></div>

<script type="text/javascript">
React.render(
    React.createElement('h1', null, 'Hello, world!'),
    document.getElementById('example')    // $("#example")[0]
);
</script>
</body>
</html>

注意這里我們將 JSXTransformer.js 文件去掉了,並且將 text/jsx 改成了 text/javascript. 當然我們也可以將編譯生產的js單獨放入一個文件,然后使用 <script type="text/javascript" src="xxx"> 引入到頁面。

效果為:

下面我們分析下Github上使用React實現的Tab選擇器

地址:https://github.com/supnate/react-tab-selector 該例子很好的說明了React的基本用法

源碼如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="js/react.js"></script>
<script src="js/JSXTransformer.js"></script>
<link rel="stylesheet" tpe="text/css" href="style.css"/>
</head>
<body>
    <div id="container"></div>
    
<script type="text/jsx">
var data = [
    {name: 'Red', value: 'red'},
    {name: 'Blue', value: 'blue'},
    {name: 'Yellow', value: 'yellow'},
    {name: 'Green', value: 'green'},
    {name: 'White', value: 'White'}
];

var TabSelector = React.createClass({
    getInitialState: function() {
        return {selected: this.props.selected};
    },

    handleOnClick: function (evt) {
           this.setState({'selected': evt.target.getAttribute('data-value')})
    },

    render: function() {
        var tabs = this.props.data.map(function (item) {
            var selected = item.value == this.state.selected ? 'selected' : '';
            return <li data-value={item.value} className={selected} onClick={this.handleOnClick}>
                        {item.name}
                   </li>;
        }, this);

        return <div className="tab-selector">
                    <label>{this.props.label}</label>
                    <ul>{tabs}</ul>
               </div>;
    }
});

React.render(
    TabSelector({label: 'Color', data: data, selected: null}),
    document.getElementById('container')
);
</script>
</body>
</html>

這個例子涉及到很多的React基礎知識:

TabSelector({label: 'Color', data: data, selected: null}) 相當於一個組件的構造函數,傳入我們從后台獲得的數據(一個json對象),在組件TabSelector的實現中有各種函數,這些函數中訪問我們傳入的數據的方式是:this.props.label, this.props.data, this.props.selected。render方法的實現,就是使用傳入的數據,然后返回我們需要在頁面上渲染的UI組件,this.props.data.map() 這里使用了javascript中數組的map函數來處理每一個數組項,每次得到 <li></li> ,所以返回的var tabs的結果是一個 <li></li> 的數組。最后通過

return <div className="tab-selector">
            <label>{this.props.label}</label>
            <ul>{tabs}</ul>
       </div>;

返回最終生成的UI組件。這里使用 var 定義的變量 tabs 的訪問方式是:{tabs},訪問傳入的數據的方式也是 {this.props.label}。每一個<li></li>標簽上定義了 onClick={this.handleOnClick} 點擊的處理方法,而 handleOnClick的實現為,每次點擊時,就使用被點擊的<li></li>元素的data-value 屬性的值來更新自己的 className={selected} 中的 {selected},從而實現被點擊時就改變它的樣式。而這個實現中調用了setState()方法,這個方法是React庫中的方法,它被調用時,如果state的狀態發生了變化,那么就會對UI組件使用新的state進行重新渲染。

在getInitialState函數中定義了該組件的state的初始狀態(selected屬性的值),該函數在組件初始化時調用:

    getInitialState: function() {
        return {selected: this.props.selected};
    },

而 this.setState({'selected': evt.target.getAttribute('data-value')}) 會修改該組件的狀態state的值,組件的state變化的話,會導致組件UI的刷新,重新生成,然后插入DOM。實際頁面如下圖:

點擊某個 tab 的效果如下圖:

所以總結一下:

1)getInitialState 函數用於定義組件的state;

2)render 函數定義了根據傳入的數據生成UI組件的方法;

3)而 setState 函數會修改組件的state,從而觸發組件UI的刷新,重新調用render方法;

4)handleOnClick 函數定義了點擊事件的處理;

5)訪問傳入的數據的方法:{this.props.xx}

6)訪問js變量的方法: {variable}

7)css 中的 class 要使用 className 替換,不能直接使用 class

8)React.createClass 創建組件(類),使用了面向對象的概念來進行處理,創建一個組件,就相當於實例化一個對象,類就是“組件類”,組件就是“對象”

9)訪問state的屬性方法:{this.state.xxx}

10)React的jsx腳本的寫法,和 html 頁面的寫法是相似的,並不像在js中那樣需要引號來包含,這樣方便我們直接將前端的 html 頁面使用React來組件化

我們可以比較一下采用jquery的寫法:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="js/jquery.min.js"></script>
<link rel="stylesheet" tpe="text/css" href="style.css"/>
</head>
<body>
    <div id="container"></div>    
    
<script type="text/javascript">
var data = [
    {name: 'Red', value: 'red'},
      {name: 'Blue', value: 'blue'},
      {name: 'Yellow', value: 'yellow'},
      {name: 'Green', value: 'green'},
      {name: 'White', value: 'White'}
];

$.fn.TabSelector = function (options) {
    var arr = ['<div class="tab-selector">'];
      arr.push('<label>', options.label, '</label>');
      arr.push('<ul>');
      options.data.forEach(function (item) {
        arr.push('<li data-value="', item.value, '">');
        arr.push(item.name);
        arr.push('</li>');
      });
      arr.push('</ul></div>');

      this.html(arr.join(''));

      var lastSelected = null;
      this.on('click', 'li', function () {
        var $this = $(this);
        if (lastSelected) {
          lastSelected.removeClass('selected');
        }
        $this.addClass('selected');
        lastSelected = $this;
    });

      return this;
}

$('#container').TabSelector({data: data, selected: null, label: 'Color'});
</script>
</body>
</html>

明顯感覺到jquery也就是javascript在拼接 html 代碼時的繁瑣,總是需要使用引號來處理,而React的jsx寫法和html幾乎一樣。

 

有價值的參考鏈接:

React實現的理論知識:http://www.infoq.com/cn/articles/subversion-front-end-ui-development-framework-react

React的介紹:http://www.cnblogs.com/chyingp/p/react-getting-started.html

官網:http://facebook.github.io/react/


免責聲明!

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



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