eggjs 实现服务端请求教程文档-1
简介
该教程适合入门级小伙伴,使用 node eggjs
框架实现服务端开发,以及处理开发过程中遇到的问题。
教程中的每个章节会附上 demo(git 分支),小伙伴可以自行拉取代码查看。
教程和 demo 会使用基于 umi
二次封装的 alita
框架进行页面渲染,重点讲解 eggjs
的 node 服务端框架。
实现通过 get
请求获取的 user
列表,并通过 post
请求获取详细的 user
信息。
作为入门级的我们,首先不用太关注过多的 api,技术类的东西建议先掌握了用法,用多了就能慢慢理解其中的奥义。所有光看不实操的小伙伴都是耍流氓。
现在我们先来创建 egg
框架。
一、eggjs 框架搭建和讲解
通过上面的链接,我们能够快速搭建 eggjs
的脚手架。
# 新建文件夹
mkdir eggDemo && cd eggDemo
# 搭建脚手架命令
npm init egg --type=simple
# 手动输入项目 pkg 信息
?project name egg
? project description
? project author
? cookie security keys 1620311360934_6251
# 进入项目安装依赖
cd init
yarn
在安装依赖的时间里,可以打开 package.json
文件看下 script
的标签。
"scripts": {
"start": "egg-scripts start --daemon --title=egg-server-egg",
"stop": "egg-scripts stop --title=egg-server-egg",
"dev": "egg-bin dev",
...
},
yarn run start
:启动egg
服务yarn run stop
:停止egg
服务yarn run dev
:启动开发模式,支持热部署
装好依赖后执行 yarn run dev
脚手架已经给我们写好了最简 demo。实现了一个最简单的接口。
eggjs
奉行『约定优于配置』,可以简单的理解为:以什么命名的文件和文件夹下就做什么事情(描述不准确,但是八九不离十)。
完整的目录结构请看官网讲解,看下脚手架为我们搭建的几个目录:
/config/config.default.js
: 配置文件/config/plugin.js
: 配置插件
/app/router.js
: 用于配置 URL 路由规则,即每个接口地址/app/controller/**
: 用于解析用户的输入,处理后返回相应的结果/app/public/**
: 用于放置静态资源
在真实的项目中会存在成百上千个接口,如果全部都挤在 app/router.js
里可能效果不佳。一般会分模块或者分后台中心来实现。
我们要实现的 demo 中有两个页面,分别为 用户列表页
和 用户详情页
。我们就按页面来区分,新建两个文件用来存放路由。
module.exports = app => {
require('./router/list')(app);
require('./router/detail')(app);
};
最后我们快速搭建一个 前端 web 框架。
# 在 eggDemo 的文件夹下键入 web 脚手架
yarn create alita eggWeb
cd eggWeb
yarn
初始化框架可以看下 demo 中的 /config/config.ts
和 /src/app.ts
文件。
二、用户列表接口开发(get 请求)
egg
每个接口都有独一无二的路由(接口名),
所以我们先来实现路由的编写:
/router/list.js
'use strict';
module.exports = app => {
const { router, controller } = app;
router.get('/api/getUserList', controller.home.userList);
};
router.get
代表 get 请求。controller.home.userListController
: 代表controller
文件夹下存在home
文件,文件内有userListController
的方法。
/app/controller/home.js
const Controller = require('egg').Controller;
class HomeController extends Controller {
async userListController() {
const { ctx } = this;
const data = Array.from(new Array(9)).map((_val, i) => ({
name: `name${i}`,
id: i,
}));
ctx.body = {
data,
success: true,
};
}
}
module.exports = HomeController;
async
: 可以理解为约定,代表了异步。
this
内参数说明:
参数 | 说明 |
---|---|
this.ctx | 当前请求的上下文 Context 对象的实例,通过它我们可以拿到框架封装好的处理当前请求的各种便捷属性和方法(能够更好的拿到请求上下文的数据) |
this.app | 当前应用 Application 对象的实例,通过它我们可以拿到框架提供的全局对象和方法 |
this.service | 通过它我们可以访问到抽象出的业务层,等价于 this.ctx.service , service 用于服务端的底层封装 |
this.config | 应用运行时的配置项 |
写完服务端的 get
请求,启动服务,打开 http://127.0.0.1:7001/api/getUserList
,能够看到请求的数据已经显示在界面上。
web
开发 web 端代码,请求 /api/getUserList
接口。
/src/pages/index/service.ts
: 使用 useRequest
请求参数。
import { request } from 'alita';
export async function getUserList(): Promise<any> {
return request('/api/getUserList', { method: 'get' });
}
/src/pages/index/index.tsx
:
import React, { FC, Fragment } from 'react';
import { useRequest, history } from 'alita';
import { Button } from 'antd-mobile';
import { getUserList } from './service';
import styles from './index.less';
interface HomePageProps {}
const HomePage: FC<HomePageProps> = () => {
const { data, run } = useRequest(getUserList, {
manual: true,
});
return (
<div className={styles.center}>
{data && (
<Fragment>
<div>调用 getUserList 请求: 出参:</div>
{data.map((item: any) => (
<div
onClick={() => {
history.push({
pathname: '/userDetail',
query: {
id: item.id,
},
});
}}
key={item?.id}
style={{
height: '1rem',
}}
>
{item.name}
</div>
))}
</Fragment>
)}
<Button onClick={() => run()}>get 请求</Button>
</div>
);
};
export default HomePage;
跨域问题
启动 web 项目访问:http://localhost:8000/#/
点击按钮调用接口发现数据并未展示出来,接口状态码 304 Not Modified
。
细看接口发现,服务接口和 web 并不同源,应该是存在跨域问题,我们需要增加代理来解决跨域问题:
/config/config.js
import { defineConfig } from 'alita';
const baseUrl = 'http://127.0.0.1:7001';
export default defineConfig({
appType: 'h5',
mobileLayout: true,
proxy: {
'/api': {
target: baseUrl,
changeOrigin: true,
},
},
});
至此,一个完整的 get 请求接口从开发,到 web 端界面渲染就完成了。
下一篇文章请小伙伴们移步至 eggjs 实现服务端请求教程文档-2