对于没JS以及React开发经验的人(比如我T_T),感觉还是需要简单了解下React Native所应用到的最基础的JS及React知识,才能更近一步地进行React Native开发。
一、JavaScript基础
1. 什么是JavaScript?
JS是一个轻量级的,解释型的讲函数视为一级公民的程序设计语言。他是一种基于原型的多范式动态脚本语言,支持面向对象,命令式编程和函数式编程。
JavaScript的标准是 ECMAScript,React Native的语法是基于ECMAScript 6,简称ES6.(下面文章内容主要是以ES6为标准介绍)
JS的组成:
a) 核心(ECMAScript):描述了该语言的语法和基本对象。担当的是一个翻译的角色;是一个解释器;帮助计算机来读懂我们写的程序;实现加减乘除, 定义变量;
b) 文档对象模型(DOM):描述了处理网页内容的方法和接口。文档指的就是网页;把网页变成一个JS可以操作的对象;给了JS可以操作页面元素的能力;
c) 浏览器对象模型(BOM):描述了与浏览器进行交互的方法和接口。给了JS操作浏览器的能力;
2. JS的基础知识
1) 声明变量,常量
- var 声明变量,可以在声明的时候初始化为一个值
- let 声明块范围局部变量,可以在声明的时候初始化一个值
- const 声明一个只读常量(和let一样只在块级作用域之内有效)
命名规范:命名要以数字字母下划线开头 。
注意点:
- JS是大小写敏感的
- JS是一个动态类型语言(dynamically typed language)中,所以变量不需声明类型,必要的时候自动转换
举例:
var mainText = "稀饭"
var subText = "欢迎阅读"
调用和显示(在render函数中返回):
return (
<View style={styles.container}>
<Text style={styles.welcome}>
{mainText}
</Text>
<Text style={[styles.instructions, {backgroundColor: 'green'}]}>
{subText}
</Text>
</View>
);
常量可以看到index.ios.js文件最下面有类似,styles就是一个常量:
const styles = StyleSheet.create({....
常量在声明的时候,必须初始化。
在JS中,{} 大括号,表示定义一个对象,大部分情况下要有成对的属性和值,或是函数。
1){mainText}代表一个JS对象,在<Text>显示mainText的内容而不是现实'mainText'字符串。
2)style={[styles.instructions, {backgroundColor: 'green'}]}中,{[...]}为一个数组对象,styles.instructions和{backgroundColor: 'green'}均表示一个JS对象,为数组元素。
2) 流程控制
- if,else
- switch
- for
- while
- break
- continue
这个各个语言大同小异, 特殊点:JS中的Switch Case中可以是String
3) 注释
// 这是一个单行注释.
/* 这是一个多行注释。
它可以是任意长度,
你可以在这里随便写什么。
*/
4) Promises
** JS本身是单线程的语言,它要实现异步都是通过回调函数来实现的。**
从ES6开始,JS中引入了Promises来处理异步和延迟操作,在React Native的网络请求中是很常见的。
Promises交互主要通过它的then方法,then方法接受一个回调函数,这个回调函数接受执行成功的返回值或执行失败的错误原因,错误原因一般是Error对象。需要注意的是,then方法执行的返回值是一个Promise对象,而then方法接受的回调函数的返回值则可以是任意的JavaScript对象,包括Promises。
例子(简单get网络请求):
fetch(url)
.then((response) => response.text())
.then((responseText) => {
callback1(JSON.parse(responseText));
})
.catch((error) => {
callback2(JSON.parse(error));
})
.done();
}
一个promise有以下几种状态:
- pending,最初的状态
- fulfilled,执行成功
- rejected,执行出错
- settled,执行结束了,失败(rejected)或者成功(fulfilled)
控制图如下:
目前对promise的理解还停留在网络请求以及在与原生交互的应用上。
这里有一篇推荐的文章,写得像小说一样去理解promise,读读也不错:
ES6 JavaScript Promise的感性认知
也有正常些的文章:初识JavaScript Promises
5) 函数
函数的定义如下,由function关键字声明,在()添加输入,输入不需要声明类型
//在class外,这样的方法是定义在全局的
function globalFunction(input){
console.log(input);
}
//在class内,当在类中定义的时候,不需要funciton关键字
//通过this.functionName来访问
var mainText = "点击屏幕任意位置"
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) 箭头函数(Arrow functions)
箭头函数=>无疑是ES6中最受关注的一个新特性了,通过它可以简写 function 函数表达式,你也可以在各种提及箭头函数的地方看到这样的观点——“=> 就是一个新的 function”。
onPress={() => this.backgorundClicked()}
这里onPress是一个函数类型(在JS中,函数本身也是一种类型)。这其实是JS中的箭头函数,他提供了一种更简洁的函数表达方式。
var a2 = a.map(function(s){ return s.length });
var a3 = a.map( (s) => s.length );
console.log(a2);
console.log(a3);
可以看到两个log的内容是一样的。(s)用来描述参数,=>后的表示方法的执行体。学过Swift的童鞋,会发现和Swift的必包很像。
注意:
this,在一个类中的不同地方,比如闭包函数中,this的指向并不都是这个类的实例。(经常出问题的地方,需不需要.bind(this))
普通函数.bind(this) 来把内部函数中的 this 绑定到了外部函数去。
箭头函数里的this还是原来的this,不需要额外绑定。
7) 模板字符串
ES6 中引进的一种新型的字符串字面量语法 - 模板字符串。书面上来解释,模板字符串是一种能在字符串文本中内嵌表示式的字符串字面量。简单来讲,就是增加了变量功能的字符串。
模板字符串使用反引号`来代替普通字符串中的用双引号和单引号。模板字符串可以包含特定语法(${expression})的占位符。占位符中的表达式和周围的文本会一起传递给一个默认函数,该函数负责将所有的部分连接起来。
var name = '丁香医生';
var desc = '丁香医生是面向大众的科普性健康类网站';
//Before ES6 字符串拼接
var html = function(name, desc){
var tpl = '公司名:' + name + '\n'+
'简介:'+ desc;
return tpl;
}
//ES6 字符串拼接
var html = `公司名:${name}
简介:${desc}`;
3. 数据结构和类型
1) 基本数据类型:
Boolean,布尔值,true或者false
null,一个表明null的特殊关键字,注意JS中大小写敏感,null和NULL是完全不同的东西
undefined.变量未定义的属性 (两种情况:1是真的没有定义, 2是虽然定义了,但没有赋值;)
Number,数字
String,字符串
**Symbol **,ES6中新增的,唯一不可变的
Object 对象是一个复合类型,它是由一组基本类型组成的;如:div,它是一个对象,它有id,width等特性,它的id是string的,width是number的;
以下值在JS中是会识别为false:
- false
- undefined
- null
- 0
- NaN
- 空字符串 ("")
2) 变量类型转换
检测变量类型: typeof()
- parseInt():从字符串中提取数字;
- NaN:not a number;
i. NaN 和任何数计算 都是NaN;
ii. NaN 不与任何值相等,包括它自身;要比较需要使用方法isNaN(); - 显性类型转换:
i. parseInt()/ parseFloat();
ii. NaN 的意义和检测:
意义:not a number;
检测:isNaN(); - 隐式类型转换:
i. "==" ,就是隐式转换,它会先把两边的东西转成一样的类型,然后再进行比较;
ii. 减法、乘法、除法 也会进行自发的隐式转换;只有加号不可以;
3) 数组
可以由以下三种方式创建数组,访问数组的方式还是通过角标来访访问:
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]);
数组有一些方便的方法,例如合并,排序,检索等,可以在MDN上找到
4) 字典Maps(相当于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中的对象的属性可以不先声明,而在运行时候动态添加,例如:
var obj = new Object()
obj.name = "1234"
console.log(obj.name);
所以,在React Native中,写代码的时候,存储数据直接this.propertyName =即可
4. JavaScript是基于原型的面对象语言
理解这一点,对使用JS开发还是比较重要的。
像Java,Objective C,C++都是基于类的面向对象语言。
面向对象语言有两个:
- 基于类的面向对象语言主要有两个概念
- 类(class),定义了一组具有某一类特征的事务。类是抽象的,比如鸟类
- 实例(instance),实体是类的实体话提现,比如一只鸟
- 基于原型的面向对象
- 基于原型的面向对象语言并不存在这种区别,基于原型的面向对象语言所有的都是对象?;谠偷拿嫦蚨韵笥镅杂幸桓龈拍罱凶鲈投韵?古代有一种东西叫做活字印刷术,那一个个字的模版就是这里的原型对象。
React Native引入了基于类的面向对象编程概念,这个在后面讲解React基础的时候来介绍
通过比较Java和JS可以了解二者的区分
|基于类的(Java)|基于原型的(JavaScript)|
| : ------: | : ------: |
|类和实例是不同的事物。|所有对象均为实例。|
|通过类定义来定义类;通过构造器方法来实例化类。|通过构造器函数来定义和创建一组对象。|
|通过 new 操作符创建单个对象。|相同。|
|通过类定义来定义现存类的子类,从而构建对象的层级结构。|指定一个对象作为原型并且与构造函数一起构建对象的层级结构|
|遵循原型链继承属性。|构造器函数或原型指定初始的属性集。允许动态地向单个的对象或者整个对象集中添加或移除属性。|
二、React基础
1. 什么是React?
A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES(一个JavaScript的用来创建界面的库)
通过名字就可以看出来,ReactNative是基于React来写的支持编写原生App的框架。
2. React的基础知识
1) React
React是整个React框架的入口
2) React.Component
Component是React类的基类,类似于iOS的UIView和Android的View,React和React native都定义了很多方便的子类来给开发者使用。
3) React.createClass
创建一个Component
4) Component 相关对象方法
render
调用React.createClass或者让一个类继承自class JSReactBasics extends Component都是需要提供render函数的。这个函数返回一个根的视图,用来渲染实际的Component可视部分,如下:
render() 中 返回的的 JSX 模板需要一个根元素包裹起来
render() {
return (
<TouchableHighlight
onPress={() => this.backgorundClicked()}
underlayColor = '#ddd'
style = {styles.container}
>
<Text style={styles.welcome}>{mainText}</Text>
</TouchableHighlight>
);
}
getInitialState()
在Component被加载之前调用一次,这个方法的返回值回被设置为this.state
Tips:这个方法只能在用React.createClass创建的时候使用,例如,在我们示例代码中,加入一个方法
getInitialState(){
return {key:"value"}
}
getDefaultProps()
在Class 创建的时候,调用一次,这个方法在调用的时候,任何实例还没有被创建?;褂幸坏阋⒁猓飧龇椒ǚ祷氐娜魏蜲bject 对象,在各个实例中是共享的,而不是每个实例一个copy。
5) statics
statics对象,用来定义Components可以调用的静态方法,例如
var MyComponent = React.createClass({
statics: {
customMethod: function(foo) {
return foo === 'bar';
}
},
render: function() {
}
});
MyComponent.customMethod('bar'); // true
3. 组件的生命周期
个人觉得React Native最核心的概念就是组件了,因此一定需要去理清组件的运作方式,即组件的生命周期,这样才能更合理地去实际应用。
因为组件的生命周期网上有好多好多类似的文章都有详细的描述,这篇文章的内容又已经太多了,所以这里留下一图一表供简单的理解,会在下一篇文章结合ES6对组件的生命周期进行详细描述。
|生命周期 |调用次数 |能否使用 setSate() |
|: ------:|:------:|:------:|
|defaultProps / getDefaultProps| 1(全局调用一次) | 否
|constructor / getInitialState |1 |否
|componentWillMount |1 |是
|render |>=1 |否
|componentDidMount |1 |是
|componentWillReceiveProps |>=0 |是
|shouldComponentUpdate |>=0 |否
|componentWillUpdate |>=0 |否
|componentDidUpdate |>=0 |否
|componentWillUnmount |1 |否
本文极大的参考了另外一篇文章的篇写,自己也添加了自己的见解和进一步的整理,感谢原文:http://blog.csdn.net/hello_hwc/article/details/51199384
这篇文章整理了下自从入门React Native之后所遇到的关于JS和React基础的知识点,还记得一开始的时候是懵哒到{{}}为啥要这样做都完全不知道,函数也不会调用,总是有this为空,该bind的时候没bind,不该的时候又bind了。。。等等一大堆问题,所以还是觉得先理解好一些最基本的东西才能进行更好的开发。
正在写React Native的学习教程ing,是一边研究一边编写的,已有的成果如下:
1) React Native 简介与入门
2) React Native 环境搭建和创建项目(Mac)
3) React Native 开发之IDE
4) React Native 入门项目与解析
- React Native 相关JS和React基础
6) React Native 组件生命周期(ES6)
7) React Native 集成到原生项目(iOS)
8) React Native 与原生之间的通信(iOS)
9) React Native 封装原生UI组件(iOS)