React Native之React速學教程(上)

来源:http://www.cnblogs.com/burningmyself/archive/2017/05/26/6910260.html
-Advertisement-
Play Games

概述 本篇為《React Native之React速學教程》的第一篇。本篇將從React的特點、如何使用React、JSX語法、組件(Component)以及組件的屬性,狀態等方面進行講解。 What’s React React是一個用於組建用戶界面的JavaScript庫,讓你以更簡單的方式來創建 ...


概述

本篇為《React Native之React速學教程》的第一篇。本篇將從React的特點、如何使用React、JSX語法、組件(Component)以及組件的屬性,狀態等方面進行講解。

What’s React

React是一個用於組建用戶界面的JavaScript庫,讓你以更簡單的方式來創建互動式用戶界面。

  1. 當數據改變時,React將高效的更新和渲染需要更新的組件。聲明性視圖使你的代碼更可預測,更容易調試。
  2. 構建封裝管理自己的狀態的組件,然後將它們組裝成複雜的用戶界面。由於組件邏輯是用JavaScript編寫的,而不是模板,所以你可以輕鬆地通過您的應用程式傳遞豐富的數據,並保持DOM狀態。
  3. 一次學習隨處可寫,學習React,你不僅可以將它用於Web開發,也可以用於React Native來開發Android和iOS應用。

不是模板卻比模板更加靈活:

Component

心得:上圖是GitHub Popular的首頁截圖,這個頁面是通過不同的組件組裝而成的,組件化的開發模式,使得代碼在更大程度上的到復用,而且組件之間對的組裝很靈活。

Get Started

使用React之前需要在頁面引入如下js庫 。

  • react.js
  • react-dom.js
  • browser.min.js

上面一共列舉了三個庫: react.js 、react-dom.js 和 browser.min.js ,它們必須首先載入。其中,react.js 是 React 的核心庫,react-dom.js 是提供與 DOM 相關的功能,browser.min.js 的作用是將 JSX 語法轉為 JavaScript 語法,這一步很消耗時間,實際上線的時候,應該將它放到伺服器完成。
你可以從React官網下載這些庫,也可以將其下載到本地去使用。

心得:在做React Native開發時,這些庫作為React Native核心庫已經被初始化在node_modules目錄下,所以不需要單獨下載。

使用React

解壓從上述地址下載的壓縮包,在根目錄中創建一個包含以下內容的 “helloworld.html” 。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <script src="build/react.js"></script>
    <script src="build/react-dom.js"></script>
    <script src="https://npmcdn.com/[email protected]/browser.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script type="text/babel">
      ReactDOM.render(
        <h1>Hello, world!</h1>,
        document.getElementById('example')
      );
    </script>
  </body>
</html>

在 JavaScript 代碼里寫著 XML 格式的代碼稱為 JSX,下文會介紹。為了把 JSX 轉成標準的 JavaScript,我們用<script type="text/babel">標簽,然後通過Babel轉換成在瀏覽器中真正執行的內容。

ReactDOM.render()

ReactDOM.render 是 React 的最基本方法,用於將模板轉為 HTML 語言,並插入指定的 DOM 節點。

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

上述代碼的作用是將<h1>Hello, world!</h1>插入到元素id為example的容器中。

JSX

JSX 是一個看起來很像 XML 的 JavaScript 語法擴展。 每一個XML標簽都會被JSX轉換工具轉換成純JavaScript代碼,使用JSX,組件的結構和組件之間的關係看上去更加清晰。
JSX並不是React必須使用的,但React官方建議我們使用 JSX , 因為它能定義簡潔且我們熟知的包含屬性的樹狀結構語法。

Usage:

React.render(//使用JSX
    <div>
        <div>
            <div>content</div>
        </div>
    </div>,
    document.getElementById('example')
);
React.render(//不使用JSX
    React.createElement('div', null,
        React.createElement('div', null,
            React.createElement('div', null, 'content')
        )
    ),
    document.getElementById('example')
);

HTML標簽 與 React組件 對比

React 可以渲染 HTML 標簽 (strings) 或 React 組件 (classes)。
要渲染 HTML 標簽,只需在 JSX 里使用小寫字母開頭的標簽名。

