一、技术准备
在即将接触一项新技术的时候,应该如何入门。第一步肯定是做一下技术准备,每一项技术总是有专门的一套语言,比如 iOS 是 OC 或者 Swift,那么 RN 又是是什么呢?直接的说是 JSX,实际上就是 JS, 毕竟 JSX 是由 JS 进化过来的。就好比 OC 是由 C 语言 进化而来的一样。
那么对于语言基础,我们应该如何准备呢?下面我罗列了一个表:
- 1.语言
- 2.变量
- 3.语句
- 4.函数
- 5.对象
感觉任何技术的任何语言,只要弄明白了以上的五个点,那么就可以实战了。这个期间不用太深入,毕竟很多的理解还需要到实战中去。当然了,主要还是看个人悟性的高低。
比如我在学习 变量 的时候,对应着 iOS 开发中的变量来做对比,做了如下的总结:
首先给出代码:
<!--var 与 let-->
<script>
{
let a_a = '18';
var b_a = '220';
// 默认是 var 声明
c_a = '320';
}
// 不能访问
console.log(a_a);
// b_a c_a 均可访问
console.log(b_a);
console.log(c_a);
</script>
<!--全局变量访问-->
<script>
// 函数
function cusFunc()
{
// 能访问到 b_a 与 c_a
console.log("Hello World!" + '_' + b_a + '_' + c_a);
}
</script>
<!--变量删除-->
<script>
{
var a_d = 5;
b_d = 4;
let c_d = 7;
console.log(a_d);
a_d = 567;
delete a_d; // 无效
// a_d 可以正常使用
console.log(a_d);
console.log(b_d);
b_d = 467;
delete b_d; // 删除定义
// b_d = 679; // 这一步相当于从新定义了一个变量
// 报错
// console.log(b_d);
console.log(c_d);
c_d = 789;
console.log(c_d);
c_d = 898;
delete c_d; // 无效
// c_d 还可以正常使用
console.log(c_d);
}
</script>
<!--常量定义-->
<script>
// ES5
{
Object.defineProperty(window, "sex_5", {
value:'快来男生',
writable:false,
});
console.log(window.sex_5);
// 只读 无效 不报错
sex_5 = '快来女生';
console.log(window.sex_5);
}
// ES6
{
const sex_6 = '快来女生';
// sex_6 = '快来女生'; // 直接报错
console.log(sex_6);
}
</script>
<!--变量的前世今生-->
<script>
var e_a;
// undefined
console.log(e_a);
// 数字类型
e_a = 18;
console.log(e_a);
// 字符串类型
e_a = 'Coder';
console.log(e_a);
</script>
<!--提升效应-->
<script>
// 变量提升 打印 undefined ,不抛出异常
console.log(xxxx);
var xxxx = 999;
// 第一次定义
function xxxxFunc() {
console.log('one');
}
// d打印的是 two, 不是 One
xxxxFunc();
// 第二次定义
function xxxxFunc() {
console.log('Two');
}
</script>
<button onclick="cusFunc()">快来点我啊</button>
然后对以上的代码做总结:
1.1 var 与 let 变量
- 1 通过 var 与 let 均可定义变量。
- 2 var 属于全局变量,let 主要是限制其作用域,即局部变量。
- 3 默认(比如 c)为 window 的一个属性。
- 开发中,尽量使用 let。
1.2 变量删除
除了 window 属性,均不可删除。
1.3 常量的定义
- 1 ES5 需要借助 Object.defineProperty 来定义常量,给常量赋新值无效,但是不报错。
- 2 ES6 直接只用 const,给常量赋值无效,直接报错。
1.4 变量的前世今生
同一个变量,可以赋值于任何类型的值。
1.5 变量提升
- 可以使用后面定义的 变量,但是当前的值是 undefine。
- 同一个同名函数的定义,以最后一个定义的为准。
1.6 异同于 iOS(OC & Swift)
- 1.var 与 let 仅用于 Swift 中,然而在 Swift 中的 let 代表的是一个常量定义以及可变与不可变之分,与作用域无关。同时 Swift 的变量定义必须要在定义的时候指定其类型,否则报错。
- 2.iOS 不可以 delete 变量,但是超出作用域就无效。其作用域由定义的位置与括号决定。
- 3.iOS 中同一个变量只能有一种类型。
以上是我在做 RN 之前对变量的总结,当然其它的小知识点也是类似。
二、创建RN新项目
终端命令:
react-native init HGDev
使用 Webstorm 将 HGDev 打开。
对于初学者来说,只用在乎 App.js 与 index.js 这两个文件即可。
- index.js 类似 iOS 中的 main.m 文件。
- App.js 类似 iOS 中的 AppDelegate.m 文件。
三、App.js 的简单介绍
完整内容如下:
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
// 组件的导入,其中包括系统组件与自定义组件的导入
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View
} from 'react-native';
// 定义了一个常量字符串, 通过 Platform 来判断在 iOS 与 Android上返回不同的值.
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
// 这个 Props 暂时理解不是太清晰
type Props = {};
// 通过 class 定义一个组件, 在 RN 中出了使用 class, 还能通过函数(function)
export default class App extends Component<Props> {
// 界面渲染方法
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
{instructions}
</Text>
</View>
);
}
}
// 样式定义
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,
},
});
以上的代码很简单,我也初略的添加了一点注释。总共分成4个部分:
- 1.组件导入,包括系统组件与自定义组件,关键字: import 与 from。
- 2.常量定义, 比如 const instructions 与 type props。
- 3.组件定义,关键字有:export default class extends。
- 4.定义样式 StyleSheet。
四、一个简单的例子
现在直接在 App.js 中修改,主要使用到的组件为系统的 FlatList。
具体代码如下:
// 导入组件
import React from 'react'
import {
View,
Text,
StyleSheet,
FlatList,
TouchableOpacity,
Image
} from 'react-native'
// 定义组件
class HGHomeContainer extends React.Component {
// item 的点击事件
_itemPress (item) {
alert(item.title);
}
// cell 的组件
_rendeItem(item) {
return (
<TouchableOpacity
key = {item.index}
style = {styles.itemStyle}
onPress = {() => {item.item.func(item.item)}}
>
<Image
source={require('../sources/home/love.png')}
style = {styles.itemImageStyle}
/>
<View style = {styles.itemRightContentStyle}>
<Text style={{marginVertical: 5}}>{item.item.title}</Text>
<Text style={{marginVertical: 5}}>{item.item.des}</Text>
</View>
<Image
source = {require('../sources/home/forward.png')}
resizeMode={'center'}
/>
</TouchableOpacity>
);
}
// 当前组件的渲染函数
render(){
// 数据
let datas = [];
for (let i=0; i<100; i++) {
datas.push({title:('标题' + i), key:(i + ''), des:('描述' + i), func:this._itemPress})
}
return (
<View style={styles.container}>
<FlatList
data = {datas}
renderItem = {this._rendeItem}
/>
</View>
);
}
}
// 定义样式
const styles = StyleSheet.create({
container: {
flex:1,
marginTop:30,
},
itemStyle:{
flexDirection:'row',
alignItems:'center',
borderBottomWidth:1,
borderBottomColor:'#E6E6E6',
marginHorizontal: 10,
marginVertical: 5,
paddingBottom:10,
},
itemRightContentStyle:{
justifyContent:'space-between',
flex:1,
marginLeft:10,
},
itemImageStyle: {
backgroundColor:'yellow',
// resizeMode:'stretch',
width:60,
height:60,
}
});
// 导出组件, 作为默认
export default HGHomeContainer;
这个功能主要使用的技术点是 FlatList 组件的使用, 与 ** StyleSheet** 中的 Flex 布局。
这个功能很简单,但是对于初学者来说先弄明白了,显得很重要。其实这些在官网上都有介绍。但是,像 FlatList 在官网上的,有两个例子:一个简单得根本就学不到什么东西,然后接下来给了一个很强悍的例子,强悍的不知所云,只能是自己通过各种的上网查阅。
对于 Flex 布局也是,网上也有很多的额介绍,并且介绍得都很专业,专业得让初学者根本不知道应该如何实战,很少找到一个实际的例子。对于 Flex 布局,参考我上面的例子,再结合下面的这句话,应该理解得就差不多了。
flex:1 表示当前组件可以占满父视图所剩余的空间。 如果当前组件的兄弟组件也带有 flex 属性,那么会按照具体的数字作为比例进行显示。
以上的 所剩余 的意思是排除那些有固定尺寸的组件所占据的空间。
四、项目结构
可以花一两天的时间学习一下:React Navigation.基本上就能对项目结构的搭建有所了解,然后开工进项目吧。
对于项目的搭建,我尝试着弄了一个小 Demo。现在大致的目录结构如下: