React Native之React速學(xué)教程(上)

React Native之React速學(xué)教程(上)

本文出自《React Native學(xué)習(xí)筆記》系列文章新翎。

React Native是基于React的锐膜,在開發(fā)React Native過程中少不了的需要用到React方面的知識乎折。雖然官方也有相應(yīng)的Document,但篇幅比較多,學(xué)起來比較枯燥。
通過《React Native之React速學(xué)教程》你可以對React有更系統(tǒng)和更深入的認(rèn)識攒巍。為了方便大家學(xué)習(xí),我將《React Native之React速學(xué)教程》分為荒勇、柒莉、三篇,大家可以根據(jù)需要進(jìn)行閱讀學(xué)習(xí)沽翔。

概述

本篇為《React Native之React速學(xué)教程》的第一篇常柄。本篇將從React的特點、如何使用React搀擂、JSX語法西潘、組件(Component)以及組件的屬性,狀態(tài)等方面進(jìn)行講解哨颂。

What's React

React是一個用于組建用戶界面的JavaScript庫喷市,讓你以更簡單的方式來創(chuàng)建交互式用戶界面。

  1. 當(dāng)數(shù)據(jù)改變時威恼,React將高效的更新和渲染需要更新的組件品姓。聲明性視圖使你的代碼更可預(yù)測,更容易調(diào)試箫措。
  2. 構(gòu)建封裝管理自己的狀態(tài)的組件腹备,然后將它們組裝成復(fù)雜的用戶界面。由于組件邏輯是用JavaScript編寫的斤蔓,而不是模板植酥,所以你可以輕松地通過您的應(yīng)用程序傳遞豐富的數(shù)據(jù),并保持DOM狀態(tài)弦牡。
  3. 一次學(xué)習(xí)隨處可寫友驮,學(xué)習(xí)React,你不僅可以將它用于Web開發(fā)驾锰,也可以用于React Native來開發(fā)Android和iOS應(yīng)用卸留。

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

Component
Component

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

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 相關(guān)的功能瞬项,browser.min.js 的作用是將 JSX 語法轉(zhuǎn)為 JavaScript 語法,這一步很消耗時間何荚,實際上線的時候囱淋,應(yīng)該將它放到服務(wù)器完成。
你可以從React官網(wǎng)下載這些庫餐塘,也可以將其下載到本地去使用妥衣。

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

使用React

解壓從上述地址下載的壓縮包蜂筹,在根目錄中創(chuàng)建一個包含以下內(nèi)容的 “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/babel-core@5.8.38/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 轉(zhuǎn)成標(biāo)準(zhǔn)的 JavaScript,我們用<script type="text/babel">標(biāo)簽兵扬,然后通過Babel轉(zhuǎn)換成在瀏覽器中真正執(zhí)行的內(nèi)容麻裳。

ReactDOM.render()

ReactDOM.render 是 React 的最基本方法,用于將模板轉(zhuǎn)為 HTML 語言器钟,并插入指定的 DOM 節(jié)點津坑。

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

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

JSX

JSX 是一個看起來很像 XML 的 JavaScript 語法擴(kuò)展傲霸。
每一個XML標(biāo)簽都會被JSX轉(zhuǎn)換工具轉(zhuǎn)換成純JavaScript代碼疆瑰,使用JSX,組件的結(jié)構(gòu)和組件之間的關(guān)系看上去更加清晰狞谱。
JSX并不是React必須使用的乃摹,但React官方建議我們使用 JSX , 因為它能定義簡潔且我們熟知的包含屬性的樹狀結(jié)構(gòu)語法。

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標(biāo)簽 與 React組件 對比

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

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

要渲染 React 組件伶跷,只需創(chuàng)建一個大寫字母開頭的本地變量掰读。

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

提示:

  • React 的 JSX 里約定分別使用首字母大、小寫來區(qū)分本地組件的類和 HTML 標(biāo)簽叭莫。
  • 由于 JSX 就是 JavaScript蹈集,一些標(biāo)識符像 class 和 for 不建議作為 XML 屬性名。作為替代雇初, React DOM 使用 className 和 htmlFor 來做對應(yīng)的屬性拢肆。

JavaScript 表達(dá)式

屬性表達(dá)式

要使用 JavaScript 表達(dá)式作為屬性值,只需把這個表達(dá)式用一對大括號 ({}) 包起來靖诗,不要用引號 ("")郭怪。

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

子節(jié)點表達(dá)式

同樣地,JavaScript 表達(dá)式可用于描述子結(jié)點:

// 輸入 (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 表達(dá)式而已鄙才。你只需要在一個標(biāo)簽的子節(jié)點內(nèi)(非最外層)用 {} 包圍要注釋的部分。

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

心得:在標(biāo)簽節(jié)點以外注釋促绵,和通常的注釋是一樣的攒庵,多行用“/**/” 單行用“//”嘴纺;

JSX延展屬性

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

不推薦做法:

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

這樣修改組件的屬性,會導(dǎo)致React不會對組件的屬性類型(propTypes)進(jìn)行的檢查浓冒。從而引發(fā)一些預(yù)料之外的問題栽渴。

推薦做法:

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

延展屬性(Spread Attributes)

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

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

傳入對象的屬性會被復(fù)制到組件內(nèi)。

它能被多次使用裆蒸,也可以和其它屬性一起用熔萧。注意順序很重要,后面的會覆蓋掉前面的僚祷。

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

上文出現(xiàn)的... 標(biāo)記被叫做延展操作符(spread operator)已經(jīng)被 ES6 數(shù)組 支持。

Component

React 允許將代碼封裝成組件(component)贮缕,然后像插入普通 HTML 標(biāo)簽一樣辙谜,在網(wǎng)頁中插入這個組件。

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 方法蜕琴,用于輸出組件。

注意

  • 組件類的第一個字母必須大寫宵溅。
  • 組件類只能包含一個頂層標(biāo)簽凌简。

組件的屬性(props)

我們可以通過this.props.xx的形式獲取組件對象的屬性,對象的屬性可以任意定義恃逻,但要避免與JavaScript關(guān)鍵字沖突雏搂。

遍歷對象的屬性:

this.props.children會返回組件對象的所有屬性。
React 提供一個工具方法 React.Children 來處理 this.props.children 寇损。我們可以用 React.Children.mapReact.Children.forEach 來遍歷子節(jié)點凸郑。
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

組件的屬性可以接受任意值矛市,字符串芙沥、對象、函數(shù)等等都可以浊吏。有時而昨,我們需要一種機(jī)制,驗證別人使用組件時卿捎,提供的參數(shù)是否符合要求配紫。
組件類的PropTypes屬性,就是用來驗證組件實例的屬性是否符合要求午阵。

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

上面的Mytitle組件有一個title屬性躺孝。PropTypes 告訴 React享扔,這個 title 屬性是必須的,而且它的值必須是字符串≈才郏現(xiàn)在惧眠,我們設(shè)置 title 屬性的值是一個數(shù)值。

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設(shè)置秀存,可以查看官方文檔
此外羽氮,getDefaultProps 方法可以用來設(shè)置組件屬性的默認(rèn)值或链。

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節(jié)點)

組件并不是真實的 DOM 節(jié)點档押,而是存在于內(nèi)存之中的一種數(shù)據(jù)結(jié)構(gòu)澳盐,叫做虛擬 DOM (virtual DOM)。只有當(dāng)它插入文檔以后令宿,才會變成真實的 DOM 叼耙。根據(jù) React 的設(shè)計,所有的 DOM 變動粒没,都先在虛擬 DOM 上發(fā)生筛婉,然后再將實際發(fā)生變動的部分,反映在真實 DOM上革娄,這種算法叫做 DOM diff 倾贰,它可以極大提高網(wǎng)頁的性能表現(xiàn)。

