React Native (簡(jiǎn)稱RN)是Facebook于2015年4月開源的跨平臺(tái)移動(dòng)應(yīng)用開發(fā)框架侄柔,是Facebook早先開源的UI框架 React 在原生移動(dòng)應(yīng)用平臺(tái)的衍生產(chǎn)物恨憎,目前支持iOS和安卓兩大平臺(tái)。RN使用Javascript語言切诀,類似于HTML的JSX,以及CSS來開發(fā)移動(dòng)應(yīng)用少孝,因此熟悉Web前端開發(fā)的技術(shù)人員只需很少的學(xué)習(xí)就可以進(jìn)入移動(dòng)應(yīng)用開發(fā)領(lǐng)域饿序。
一、從 ES6 開始
-
const、let 關(guān)鍵字
let:眾所周知 JavaScript 中變量默認(rèn)是全局的皂林,只存在函數(shù)級(jí)作用域朗鸠。ES6中提出 let 關(guān)鍵字,使JavaScript 也有了塊級(jí)作用域式撼。
-
const:用來定義常量童社,一旦定以后不可修改,但是可以修改屬性著隆。
const MYNAME = {foo: 'Ginger'}; MYNAME.foo = 'Zoe';
-
函數(shù)
-
箭頭函數(shù)
可以看做是一種語法糖,箭頭函數(shù)永遠(yuǎn)是匿名的let add = (a, b) => {return a + b;} // 當(dāng)后面是表達(dá)式的時(shí)候呀癣,還可以簡(jiǎn)寫成 let add = (a, b) => a + b; // 等同于 let add = function(a, b){ return a + b; } // 在回調(diào)函數(shù)中的應(yīng)用 let numbers = [1, 2, 3]; let doubleNumbers = numbers.map((number) => number * 2); // [2, 4, 6]
-
this 在箭頭函數(shù)中的使用
在對(duì)象方法的嵌套函數(shù)中美浦,this 會(huì)指向 global。let age = 2; let kitty = { age: 1, grow: function() { setTimeout(function() { console.log(++this.age); }, 100); } } kitty.grow(); // 3 // 一般的解決方法 let kitty = { age: 1, grow: function() { setTimeout(function() { console.log(++this.age); }.bind(this), 100); } } // 或者 let kitty = { age: 1, grow: function() { const self = this; setTimeout(function() { console.log(++self.age); }.bind(this), 100); } } // 有了箭頭函數(shù)這個(gè)問題就可以輕松解決了 let kitty = { age: 1, grow: function() { setTimeout(() => { console.log(++this.age); }, 100); } }
-
默認(rèn)參數(shù)函數(shù)
function desc(name = 'Ginger', age = 18){ return name + ' is ' + age + ' years old'; } desc(); //Ginger is 18 years old
-
Rest 參數(shù)
當(dāng)一個(gè)函數(shù)的最后一個(gè)參數(shù)有“…”這樣的前綴项栏,它就會(huì)變成一個(gè)參數(shù)的數(shù)組浦辨。function test(...args){ console.log(args); } test(1, 2, 3); //[1, 2, 3] function test2(name, ...args){ console.log(args); } test2('Ginger', 2, 3); //[2, 3]
?
-
-
展開操作符(“…”)
允許一個(gè)表達(dá)式在某處展開,在存在多個(gè)參數(shù)(用于函數(shù)調(diào)用)沼沈、多個(gè)元素(用于數(shù)組字面量)或者多個(gè)變量(用于結(jié)構(gòu)賦值)的地方就會(huì)出現(xiàn)這種情況流酬。
-
用于函數(shù)調(diào)用
// 之前,想讓函數(shù)把一個(gè)數(shù)組作為依次作為參數(shù)調(diào)用方法如下 function test(x, y, z) { }; var args = [1, 2, 3]; test.apply(null, args); // 有了 ES6 的展開運(yùn)算符之后 function test(x, y, z) { }; let args = [1, 2, 3]; test(...args);
-
用于數(shù)組字面量
在之前的版本中列另,想要?jiǎng)?chuàng)建含某些元素的新數(shù)組芽腾,常使用 splice、concat页衙、push.var arr1 = [1, 2, 3]; var arr2 = [4, 5, 6]; var arr3 = arr1.concat(arr2); // 使用 ES6 之后 let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let arr3 = [...arr1, ...arr2];
-
對(duì)象的展開運(yùn)算符
let mike = {name: 'mike', age: 50}; mike = {...mike, sex: 'male'}; console.log(mike); // {name: 'mike', age: 50, sex: 'male'}
-
-
模板字符串(注意不是',是`)
字符串拼接總是令人很不爽的一件事情摊滔,但是在 ES6 來臨的時(shí)代,這個(gè)痛處也被治愈了店乐。// 之前 var name = 'Ginger'; var a = 'My name is ' + Ginger + '!' // 多行 var langStory = 'This is a long story,' + 'this is a long story,' + 'this is a long story.'; // 有了 ES6 之后 let name = 'Ginger'; let a = `My name is ${name} !`; let longStory = `This is a long story, this is a long story, this is a long story`;
-
解構(gòu)賦值
-
解構(gòu)數(shù)組
let foo = ['one', 'two', 'three']; let [one, two, three] = foo; console.log(`${one}, ${two}, ${three}`); // one, two, three
-
解構(gòu)對(duì)象
let person = {name: 'Ginger', age: 18}; let {name, age} = person; console.log(`${name}, ${age}`); // Ginger, 18
-
-
類
提供了 class 這個(gè)語法糖艰躺。讓開發(fā)者可以模仿其他語言類的聲明方式。只是原型鏈方式的一種語法糖眨八。class Animal { // 構(gòu)造函數(shù) constructor (name, age) { this.name = name; this.age = age; } shout() { return `${name}, ${age}`; } // 靜態(tài)方法 static foo() { return 'here is a static method'; } } const cow = new Animal('betty', 2); cow.shout(); // betty, 2 Animal.foo(); // here is a static method class Dog extends Animal { constructor(name, age = 2, color = 'black') { // 在構(gòu)造函數(shù)中可以直接調(diào)用 spuer 方法 super(name, age); this.color = color; } shout(){ // 非構(gòu)造函數(shù)中不能直接調(diào)用 super 方法 return `${name}, ${age}, ${color}`; } }
?
模塊
在 ES6 之前腺兴,JavaScript 并沒有對(duì)模塊做出任何定義,于是先驅(qū)者們創(chuàng)造了各種各樣的規(guī)范來完成這個(gè)任務(wù)廉侧。比如 Require.js页响,CommonJS,browerify 等等伏穆。
使用 import export 關(guān)鍵字來完成模塊的導(dǎo)入和導(dǎo)出拘泞。
還可以使用 default 關(guān)鍵字來默認(rèn)導(dǎo)出。
二枕扫、再說說 React
特點(diǎn):1. 組件化陪腌;2. JSX;3. 虛擬 DOM;
-
JSX
-
JSX 不是必須的诗鸭。類似一種語法糖染簇。把標(biāo)簽型的寫法轉(zhuǎn)化成 React 提供的一個(gè)用來創(chuàng)建 ReactElement 的方法。
let app = <h1 title = "My title">this is my title</h1> // jsx轉(zhuǎn)換后的結(jié)果 let app = React.createElement('h1', {title: 'my title', 'this is my title'});
HTML 標(biāo)簽與 React 組件
HTML 標(biāo)簽第一個(gè)字母用小寫表示强岸。
React 組件第一個(gè)字母用大寫表示锻弓。
JSX 語法使用第一個(gè)字母大小寫來區(qū)分是一個(gè)普通的 HTML 標(biāo)簽還是一個(gè) React 組件。JavaScript 表達(dá)式
當(dāng)遇到{}這個(gè)表達(dá)式的情況下蝌箍,里面的代碼會(huì)被仿作 JavaScript 代碼處理青灼。
當(dāng)省略一個(gè)屬性值的時(shí)候,JSX會(huì)自動(dòng)把它的值認(rèn)為是 true妓盲。-
注釋
JSX 注釋沿用 JavaScript 的方法杂拨,需要注意的是,在子組件的位置需要用{}括起來悯衬。let component = ( <div> {/*這里是一個(gè)注釋弹沽!*/} <Headline /> </div> );
-
JSX 屬性擴(kuò)散
let props = { name: 'Ginger', age: 18 } // 用這種方式可以將 name,age 全部載入進(jìn)來 let component = <Profile {...props} /> // 值得注意的是筋粗,越靠后的屬性會(huì)覆蓋前面的屬性 let component = <Profile {...props} name='Zoe' />
-
-
React 的生命周期
實(shí)例化
首次實(shí)例化
- getDefaultProps
- getInitialState
- componentWillMount
- render
- componentDidMount
實(shí)例化完成后的更新
- getInitialState
- componentWillMount
- render
- componentDidMount
存在期
組件已存在時(shí)的狀態(tài)改變
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
銷毀&清理期
- componentWillUnmount
說明
生命周期共提供了10個(gè)不同的API策橘。
1.getDefaultProps
作用于組件類,只調(diào)用一次娜亿,返回對(duì)象用于設(shè)置默認(rèn)的
props
丽已,對(duì)于引用值,會(huì)在實(shí)例中共享暇唾。2.getInitialState
作用于組件的實(shí)例促脉,在實(shí)例創(chuàng)建時(shí)調(diào)用一次,用于初始化每個(gè)實(shí)例的
state
策州,此時(shí)可以訪問this.props
瘸味。3.componentWillMount
在完成首次渲染之前調(diào)用,此時(shí)仍可以修改組件的state够挂。
4.render
必選的方法旁仿,創(chuàng)建虛擬DOM,該方法具有特殊的規(guī)則:
- 只能通過
this.props
和this.state
訪問數(shù)據(jù) - 可以返回
null
孽糖、false
或任何React組件 - 只能出現(xiàn)一個(gè)頂級(jí)組件(不能返回?cái)?shù)組)
- 不能改變組件的狀態(tài)
- 不能修改DOM的輸出
5.componentDidMount
真實(shí)的DOM被渲染出來后調(diào)用枯冈,在該方法中可通過
this.getDOMNode()
訪問到真實(shí)的DOM元素。此時(shí)已可以使用其他類庫來操作這個(gè)DOM办悟。比如 AJAX 請(qǐng)求可以放在這里尘奏。在服務(wù)端中,該方法不會(huì)被調(diào)用病蛉。
6.componentWillReceiveProps
組件接收到新的
props
時(shí)調(diào)用炫加,并將其作為參數(shù)nextProps
使用瑰煎,此時(shí)可以更改組件props
及state
。componentWillReceiveProps: function(nextProps) { if (nextProps.bool) { this.setState({ bool: true }); } }
7.shouldComponentUpdate
組件是否應(yīng)當(dāng)渲染新的
props
或state
俗孝,返回false
表示跳過后續(xù)的生命周期方法酒甸,通常不需要使用以避免出現(xiàn)bug。在出現(xiàn)應(yīng)用的瓶頸時(shí)赋铝,可通過該方法進(jìn)行適當(dāng)?shù)膬?yōu)化插勤。在首次渲染期間或者調(diào)用了forceUpdate方法后,該方法不會(huì)被調(diào)用
8.componentWillUpdate
接收到新的
props
或者state
后革骨,進(jìn)行渲染之前調(diào)用农尖,此時(shí)不允許更新props
或state
。9.componentDidUpdate
完成渲染新的
props
或者state
后調(diào)用苛蒲,此時(shí)可以訪問到新的DOM元素卤橄。不能再該狀態(tài)下 setState 等,會(huì)造成組件死循環(huán)臂外。10.componentWillUnmount
組件被移除之前被調(diào)用,可以用于做一些清理工作喇颁,在
componentDidMount
方法中添加的所有任務(wù)都需要在該方法中撤銷漏健,比如創(chuàng)建的定時(shí)器或添加的事件監(jiān)聽器。 -
組件
先來一個(gè)簡(jiǎn)單的例子橘霎。import React from 'react'; class List extends React.Component { // 在 ES6 中不再使用getInitialState而使用constructor constructor(props) { super(props); this.state = ['a', 'b', 'c']; } render(){ return (...); } }
props 屬性
可以看做是組件的數(shù)據(jù)來源蔫浆。
要想子組件傳遞數(shù)據(jù)需要通過 props 來完成state 狀態(tài)
state 是組件內(nèi)部的屬性。
當(dāng) state 的值發(fā)生改變的時(shí)候姐叁,可以調(diào)用 this.setState 方法讓組件再次調(diào)用 render 方法瓦盛,重新渲染 UI。
state 中應(yīng)該包含組件的事件回調(diào)函數(shù)可能引發(fā) UI 更新的這類數(shù)據(jù)外潜。-
引入組件
將組件的文件引入原环,再在新的組件中加入已經(jīng)寫好的組件標(biāo)簽。import React from 'react'; import List from './list'; class Profile extends React.Component { // 在 ES6 中不再使用getInitialState而使用constructor constructor(props) { super(props); } render(){ return ( <List /> ); } }
三处窥、讓我們開始 React Native 的旅程
快速開始
參考網(wǎng)站:http://reactnative.cn/docs/0.41/getting-started.html
事先搭建好開發(fā)環(huán)境嘱吗。快速開始:react-native init HelloRN
進(jìn)入這個(gè) HelloRN 文件夾后滔驾,里面有兩個(gè)入口文件: index.ios.js index.android.js谒麦,修改入口文件內(nèi)容刷新模擬器,即可看到你寫的內(nèi)容~-
flexbox 布局
我們?cè)赗eact Native中使用flexbox規(guī)則來指定某個(gè)組件的子元素的布局哆致。Flexbox可以在不同屏幕尺寸上提供一致的布局結(jié)構(gòu)绕德。
一般來說,使用flexDirection
摊阀、alignItems
和justifyContent
三個(gè)樣式屬性就已經(jīng)能滿足大多數(shù)布局需求耻蛇。
摘自網(wǎng)上總結(jié)的很好的 flex 布局口訣圖踪蹬。(http://weibo.com/1712131295/CoRnElNkZ?ref=collection&type=comment#_rnd1488247287265)
flex1.jpg
flex2.jpg
flex3.jpg
flex4.jpg
flex5.jpg -
常用組件介紹
入口文件說明import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Text, View } from 'react-native'; // 將使用到的 react-native 組件引入 export default class reactNative extends Component { render() { return ( // View 組件相當(dāng)于 html 的 div〕巧ィ可以視作一個(gè)包裹內(nèi)容的容器延曙。 <View style={styles.container}> // 所有的文字內(nèi)容都需要被包裹在 Text 標(biāo)簽中 <Text style={styles.welcome}> Welcome to React Native! </Text> // 若要直接在組件中寫入樣式 <Text style={{textAlign: 'center'}}>。注意是 {{}} <Text style={styles.instructions}> To get started, edit index.ios.js </Text> <Text style={styles.instructions}> Double tap R on your keyboard to reload,{'\n'} Shake or press menu button for dev menu </Text> </View> ); } } // StyleSheet提供了一種類似CSS樣式表的抽象亡哄。RN 中樣式使用駝峰格式枝缔。 const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, }); AppRegistry.registerComponent('reactNative', () => reactNative); // AppRegistry是JS運(yùn)行所有React Native應(yīng)用的入口。應(yīng)用的根組件應(yīng)當(dāng)通過AppRegistry.registerComponent方法注冊(cè)自己蚊惯,然后原生系統(tǒng)才可以加載應(yīng)用的代碼包并且在啟動(dòng)完成之后通過調(diào)用AppRegistry.runApplication來真正運(yùn)行應(yīng)用愿卸。
View
類似于 html 中的 div,盒子布局截型,將內(nèi)容包裹在里面趴荸。Text
所有的文字都必須要放在 Text 標(biāo)簽中。Image
renderImages() { return ( <View> // 本地模式 <Image style={styles.icon} source={require('./icon.png')} /> // 使用網(wǎng)絡(luò)資源 <Image style={styles.logo} source={{uri: 'http://facebook.github.io/react/img/logo_og.png'}} /> </View> ); }
? 至此宦焦,關(guān)于 React Native 的基礎(chǔ)說明完成发钝。趕快開始在 index.ios.js 中涂涂畫畫吧~
-
其他常用組件
-
NavigatorIOS
該組件本質(zhì)上是對(duì) UIKit navigation 的包裝。也就是說波闹,使用 NavigatorIOS 進(jìn)行路由切換酝豪,實(shí)質(zhì)上是調(diào)用了UIKit的navigation。
navigation.jpeg TextInput
通過鍵盤將文本輸入到 app 的組件精堕。Touchable
RN 沒有像 web 開發(fā)那樣可以個(gè)元素綁定 click 時(shí)間孵淘。Text 組件中可以使用 onPress 事件綁定觸摸點(diǎn)擊事件。為了使其他組件也可以被點(diǎn)擊歹篓,提供了3個(gè)組件來做這個(gè)事情瘫证。這3個(gè)組件被稱為“Touchable類組件”。-
TarBarIOS
為切換不同頁面
TarBar.jpeg WebView
-
趕快動(dòng)手試試這些組件吧~
參考內(nèi)容:
http://reactnative.cn/docs/0.41/getting-started.html
《React 全椬椋》
《React Native 入門與實(shí)戰(zhàn)》