var myDivElement = <div className="foo" />;
React.render(myDivElement, document.body);

要渲染 React 組件,只需創建一個大寫字母開頭的本地變數。

var MyComponent = React.createClass({/*...*/});
var myElement = <MyComponent someProperty={true} />;
React.render(myElement, document.body);

提示:

  • React 的 JSX 里約定分別使用首字母大、小寫來區分本地組件的類和 HTML 標簽。
  • 由於 JSX 就是 JavaScript,一些標識符像 class 和 for 不建議作為 XML 屬性名。作為替代, React DOM 使用 className 和 htmlFor 來做對應的屬性。

JavaScript 表達式

屬性表達式

要使用 JavaScript 表達式作為屬性值,只需把這個表達式用一對大括弧 ({}) 包起來,不要用引號 (“”)。

// 輸入 (JSX):
var person = <Person name={window.isLoggedIn ? window.name : ''} />;
// 輸出 (JS):
var person = React.createElement(
  Person,
  {name: window.isLoggedIn ? window.name : ''}
);

子節點表達式

同樣地,JavaScript 表達式可用於描述子結點:

// 輸入 (JSX):
var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
// 輸出 (JS):
var content = React.createElement(
  Container,
  null,
  window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
);

註釋

JSX 里添加註釋很容易;它們只是 JS 表達式而已。你只需要在一個標簽的子節點內(非最外層)用 {} 包圍要註釋的部分。

class ReactDemo extends Component {
  render() {
    return (     
      <View style={styles.container}>
        {/*標簽子節點的註釋*/}
        <Text style={styles.welcome}
          //textAlign='right'
          textShadowColor='yellow'
          /*color='red'
          textShadowRadius='1'*/
          >
          React Native!
        </Text>
      </View>
    );
  }
}

心得:在標簽節點以外註釋,和通常的註釋是一樣的,多行用“/**/” 單行用“//”;

JSX延展屬性

不要試圖去修改組件的屬性

不推薦做法:

  var component = <Component />;
  component.props.foo = x; // 不推薦
  component.props.bar = y; // 不推薦

這樣修改組件的屬性,會導致React不會對組件的屬性類型(propTypes)進行的檢查。從而引發一些預料之外的問題。

推薦做法:

var component = <Component foo={x} bar={y} />;

延展屬性(Spread Attributes)

你可以使用 JSX 的新特性 - 延展屬性:

  var props = {};
  props.foo = x;
  props.bar = y;
  var component = <Component {...props} />;

傳入對象的屬性會被覆制到組件內。

它能被多次使用,也可以和其它屬性一起用。註意順序很重要,後面的會覆蓋掉前面的。

  var props = { foo: 'default' };
  var component = <Component {...props} foo={'override'} />;
  console.log(component.props.foo); // 'override'

上文出現的… 標記被叫做延展操作符(spread operator)已經被 ES6 數組 支持。

Component

React 允許將代碼封裝成組件(component),然後像插入普通 HTML 標簽一樣,在網頁中插入這個組件。

var HelloMessage = React.createClass({
  render: function() {
    return <h1>Hello {this.props.name}</h1>;
  }
});
ReactDOM.render(
  <HelloMessage name="John" />,
  document.getElementById('example')
);

上面代碼中,變數 HelloMessage 就是一個組件類。模板插入 <HelloMessage /> 時,會自動生成 HelloMessage 的一個實例。所有組件類都必須有自己的 render 方法,用於輸出組件。

註意

  • 組件類的第一個字母必須大寫。
  • 組件類只能包含一個頂層標簽。

組件的屬性(props)

我們可以通過this.props.xx的形式獲取組件對象的屬性,對象的屬性可以任意定義,但要避免與JavaScript關鍵字衝突。

遍歷對象的屬性:

this.props.children會返回組件對象的所有屬性。
React 提供一個工具方法 React.Children 來處理 this.props.children 。我們可以用 React.Children.mapReact.Children.forEach 來遍歷子節點。
React.Children.map

array React.Children.map(object children, function fn [, object thisArg])