但是拦惋,有時需要從組件獲取真實 DOM 的節(jié)點匆浙,這時就要用到 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 的子節(jié)點有一個文本輸入框首尼,用于獲取用戶的輸入。這時就必須獲取真實的 DOM 節(jié)點言秸,虛擬 DOM 是拿不到用戶輸入的软能。為了做到這一點,文本輸入框必須有一個 ref 屬性举畸,然后 this.refs.[refName] 就會返回這個真實的 DOM 節(jié)點查排。
需要注意的是,由于 this.refs.[refName] 屬性獲取的是真實 DOM 抄沮,所以必須等到虛擬 DOM 插入文檔以后跋核,才能使用這個屬性岖瑰,否則會報錯。上面代碼中砂代,通過為組件指定 Click 事件的回調(diào)函數(shù)蹋订,確保了只有等到真實 DOM 發(fā)生 Click 事件之后,才會讀取 this.refs.[refName] 屬性刻伊。
React 組件支持很多事件露戒,除了 Click 事件以外,還有 KeyDown 捶箱、Copy智什、Scroll 等,完整的事件清單請查看官方文檔讼呢。

心得:ref屬性在開發(fā)中使用頻率很高撩鹿,使用它你可以獲取到任何你想要獲取的組件的對象,有個這個對象你就可以靈活地做很多事情悦屏,比如:讀寫對象的變量,甚至調(diào)用對象的函數(shù)键思。

state

上文講到了props础爬,因為每個組件只會根據(jù)props 渲染了自己一次,props 是不可變的吼鳞。為了實現(xiàn)交互看蚜,可以使用組件的 state 。this.state 是組件私有的赔桌,可以通過getInitialState()方法初始化供炎,通過調(diào)用 this.setState() 來改變它。當(dāng) state 更新之后疾党,組件就會重新渲染自己音诫。
render() 方法依賴于 this.props 和 this.state ,框架會確保渲染出來的 UI 界面總是與輸入( this.props 和 this.state )保持一致雪位。

初始化state

通過getInitialState()方法初始化state竭钝,在組件的生命周期中僅執(zhí)行一次,用于設(shè)置組件的初始化 state 雹洗。

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

更新 state

通過this.setState()方法來更新state香罐,調(diào)用該方法后脆荷,React會重新渲染相關(guān)的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 方法用于定義初始狀態(tài)搀菩,也就是一個對象螃成,這個對象可以通過 this.state 屬性讀取旦签。當(dāng)用戶點擊組件查坪,導(dǎo)致狀態(tài)變化,this.setState 方法就修改狀態(tài)值顷霹,每次修改以后咪惠,自動調(diào)用 this.render 方法,再次渲染組件淋淀。

心得:由于 this.props 和 this.state 都用于描述組件的特性遥昧,可能會產(chǎn)生混淆。一個簡單的區(qū)分方法是朵纷,this.props 表示那些一旦定義炭臭,就不再改變的特性,而 this.state 是會隨著用戶互動而產(chǎn)生變化的特性袍辞。

參考

React's official site
React on ES6+

About

本文出自《React Native學(xué)習(xí)筆記》系列文章鞋仍。
了解更多,可以關(guān)注我的GitHub
@http://jiapenghui.com

推薦閱讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末威创,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子谎懦,更是在濱河造成了極大的恐慌肚豺,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件界拦,死亡現(xiàn)場離奇詭異吸申,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)享甸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門截碴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蛉威,你說我怎么就攤上這事日丹。” “怎么了瓷翻?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵聚凹,是天一觀的道長。 經(jīng)常有香客問我齐帚,道長妒牙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任对妄,我火速辦了婚禮湘今,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘剪菱。我一直安慰自己摩瞎,他們只是感情好拴签,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著旗们,像睡著了一般蚓哩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上上渴,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天岸梨,我揣著相機(jī)與錄音,去河邊找鬼稠氮。 笑死曹阔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的隔披。 我是一名探鬼主播赃份,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奢米!你這毒婦竟也來了抓韩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鬓长,失蹤者是張志新(化名)和其女友劉穎园蝠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痢士,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年茂装,在試婚紗的時候發(fā)現(xiàn)自己被綠了怠蹂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡少态,死狀恐怖城侧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情彼妻,我是刑警寧澤嫌佑,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站侨歉,受9級特大地震影響屋摇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜幽邓,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一炮温、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧牵舵,春花似錦柒啤、人聲如沸倦挂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽方援。三九已至,卻和暖如春涛癌,著一層夾襖步出監(jiān)牢的瞬間犯戏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工祖很, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留笛丙,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓假颇,卻偏偏與公主長得像胚鸯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子笨鸡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容