ReactJS和ReactNative

两者区别比较

IMAGE

  • 最重要的区别莫过于是控件方面的区别,对应的分别是对应平台的组件

IMAGE

  • ReactNative提供转化的桥梁

规范/规则

借鉴与XHTML

  1. 开始和结束标签配对
    <组件>ooxx</组件>
  2. 无内容的组件标签应写为自封闭形式
    <组件></组件> 应写为 <组件 />
  3. 可自定义属性,字符串值应使用双引号,其他值用{}括起来

    1
    <Person age={30} sex=“male” married={true} />
  4. 布尔属性可省略值

    1
    <Person married /> 等价于 <Person married={true} />
  5. Render(渲染)必须是单一节点
    IMAGE

  6. 空值会被自动忽略掉

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <div />
    <div></div>
    <div>{false}</div>
    <div>{null}</div>
    <div>{undefined}</div>
    <div>{true}</div>
    // 技巧 显示和隐藏组件
    <View>
    { showWarning && <Text>FBI warning</Text> }
    </View>
  7. 组件必须已大写开头
    IMAGE

  8. 文本必须写在Text的组件内
    IMAGE
  9. 注释的写法
    IMAGE
  10. 只能嵌入表达式
    IMAGE

初识React组件化开发

在线模拟器

练习基础的模拟器

示例一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 导入开发所需要的库
import React, { Component } from 'react'
import {
AppRegistry,
StyleSheet,
Text,
View,
} from 'react-native'
// Class类中会默认带有props,可以进行调用获取
class GoodMorning extends Component {
static defaultProps = {
name: 'somebody'
}
static propTypes = {
name: React.propTypes.string, // 约定需要的类型(为字符串)
}
render() {
return (
// 结构式语法
<Text>Good morning, {this.props.name}!</Text>
)
}
}
// Method中必须要手动去指定一下
// 如果的这里写了asd那么下面也要改成asd
// 如果这边有两个参数,默认是取第一个参数去取值
const GoodEvening = (props) => {
return (
<Text>Good evening, {props.name}</Text>
)
}
// 生命一个组件 App是名字
class App extends Component {
render() {
return (
<View>
<GoodMorning name="Sir" />
<GoodEvening name="Madam" />
</View >
)
}
}
AppRegistry.registerComponent('App', () => App)
  • 属性使用小结
    • 在类中,属性为默认配置,不需要去写,
    • 在方法中,属性要自己去声明,默认取第一个参数当做是属性的调用类
    • 在使用属性的时候,必须加入大括号,才可以进行调用
  • defaultProps 是用来设置属性的默认值的。
  • propTypes 是用来约束设置的属性的类型的,这个只在开发阶段有效,发布阶段会被自动移除

变量作用于

  • 函数内的局部变量,只能函数内读写,函数运行完后销毁(闭包除外)
  • class内的成员变量,在单个class的实例内读写,实例销毁时一并销毁
    • 使用时不要忘记this.
  • class内的静态成员变量,在所有class的实例内共享,不会自动销毁
    • 其他模块可通过此class访问(类public)
  • class外的变量,在所有class的实例内共享(公有),不会自动销毁
    • 除非明确export,否则其他模块不可访问(类private)
  • global全局变量,任何地方可读写(类浏览器的window),不会自动销毁
    • global.test = 1;则之后的任何地方可alert(global.test)或alert(test)

各种变量的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
global.d = 0;// 全局变量
const c = [1,2,3];// 在当前文件都可以访问
class GoodMorning extends Component {
// 成员变量
// 推荐写法
a = 1 // 成员变量写法,注意没有var或者let
// 并不推荐的写法
constructor(props) { // 构造函数
super(props); // 照抄即可,不可省略
this.a = 1;
}
// 静态变量 可以直接通过类名来访问,GoodMorning.defaultProps
static b = 2;
render() {
return (
<Text>Good morning, {this.props.name}!</Text>
)
}
method1(){
// 因为是实例的成员变量,所有加入this才可以使用
this.a;
}
}

示例二,使用map进行列表的循环创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import React, { Component } from 'react'
import {
AppRegistry,
StyleSheet,
Text,
View,
} from 'react-native'
class GoodMorning extends Component {
render() {
return (
<Text>Good morning, {this.props.name}!</Text>
)
}
}
const names = ['name1', 'name2', 'name3','name4']
const GoodEvening = (props) => {
return (
<Text>Good evening, {props.name}</Text>
)
}
class App extends Component {
render() {
return (
<View>
{
// 因为虚拟DOM的需要比较差异,使用key方便DOM进行差异的比较,key直接放在直接容器上面
names.map(name => <GoodMorning key={name} name={name} />)
}
</View >
)
}
}
AppRegistry.registerComponent('App', () => App)

示例三,点赞示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import React, { Component } from 'react'
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
} from 'react-native'
class App extends Component {
state = {
likes: 0,
};
onPress = () => {
const { likes } = this.state;
this.setState({
likes: likes + 1,
});
};
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={this.onPress}>
<Image
style={styles.image}
source={{
uri: 'https://github.com/facebook/react-native/blob/master/Examples/UIExplorer/js/Thumbnails/like.png?raw=true',
}}
/>
</TouchableOpacity>
<Text>{this.state.likes}</Text>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
image: {
width: 65,
height: 65,
},
})
AppRegistry.registerComponent('App', () => App)

总结

  • 一切界面的变化都是因为state变化而引起的
  • 但是state的修改必须通过setState进行修改
  • 直接通过修改属性值是无效的,例如this.state.likes = 100;这样的直接赋值修改是无效的
  • setState是一个merge合并操作,只修改指定的属性,不影响其他属性
  • setState是一个异步操作,修改之后并不能马上修改生效。

    • 比如说在setState之后马上运行alert,进行数字的显示,这个时候是错的
      1
      2
      3
      4
      5
      6
      7
      8
      // 错误示例
      onPress = () => {
      const { likes } = this.state;
      this.setState({
      likes: likes + 1,
      });
      alert(this.state.like);
      };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 正确示例
    onPress = () => {
    const { likes } = this.state;
    const newLikes = likes + 1;
    this.setState({
    likes: newLikes,
    });
    alert(newLikes);
    };

为什么要引入State的概念

IMAGE
如图所示,虚拟DOM的修改只是一个增量更新,比较得出前和后的差异,计算出diff,然后去重新渲染差异部分
IMAGE
IMAGE
Key的使用方便了DOM计算出差异部分,对差异部分可以进行更方便的比较。

参考链接

JSX

Introducint JSX
JSX In Depth