該方法會返回一個array。
React.Children.forEach

React.Children.forEach(object children, function fn [, object thisArg])

Usage:

var NotesList = React.createClass({
  render: function() {
    return (
      <ol>
      {
        React.Children.map(this.props.children, function (child) {
          return <li>{child}</li>;
        })
      }
      </ol>
    );
  }
});
ReactDOM.render(
  <NotesList>
    <span>hello</span>
    <span>world</span>
  </NotesList>,
  document.body
);

PropTypes

組件的屬性可以接受任意值,字元串、對象、函數等等都可以。有時,我們需要一種機制,驗證別人使用組件時,提供的參數是否符合要求。
組件類的PropTypes屬性,就是用來驗證組件實例的屬性是否符合要求。

var MyTitle = React.createClass({
  propTypes: {
    title: React.PropTypes.string.isRequired,
  },
  render: function() {
     return <h1> {this.props.title} </h1>;
   }
});

上面的Mytitle組件有一個title屬性。PropTypes 告訴 React,這個 title 屬性是必須的,而且它的值必須是字元串。現在,我們設置 title 屬性的值是一個數值。

var data = 123;
ReactDOM.render(
  <MyTitle title={data} />,
  document.body
);

這樣一來,title屬性就通不過驗證了。控制台會顯示一行錯誤信息。

Warning: Failed propType: Invalid prop `title` of type `number` supplied to `MyTitle`, expected `string`.

更多的PropTypes設置,可以查看官方文檔
此外,getDefaultProps 方法可以用來設置組件屬性的預設值。

var MyTitle = React.createClass({
  getDefaultProps : function () {
    return {
      title : 'Hello World'
    };
  },
  render: function() {
     return <h1> {this.props.title} </h1>;
   }
});
ReactDOM.render(
  <MyTitle />,
  document.body
);

上面代碼會輸出"Hello World"

ref 屬性(獲取真實的DOM節點)

組件並不是真實的 DOM 節點,而是存在於記憶體之中的一種數據結構,叫做虛擬 DOM (virtual DOM)。只有當它插入文檔以後,才會變成真實的 DOM 。根據 React 的設計,所有的 DOM 變動,都先在虛擬 DOM 上發生,然後再將實際發生變動的部分,反映在真實 DOM上,這種演算法叫做 DOM diff ,它可以極大提高網頁的性能表現。

但是,有時需要從組件獲取真實 DOM 的節點,這時就要用到 ref 屬性。

var MyComponent = React.createClass({
  handleClick: function() {
    this.refs.myTextInput.focus();
  },
  render: function() {
    return (
      <div>
        <input type="text" ref="myTextInput" />
        <input type="button" value="Focus the text input" 		  onClick={this.handleClick} />
      </div>
    );
  }
});
ReactDOM.render(
  <MyComponent />,
  document.getElementById('example')
);

上面代碼中,組件 MyComponent 的子節點有一個文本輸入框,用於獲取用戶的輸入。這時就必須獲取真實的 DOM 節點,虛擬 DOM 是拿不到用戶輸入的。為了做到這一點,文本輸入框必須有一個 ref 屬性,然後 this.refs.[refName] 就會返回這個真實的 DOM 節點。
需要註意的是,由於 this.refs.[refName] 屬性獲取的是真實 DOM ,所以必須等到虛擬 DOM 插入文檔以後,才能使用這個屬性,否則會報錯。上面代碼中,通過為組件指定 Click 事件的回調函數,確保了只有等到真實 DOM 發生 Click 事件之後,才會讀取 this.refs.[refName] 屬性。
React 組件支持很多事件,除了 Click 事件以外,還有 KeyDown 、Copy、Scroll 等,完整的事件清單請查看官方文檔

心得:ref屬性在開發中使用頻率很高,使用它你可以獲取到任何你想要獲取的組件的對象,有個這個對象你就可以靈活地做很多事情,比如:讀寫對象的變數,甚至調用對象的函數。

state

