- 一. 构建项目
- 二. 先解决本地的跨域问题
- 三. 用装饰器实现参数校验
1.创建一个React项目,在本地有npm命令的情况下,通过umi脚手架来搭建项目(注意,这里用了umi,也可以用React自带的脚手架,只不过后续修改跨域的配置文件不一样):
npm create @umijs/umi-app
2.初始化下项目:
npm install
3.创建Egg项目,执行命令:
npm init egg --type=simple
4.初始化egg项目:
npm install二. 先解决本地的跨域问题
React项目中,修改.umirc.ts文件,增加以下内容:(若是React脚手架搭建的,则修改package.json文件)
proxy: {
// 以api为前缀的都会走这个代理
"/api": {
// 将请求代理到egg服务商
target: "http://localhost:7001",
changeOrigin: true,
// 重写路径,最终请求到egg的路由是不带api前缀的
pathRewrite: {
"^/api": ""
}
}
}
修改pages目录下的index.tsx文件:(记得npm install axios)
import styles from './index.less';
import { Input, Button } from 'antd';
import axios from 'axios'
import { useState } from 'react'
export default function IndexPage() {
const [state, setState] = useState('')
const click = async () => {
console.log(state)
await axios({
url: '/api/test',
method: 'post',
withCredentials: true,
data: {
message: state,
},
})
}
return (
Page index
{ setState(event.target.value) }}>
);
}
然后启动项目,npm start,页面效果如下:
修改Egg项目,增加一条路由配置:
内容如下:
router.post('/test', controller.home.index);
在home.js中添加一条提示语:
启动egg项目:npm run dev
然后最终效果如下:
到这里,准备工作都已经做好了,那么来讲一讲本文的重点内容。在进行前后开发的过程中,往往我们需要注意前台传给后台的参数是否合法、是否有效。
在Java里面,我们可以通过@NotBlank、@NotEmpty等注解来控制一个变量的值,那么在Node里面,我们可以怎样去实现这样的效果呢?
三. 用装饰器实现参数校验首先配置下Egg项目中的一些配置,在根目录下创建一个tsconfig.json文件,添加以下内容:
{
"compilerOptions": {
"target": "es2017",
"experimentalDecorators": true,
}
}
其次来编写下装饰器,创建一个decorator文件夹,创建myValid.ts文件:
import { Controller } from 'egg';
// 校验方法中参数的类型
export type CheckFunc = (paramVal: T) => boolean;
interface ParamEntity {
[x: string]: (paramVal: any) => boolean;
}
export function preAction(preFn: any): any {
return function (_target: any, _name: any, descriptor: PropertyDescriptor): any {
// 获取旧属性值
const oldValue = descriptor.value;
descriptor.value = function (...args: any) {
// 执行preFn函数,查看这个参数是否校验通过,若某个参数不通过,则后续的就因短路运算就不走了
const isContinueFlag= preFn?.apply(this, args);
return isContinueFlag && oldValue.apply(this, args);
};
return descriptor;
};
}
export function valid(rules: CheckFunc[]): (paramVal: T) => boolean {
return (paramVal: T) => rules.reduce((prev: boolean, curr) => { return prev ? curr(paramVal) : prev; }, true);
}
export function ParamValid(paramEntity: ParamEntity) {
return preAction(function (this: Controller) {
// 前端请求参数体
const requestBodyFromFront = this.ctx.request.body;
// 校验注解中传入的参数数组
const paramNames: string[] = Object.keys(paramEntity);
const result: boolean = paramNames.reduce((prev: boolean, paramName) => {
// 根据参数名称去获得对应 前端请求体中 对应参数的值
const paramVal = requestBodyFromFront[paramName];
// 获得对应的校验API(对应上述的valid方法)
const checkFunc = paramEntity[paramName];
// 若不通过校验,则后续的方法就不执行了
return prev ? checkFunc(paramVal) : prev;
}, true);
if (result === false) {
this.ctx.body = {
content: '参数不合法',
success: false,
};
} else {
this.ctx.body = {
success: true,
};
}
return result;
});
}
export const notBlank = (): CheckFunc => (str: string) => str?.trim().length > 0;
在Controller层的方法上调用:
import { Controller } from 'egg';
import { ParamValid, valid, notBlank } from '../decorator/myValid'
class HomeController extends Controller {
@ParamValid({
message: valid([notBlank()]),
})
async index() {
const { ctx } = this;
const { message } = this.ctx.request.body;
console.log('获得请求了:' + message)
ctx.body = '校验通过';
}
}
export default HomeController;
最终的实现效果如下:
到这里一个简单的校验参数功能就做好啦。



