react_node.js开发实战

Posted by アライさん on 2022年09月16日

一、基础知识(杂)

需要安装

node、yarn或npm(包管理器)、(也可以使用brew安装node)
查询版本

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
52
53
54
55
56
57
58
59
60
61
62
63
node --version
npm --version
brew --version
```
使用n或者nvm,可以在一台电脑上切换管理不同的node版本。
nvm(https://github.com/nvm-sh/nvm)
n(https://github.com/tj/n)


## yarn与npm常用命令
npm通过命令后加-g参数实现全局命令。
yarn通过命令前加global实现全局命令。
```shell
# 安装yarn
brew install yarn

# 初始化node项目,生成package.json
npm init -y
yarn init

# 查看本地安装目录(全局项目命令加上 -g)
npm root

# 安装本地依赖包
npm install

# 安装项目依赖包,并保存到package.json
npm install --save
yarn add

# 安装项目开发依赖包,并保存到package.json
npm install --save-dev
yarn add --dev

# 更新本地依赖包
npm update
yarn upgrade

# 查看本地依赖包
npm ls
yarn list

# 卸载本地依赖包
npm uninstall
yarn remove

# 查看依赖包信息
npm info

# 执行scripts配置
npm run
```

使用cnpm,改用淘宝源。
```shell
npm install -g cnpm --registry=https://registry.npm.taobao.org
```

使用其他镜像源
```shell
npm install -g nrm
nrm ls
nrm use cnpm

yarn替换npm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
brew install yarn
yarn --version
yarn init
yarn add
```

## npx是npm自带的包执行器
npx让npm中的命令行和其他可执行文件在使用上更简单。
```shell
npx --version

# ./node_modules/.bin/mocha --version
# 上面这条npm命令可以简化为如下命令
npx mocha --version

node允许跨域的基本设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
app.all('*', function (req, res, next) {
//允许跨域的域名,*代表允许任意域名跨域
res.header('Access-Control-Allow-Origin', '*');
//允许跨域的请求头
res.header('Access-Control-Allow-Headers', 'content-type');
//允许跨域的请求方法
res.header('Access-Control-Allow-Methods', 'DELETE,PUT,POST,GET,OPTIONS');
next();
});
```

## 高阶函数
```javascript
const add = x => y => x + y;

//等价于
var add = function add(x){
return function (y){
return x + y;
}
}
//返回为3
add(1)(2);



二、React

JSX

JSX需要由父标签包裹,一般使用<div>,也可以直接使用<React.Fragment><>(简写)。
JSX中所有标签都需要闭合。
使用{/*注释内容*/}做单行注释,使用/* 多行 */做多行注释。
{}括号中位JavaScript表达式。
``反引号包裹模版字符串。
null也是合法的JSX元素,但不会被渲染。可以用于三元表达式。

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
{/* 以下等同,都不会被渲染 */}
<div />
<div></div>
<div>{false}</div>
<div>{true}</div>
<div>{null}</div>
<div>{undefined}</div>
```
小写开头标签为原生标签,大写开头标签为React组件。
原生标签的class属性,换成className属性。如```<h3 className="title"></h3>```
内联的css样式,包含-的,改为驼峰写法。如```<h3 style={{fontSize:"14px"}}></h3>```
多属性传入。```const props={text:'',font:'big'} <CustomeText {...props}></CustomeText>```
JSX中无法通过return或false来阻止默认时间,需要调用preventDefault()或stopPropagation()等。


## 组件Component
```javascript
class CustomComponent extends React.Cpmponent{
constructor(props) {
super(props);
this.state={};
}
render(){
return (<div></div>);
}
}
//无状态组件
function CustomComponent(){
return (<div></div>);
}
```

## 高阶组件
```javascript
const Container = (WrappedComponent) => {
class extends React.Component {
render() {
let newProps = { status : 'ok'};
return <WrappedComponent {...this.props} {...newProps} />
}
}
}

@Container
export default class App extends React.Component {
render(){
return (
<div>hello world</div>
);
}
}
```


## 数据流(状态管理)
使用Props单向传递参数
```javascript
class Father extends React.Component {
deleteTodoItem(item){}
render(){
return (
<div>
{/* 子组件Son,通过 this.props.name 就可以获得参数。props为只读 */}
{/* 子组件调用this.props.deleteTodoItem(item)可以回调父组件方法 */}
<Son name='Jack' age={25} deleteTodoItem={this.deleteTodoItem}/>
</div>
);
}
}
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//setState可以接收现有state与props作为参数
this.setState((state,props)=>{
return {counter:state.counter + props.step};
});
```
<br>
<br>
使用redux

三大原则:
* 单一数据源
* state只读,触发action改变。
* 使用纯函数reducer执行修改,接收state和action,返回新的state进行覆盖。

<br>
<br>

**使用MobX**:
```shell
npm install --save mobx
npm install --save mobx-react
```
```javascript
import {observable,action,configure} from 'mobx';
configure({enforceActions:true});//开启严格模式,只能在action里修改状态

//定义state
class AppState {
@observable
timer = 0;

//开启了严格模式,只能在action中修改state
@action
addTimer(){
this.timer = this.timer + 1;
}
}

var appState = new AppState();
```

<br>
<br>
<br>
<br>

# 三、Node

Promise用法:
也可以使用bluebird之类第三方库来简化Promise。
自己封装:
```javascript
function getData(fileName, options) {
return new Promise(function (resolve, reject) {
fs.readFile(fileName, options, function (err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}

getData('./test.txt', { 'encoding': 'utf8' }).then(function (data) {
console.log('Data: ', data);
}).catch(function (error) {
console.log('Error:', error);
});

定时相关:

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
52
function printHello(){
console.log("Hello World!");
}

//执行一次,2秒后执行
var t1 = setTimeout(printHello,2000);
//清除Timeout定时器
clearTimeout(t1);

//每2秒执行一次,无限循环
var t2 = setInterval(printHello,2000);
//清除Interval定时器
clearInterval(t2);
```


```javascritp
console.log();
console.info();
console.warn();
console.error();

console.time('label');
//do somethings
console.timeEnd('lable');
//会自动计算,2次'lable'的时间差,输出 label:xxx ms。用于展示执行耗时。
```
<br>

**process**
process为当前Node的进程,如获取环境变量:```console.log(process.env.PATH)```

**os操作系统模块**
```javascript
var os = require("os");
console.log('系统内存:'+ os.totalmem() / 1024 / 1024 + " MB");
```

**path路径模块**
```javascript
var path = require("path");
var full_path = '/Application/';
//获取目录
console.log(path.dirname(full_path));
//获取后缀名
console.log(path.extname(full_path));
```

**net底层网络通信模块**
```javascript
var net = require("net");
//如进行TCP通信