上文講到了props,因為每個組件只會根據props 渲染了自己一次,props 是不可變的。為了實現交互,可以使用組件的 state 。this.state 是組件私有的,可以通過getInitialState()方法初始化,通過調用 this.setState() 來改變它。當 state 更新之後,組件就會重新渲染自己。
render() 方法依賴於 this.props 和 this.state ,框架會確保渲染出來的 UI 界面總是與輸入( this.props 和 this.state )保持一致。

初始化state

通過getInitialState() 方法初始化state,在組件的生命周期中僅執行一次,用於設置組件的初始化 state 。

 getInitialState:function(){
    return {favorite:false};
  }

更新 state

通過this.setState()方法來更新state,調用該方法後,React會重新渲染相關的UI。
this.setState({favorite:!this.state.favorite});

Usage:

var FavoriteButton=React.createClass({
  getInitialState:function(){
    return {favorite:false};
  },
  handleClick:function(event){
    this.setState({favorite:!this.state.favorite});
  },
  render:function(){
    var text=this.state.favorite? 'favorite':'un favorite';
    return (
      <div type='button' onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </div>
    );
  }
});

上面代碼是一個 FavoriteButton 組件,它的 getInitialState 方法用於定義初始狀態,也就是一個對象,這個對象可以通過 this.state 屬性讀取。當用戶點擊組件,導致狀態變化,this.setState 方法就修改狀態值,每次修改以後,自動調用 this.render 方法,再次渲染組件。

心得:由於 this.props 和 this.state 都用於描述組件的特性,可能會產生混淆。一個簡單的區分方法是,this.props 表示那些一旦定義,就不再改變的特性,而 this.state 是會隨著用戶互動而產生變化的特性。

參考

React’s official site
React on ES6+

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 re ...
  • 前文提要:【js實例】js中的5種基本數據類型和9種操作符 Array類型的9個數組方法 Array中有9個數組方法: 1.檢測數組 2.轉換方法 3.棧方法 4.隊列方法 5.沖排序方法6.操作方法 7.位置方法 8.迭代方法 9.歸併方法 在實例中介紹,實例如下 Date類型的41個日期方法 D ...
  • 做為css佈局的又一種新方式,Flex擁有極強的使用效果,相比原來的float,position對元素樣式的操作更加簡潔,本文是我的一點學習經驗和心得吧,如有錯誤以及不足之處,請多多指點。 好進入正題吧,首先借用阮一峰大神的一副圖片: 再來說說flex的幾個屬性吧: 一、容器屬性 1.flex-di ...
  • 1.Generator函數其實是一個封裝了多個內部狀態的狀態機,執行它會返回一個遍歷器對象,然後可以依次遍歷Generator中的每一個狀態,也就是分段執行,yield是暫停執行的標記,next恢復執行。 2.yield: - 一個函數裡面,return只能執行一遍,yield可以執行多次; - G ...
  • JavaScript中的運算符分為以下幾類: 算術運算符 比較運算符 邏輯運算符 賦值運算符 1. 算術運算符 算術運算符用於執行變數與/或值之間的算術運算。 給定 y=5,下麵的表格解釋了這些算術運算符: 註意點: a. 自增和自減 遞增和遞減運算符可以放在變數前也可以放在變數後: 當放在變數前, ...
  • Promise 是什麼 Promise是非同步編程的一種解決方案。Promise對象表示了非同步操作的最終狀態(完成或失敗)和返回的結果。 其實我們在jQuery的ajax中已經見識了部分Promise的實現,通過Promise,我們能夠將回調轉換為鏈式調用,也起到解耦的作用。 怎麼用 Promise接 ...
  • vue-cli+webpack在生成的項目中使用bootstrap方法(一)中,是通過手動下載bootstrap庫,然後手動添加到src/assets中,顯然是過程太多。 當然是可以更省力些,可以通過npm安裝bootstrap,然後用import直接導入bootstrap的方式進行整合,因為vue ...
  • 轉載請註明:http://www.cnblogs.com/igoslly/p/6911165.html 由於最近廢寢忘食地在開發App,沒來得及及時做總結,沒有用很高級的部件,勉強也使用一些功能完成了自己的第一個App,撒花~~~ 接下來都是自己在開發中使用後的一些經驗,也是和他人學習實踐後的成果, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...