對于沒JS以及React開發(fā)經(jīng)驗(yàn)的人(比如我T_T),感覺還是需要簡單了解下React Native所應(yīng)用到的最基礎(chǔ)的JS及React知識,才能更近一步地進(jìn)行React Native開發(fā)。
一、JavaScript基礎(chǔ)
1. 什么是JavaScript?
JS是一個(gè)輕量級的,解釋型的講函數(shù)視為一級公民的程序設(shè)計(jì)語言。他是一種基于原型的多范式動態(tài)腳本語言,支持面向?qū)ο螅钍骄幊毯秃瘮?shù)式編程。
JavaScript的標(biāo)準(zhǔn)是 ECMAScript,React Native的語法是基于ECMAScript 6,簡稱ES6.(下面文章內(nèi)容主要是以ES6為標(biāo)準(zhǔn)介紹)
JS的組成:
a) 核心(ECMAScript):描述了該語言的語法和基本對象。擔(dān)當(dāng)?shù)氖且粋€(gè)翻譯的角色;是一個(gè)解釋器;幫助計(jì)算機(jī)來讀懂我們寫的程序;實(shí)現(xiàn)加減乘除, 定義變量;
b) 文檔對象模型(DOM):描述了處理網(wǎng)頁內(nèi)容的方法和接口。文檔指的就是網(wǎng)頁;把網(wǎng)頁變成一個(gè)JS可以操作的對象;給了JS可以操作頁面元素的能力;
c) 瀏覽器對象模型(BOM):描述了與瀏覽器進(jìn)行交互的方法和接口。給了JS操作瀏覽器的能力;
2. JS的基礎(chǔ)知識
1) 聲明變量,常量
- var 聲明變量,可以在聲明的時(shí)候初始化為一個(gè)值
- let 聲明塊范圍局部變量,可以在聲明的時(shí)候初始化一個(gè)值
- const 聲明一個(gè)只讀常量(和let一樣只在塊級作用域之內(nèi)有效)
命名規(guī)范:命名要以數(shù)字字母下劃線開頭 。
注意點(diǎn):
- JS是大小寫敏感的
- JS是一個(gè)動態(tài)類型語言(dynamically typed language)中,所以變量不需聲明類型,必要的時(shí)候自動轉(zhuǎn)換
舉例:
var mainText = "稀飯"
var subText = "歡迎閱讀"
調(diào)用和顯示(在render函數(shù)中返回):
return (
<View style={styles.container}>
<Text style={styles.welcome}>
{mainText}
</Text>
<Text style={[styles.instructions, {backgroundColor: 'green'}]}>
{subText}
</Text>
</View>
);
常量可以看到index.ios.js文件最下面有類似,styles就是一個(gè)常量:
const styles = StyleSheet.create({....
常量在聲明的時(shí)候,必須初始化。
在JS中,{} 大括號,表示定義一個(gè)對象,大部分情況下要有成對的屬性和值,或是函數(shù)。
1){mainText}代表一個(gè)JS對象,在<Text>顯示mainText的內(nèi)容而不是現(xiàn)實(shí)'mainText'字符串。
2)style={[styles.instructions, {backgroundColor: 'green'}]}中,{[...]}為一個(gè)數(shù)組對象,styles.instructions和{backgroundColor: 'green'}均表示一個(gè)JS對象,為數(shù)組元素。
2) 流程控制
- if,else
- switch
- for
- while
- break
- continue
這個(gè)各個(gè)語言大同小異, 特殊點(diǎn):JS中的Switch Case中可以是String
3) 注釋
// 這是一個(gè)單行注釋.
/* 這是一個(gè)多行注釋。
它可以是任意長度,
你可以在這里隨便寫什么。
*/
4) Promises
** JS本身是單線程的語言,它要實(shí)現(xiàn)異步都是通過回調(diào)函數(shù)來實(shí)現(xiàn)的。**
從ES6開始,JS中引入了Promises來處理異步和延遲操作,在React Native的網(wǎng)絡(luò)請求中是很常見的。
Promises交互主要通過它的then方法,then方法接受一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)接受執(zhí)行成功的返回值或執(zhí)行失敗的錯(cuò)誤原因,錯(cuò)誤原因一般是Error對象。需要注意的是,then方法執(zhí)行的返回值是一個(gè)Promise對象,而then方法接受的回調(diào)函數(shù)的返回值則可以是任意的JavaScript對象,包括Promises。
例子(簡單get網(wǎng)絡(luò)請求):
fetch(url)
.then((response) => response.text())
.then((responseText) => {
callback1(JSON.parse(responseText));
})
.catch((error) => {
callback2(JSON.parse(error));
})
.done();
}
一個(gè)promise有以下幾種狀態(tài):
- pending,最初的狀態(tài)
- fulfilled,執(zhí)行成功
- rejected,執(zhí)行出錯(cuò)
- settled,執(zhí)行結(jié)束了,失敗(rejected)或者成功(fulfilled)
控制圖如下:
目前對promise的理解還停留在網(wǎng)絡(luò)請求以及在與原生交互的應(yīng)用上。
這里有一篇推薦的文章,寫得像小說一樣去理解promise,讀讀也不錯(cuò):
ES6 JavaScript Promise的感性認(rèn)知
也有正常些的文章:初識JavaScript Promises
5) 函數(shù)
函數(shù)的定義如下,由function關(guān)鍵字聲明,在()添加輸入,輸入不需要聲明類型
//在class外,這樣的方法是定義在全局的
function globalFunction(input){
console.log(input);
}
//在class內(nèi),當(dāng)在類中定義的時(shí)候,不需要funciton關(guān)鍵字
//通過this.functionName來訪問
var mainText = "點(diǎn)擊屏幕任意位置"
class JSReactBasics extends Component {
render() {
return (
<TouchableHighlight
onPress={() => this.backgorundClicked()}
underlayColor = '#ddd'
style = {styles.container}
>
<Text style={styles.welcome}>{mainText}</Text>
</TouchableHighlight>
);
}
backgorundClicked(){
console.log("類中的方法");
}
}
6) 箭頭函數(shù)(Arrow functions)
箭頭函數(shù)=>無疑是ES6中最受關(guān)注的一個(gè)新特性了,通過它可以簡寫 function 函數(shù)表達(dá)式,你也可以在各種提及箭頭函數(shù)的地方看到這樣的觀點(diǎn)——“=> 就是一個(gè)新的 function”。
onPress={() => this.backgorundClicked()}
這里onPress是一個(gè)函數(shù)類型(在JS中,函數(shù)本身也是一種類型)。這其實(shí)是JS中的箭頭函數(shù),他提供了一種更簡潔的函數(shù)表達(dá)方式。
var a2 = a.map(function(s){ return s.length });
var a3 = a.map( (s) => s.length );
console.log(a2);
console.log(a3);
可以看到兩個(gè)log的內(nèi)容是一樣的。(s)用來描述參數(shù),=>后的表示方法的執(zhí)行體。學(xué)過Swift的童鞋,會發(fā)現(xiàn)和Swift的必包很像。
注意:
this,在一個(gè)類中的不同地方,比如閉包函數(shù)中,this的指向并不都是這個(gè)類的實(shí)例。(經(jīng)常出問題的地方,需不需要.bind(this))
普通函數(shù).bind(this) 來把內(nèi)部函數(shù)中的 this 綁定到了外部函數(shù)去。
箭頭函數(shù)里的this還是原來的this,不需要額外綁定。
7) 模板字符串
ES6 中引進(jìn)的一種新型的字符串字面量語法 - 模板字符串。書面上來解釋,模板字符串是一種能在字符串文本中內(nèi)嵌表示式的字符串字面量。簡單來講,就是增加了變量功能的字符串。
模板字符串使用反引號`來代替普通字符串中的用雙引號和單引號。模板字符串可以包含特定語法(${expression})的占位符。占位符中的表達(dá)式和周圍的文本會一起傳遞給一個(gè)默認(rèn)函數(shù),該函數(shù)負(fù)責(zé)將所有的部分連接起來。
var name = '丁香醫(yī)生';
var desc = '丁香醫(yī)生是面向大眾的科普性健康類網(wǎng)站';
//Before ES6 字符串拼接
var html = function(name, desc){
var tpl = '公司名:' + name + '\n'+
'簡介:'+ desc;
return tpl;
}
//ES6 字符串拼接
var html = `公司名:${name}
簡介:${desc}`;
3. 數(shù)據(jù)結(jié)構(gòu)和類型
1) 基本數(shù)據(jù)類型:
Boolean,布爾值,true或者false
null,一個(gè)表明null的特殊關(guān)鍵字,注意JS中大小寫敏感,null和NULL是完全不同的東西
undefined.變量未定義的屬性 (兩種情況:1是真的沒有定義, 2是雖然定義了,但沒有賦值;)
Number,數(shù)字
String,字符串
**Symbol **,ES6中新增的,唯一不可變的
Object 對象是一個(gè)復(fù)合類型,它是由一組基本類型組成的;如:div,它是一個(gè)對象,它有id,width等特性,它的id是string的,width是number的;
以下值在JS中是會識別為false:
- false
- undefined
- null
- 0
- NaN
- 空字符串 ("")
2) 變量類型轉(zhuǎn)換
檢測變量類型: typeof()
- parseInt():從字符串中提取數(shù)字;
- NaN:not a number;
i. NaN 和任何數(shù)計(jì)算 都是NaN;
ii. NaN 不與任何值相等,包括它自身;要比較需要使用方法isNaN(); - 顯性類型轉(zhuǎn)換:
i. parseInt()/ parseFloat();
ii. NaN 的意義和檢測:
意義:not a number;
檢測:isNaN(); - 隱式類型轉(zhuǎn)換:
i. "==" ,就是隱式轉(zhuǎn)換,它會先把兩邊的東西轉(zhuǎn)成一樣的類型,然后再進(jìn)行比較;
ii. 減法、乘法、除法 也會進(jìn)行自發(fā)的隱式轉(zhuǎn)換;只有加號不可以;
3) 數(shù)組
可以由以下三種方式創(chuàng)建數(shù)組,訪問數(shù)組的方式還是通過角標(biāo)來訪訪問:
var a = ["1","2","3","4"];
var b = new Array("1","2","3","4")
var c = Array("1","2","3","4")
console.log(a[1]);
數(shù)組有一些方便的方法,例如合并,排序,檢索等,可以在MDN上找到
4) 字典Maps(相當(dāng)于iOS中的NSDictionary)
var map = {"key1":"value1","key2":"value2"}
var map = {"key1":"value1","key2":"value2"}
map["key4"] = "value4"
console.log(map["key1"])
console.log(map["key4"])
5) 對象
JS中的對象的屬性可以不先聲明,而在運(yùn)行時(shí)候動態(tài)添加,例如:
var obj = new Object()
obj.name = "1234"
console.log(obj.name);
所以,在React Native中,寫代碼的時(shí)候,存儲數(shù)據(jù)直接this.propertyName =即可
4. JavaScript是基于原型的面對象語言
理解這一點(diǎn),對使用JS開發(fā)還是比較重要的。
像Java,Objective C,C++都是基于類的面向?qū)ο笳Z言。
面向?qū)ο笳Z言有兩個(gè):
- 基于類的面向?qū)ο笳Z言主要有兩個(gè)概念
- 類(class),定義了一組具有某一類特征的事務(wù)。類是抽象的,比如鳥類
- 實(shí)例(instance),實(shí)體是類的實(shí)體話提現(xiàn),比如一只鳥
- 基于原型的面向?qū)ο?/strong>
- 基于原型的面向?qū)ο笳Z言并不存在這種區(qū)別,基于原型的面向?qū)ο笳Z言所有的都是對象。基于原型的面向?qū)ο笳Z言有一個(gè)概念叫做原型對象,古代有一種東西叫做活字印刷術(shù),那一個(gè)個(gè)字的模版就是這里的原型對象。
React Native引入了基于類的面向?qū)ο缶幊谈拍睿@個(gè)在后面講解React基礎(chǔ)的時(shí)候來介紹
通過比較Java和JS可以了解二者的區(qū)分
|基于類的(Java)|基于原型的(JavaScript)|
| : ------: | : ------: |
|類和實(shí)例是不同的事物。|所有對象均為實(shí)例。|
|通過類定義來定義類;通過構(gòu)造器方法來實(shí)例化類。|通過構(gòu)造器函數(shù)來定義和創(chuàng)建一組對象。|
|通過 new 操作符創(chuàng)建單個(gè)對象。|相同。|
|通過類定義來定義現(xiàn)存類的子類,從而構(gòu)建對象的層級結(jié)構(gòu)。|指定一個(gè)對象作為原型并且與構(gòu)造函數(shù)一起構(gòu)建對象的層級結(jié)構(gòu)|
|遵循原型鏈繼承屬性。|構(gòu)造器函數(shù)或原型指定初始的屬性集。允許動態(tài)地向單個(gè)的對象或者整個(gè)對象集中添加或移除屬性。|
二、React基礎(chǔ)
1. 什么是React?
A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES(一個(gè)JavaScript的用來創(chuàng)建界面的庫)
通過名字就可以看出來,ReactNative是基于React來寫的支持編寫原生App的框架。
2. React的基礎(chǔ)知識
1) React
React是整個(gè)React框架的入口
2) React.Component
Component是React類的基類,類似于iOS的UIView和Android的View,React和React native都定義了很多方便的子類來給開發(fā)者使用。
3) React.createClass
創(chuàng)建一個(gè)Component
4) Component 相關(guān)對象方法
render
調(diào)用React.createClass或者讓一個(gè)類繼承自class JSReactBasics extends Component都是需要提供render函數(shù)的。這個(gè)函數(shù)返回一個(gè)根的視圖,用來渲染實(shí)際的Component可視部分,如下:
render() 中 返回的的 JSX 模板需要一個(gè)根元素包裹起來
render() {
return (
<TouchableHighlight
onPress={() => this.backgorundClicked()}
underlayColor = '#ddd'
style = {styles.container}
>
<Text style={styles.welcome}>{mainText}</Text>
</TouchableHighlight>
);
}
getInitialState()
在Component被加載之前調(diào)用一次,這個(gè)方法的返回值回被設(shè)置為this.state
Tips:這個(gè)方法只能在用React.createClass創(chuàng)建的時(shí)候使用,例如,在我們示例代碼中,加入一個(gè)方法
getInitialState(){
return {key:"value"}
}
getDefaultProps()
在Class 創(chuàng)建的時(shí)候,調(diào)用一次,這個(gè)方法在調(diào)用的時(shí)候,任何實(shí)例還沒有被創(chuàng)建。還有一點(diǎn)要注意,這個(gè)方法返回的任何Object 對象,在各個(gè)實(shí)例中是共享的,而不是每個(gè)實(shí)例一個(gè)copy。
5) statics
statics對象,用來定義Components可以調(diào)用的靜態(tài)方法,例如
var MyComponent = React.createClass({
statics: {
customMethod: function(foo) {
return foo === 'bar';
}
},
render: function() {
}
});
MyComponent.customMethod('bar'); // true
3. 組件的生命周期
個(gè)人覺得React Native最核心的概念就是組件了,因此一定需要去理清組件的運(yùn)作方式,即組件的生命周期,這樣才能更合理地去實(shí)際應(yīng)用。
因?yàn)榻M件的生命周期網(wǎng)上有好多好多類似的文章都有詳細(xì)的描述,這篇文章的內(nèi)容又已經(jīng)太多了,所以這里留下一圖一表供簡單的理解,會在下一篇文章結(jié)合ES6對組件的生命周期進(jìn)行詳細(xì)描述。
|生命周期 |調(diào)用次數(shù) |能否使用 setSate() |
|: ------:|:------:|:------:|
|defaultProps / getDefaultProps| 1(全局調(diào)用一次) | 否
|constructor / getInitialState |1 |否
|componentWillMount |1 |是
|render |>=1 |否
|componentDidMount |1 |是
|componentWillReceiveProps |>=0 |是
|shouldComponentUpdate |>=0 |否
|componentWillUpdate |>=0 |否
|componentDidUpdate |>=0 |否
|componentWillUnmount |1 |否
本文極大的參考了另外一篇文章的篇寫,自己也添加了自己的見解和進(jìn)一步的整理,感謝原文:http://blog.csdn.net/hello_hwc/article/details/51199384
這篇文章整理了下自從入門React Native之后所遇到的關(guān)于JS和React基礎(chǔ)的知識點(diǎn),還記得一開始的時(shí)候是懵噠到{{}}為啥要這樣做都完全不知道,函數(shù)也不會調(diào)用,總是有this為空,該bind的時(shí)候沒bind,不該的時(shí)候又bind了。。。等等一大堆問題,所以還是覺得先理解好一些最基本的東西才能進(jìn)行更好的開發(fā)。
正在寫React Native的學(xué)習(xí)教程ing,是一邊研究一邊編寫的,已有的成果如下:
1) React Native 簡介與入門
2) React Native 環(huán)境搭建和創(chuàng)建項(xiàng)目(Mac)
3) React Native 開發(fā)之IDE
4) React Native 入門項(xiàng)目與解析
- React Native 相關(guān)JS和React基礎(chǔ)
6) React Native 組件生命周期(ES6)
7) React Native 集成到原生項(xiàng)目(iOS)
8) React Native 與原生之間的通信(iOS)
9) React Native 封裝原生UI組件(iOS)