摘要:如果需要在構(gòu)造函數(shù)做一些處理,一定要有這句話,才能保證后面的使用。文件夾里面存放工具類引用拿到內(nèi)置對(duì)象也就是進(jìn)入這個(gè)文件頁(yè)面渲染使用的是頁(yè)面模板在里面添加添加渲染
egg.js是什么
是一個(gè)node.js的后臺(tái)web框架,類似的還有express,koa
優(yōu)勢(shì):規(guī)范、插件機(jī)制
Egg.js約定了一套代碼目錄結(jié)構(gòu)
(配置config、路由router、擴(kuò)展extend、中間件middleware、控制器controller)
規(guī)范的目錄結(jié)構(gòu),可以使得不同團(tuán)隊(duì)的開發(fā)者使用框架寫出來(lái)的代碼風(fēng)格會(huì)更一致,接手成本也會(huì)更低。
BFF層(前后端之間的中間層)、全棧、SSR(服務(wù)端渲染)
目錄結(jié)構(gòu)框架約定的目錄
app/router.js 用于配置URL路由規(guī)則 app/contorller/** 用于解析用戶的輸入,處理后返回相應(yīng)的結(jié)果 app/service/** 用于編寫業(yè)務(wù)邏輯層 【可選】 app/middleware/** 用于編寫中間件 【可選】 app/service/** 用于框架的擴(kuò)展 【可選】 ... 自定義的目錄 app/view/** 用于防止模板文件 【可選】加載順序
Egg 將應(yīng)用、框架和插件都稱為加載單元(loadUnit);
在加載過(guò)程中,Egg會(huì)遍歷所有的加載單元,加載時(shí)有一點(diǎn)的優(yōu)先級(jí)
· 插件 => 框架 => 應(yīng)用依次加載
· 依賴方先加載
· 框架按繼承順序加載,越底層越先加載
如有這樣一個(gè)應(yīng)用配置了如下依賴
app | ├── plugin2 (依賴 plugin3) | └── plugin3 └── framework1 | └── plugin1 └── egg
最終的加載順序?yàn)?/p>
=> plugin1 => plugin3 => plugin2 => egg => framework1 => app
文件加載順序
package.json => config => app/extend => app.js => app/service => app/middleware => app/controller => app/router.jsrouter
首先我們需要配置路由
因?yàn)槲覀冊(cè)趯?shí)際的開發(fā)中會(huì)使用很多路由所以這里我們將路由改成分級(jí)的
在app下創(chuàng)建一個(gè)router文件夾用來(lái)存放路由文件home.js
//app/router/home.js "use strict" module exports = app => { const { home } = app.controller //獲取controller下的home.js app.get("/",home.index); app.get("/home/param",home.getParam); app.get("/home/postParam",home.postParam); } // app/router.js "use strict" const RouteHome = require("./router/home"); module.exports = { const {router, controller} = app; RouteHome(app); } //app/controller/home.js "use strict" const Controller = require("egg").Controller; class HomeController extends Controller { async index() { await this.ctx.render("/index",{name:"egg"}); } async getParam() { let id = await this.ctx.query.id; this.ctx.body = id; } async postParam(){ let id = await this.ctx.request.body.id; //獲取post參數(shù) this.ctx.body = id; } } module exports = HomeController;controller
我們通過(guò) Router 將用戶的請(qǐng)求基于 method 和 URL 分發(fā)到了對(duì)應(yīng)的 Controller 上, Controller 負(fù)責(zé)解析用戶的輸入,處理后返回相應(yīng)的結(jié)果
框架推薦 Controller 層主要對(duì)用戶的請(qǐng)求參數(shù)進(jìn)行處理(校驗(yàn)、轉(zhuǎn)換),然后調(diào)用對(duì)應(yīng)的 service 方法處理業(yè)務(wù),得到業(yè)務(wù)結(jié)果后封裝并返回
所有的 Controller 文件都必須放在 app/controller 目錄下,可以支持多級(jí)目錄
訪問(wèn)的時(shí)候可以通過(guò)目錄名級(jí)聯(lián)訪問(wèn)
//在app/controller目錄下 新建一個(gè)controller "use strict" const Controller = required("egg").Controller; class CustomerController extends Controller { async customIndex() { //ctx.body 是 ctx.response.body 的簡(jiǎn)寫,不要和 ctx.request.body 混淆了 this.ctx.body = "this is my controller"; } } module.exports = CustomController; //在router.js中配置路由(訪問(wèn)時(shí)請(qǐng)求的路徑) "use strict" module.exports = app => { //相當(dāng)于拿到app文件夾下的router和controller const {router, controller} = app; router.get("/", controller.home.index); router.get("/custom",controller.customerController.customIndex); }
定義的 Controller 類,會(huì)在每一個(gè)請(qǐng)求訪問(wèn)到 server 時(shí)實(shí)例化一個(gè)全新的對(duì)象,而項(xiàng)目中的 Controller 類繼承于 egg.Controller,會(huì)有下面幾個(gè)屬性掛在 this 上
- this.ctx 框架封裝好的處理當(dāng)前請(qǐng)求的各種便捷屬性和方法 - this.app 框架提供的全局對(duì)象和方法 - this.service 訪問(wèn)抽象出的業(yè)務(wù)層 相當(dāng)于 this.ctx.service - this.config 運(yùn)行的配置項(xiàng) - this.logger 日志service
業(yè)務(wù)邏輯層
"use strict"; const Service = require("egg").Service; class customService extends Service { async show(zc, hh) { //異步防阻塞 return zc + " and " + hh; } } module.exports = UserService; //controller代碼 "use strict"; const Controller = require("egg").Controller; class CustomController extends Controller { async custonIndex() { let str = await this.ctx.service.customService.show("zc","hh"); //這里使用await來(lái)獲取異步方法的返回值 this.ctx.body = "this is my controller"+str; } } module.exports = CustomController;
一個(gè)更完整的栗子
// app/router.js module.exports = app => { app.router.get("/user/:id", app.controller.user.info); }; // app/controller/user.js const Controller = require("egg").Controller; class UserController extends Controller { async info() { const userId = ctx.params.id; const userInfo = await ctx.service.user.find(userId); ctx.body = userInfo; } } module.exports = UserController; // app/service/user.js const Service = require("egg").Service; class UserService extends Service { // 默認(rèn)不需要提供構(gòu)造函數(shù)。 // constructor(ctx) { // super(ctx); 如果需要在構(gòu)造函數(shù)做一些處理,一定要有這句話,才能保證后面 `this.ctx`的使用。 // // 就可以直接通過(guò) this.ctx 獲取 ctx 了 // // 還可以直接通過(guò) this.app 獲取 app 了 // } async find(uid) { // 假如 我們拿到用戶 id 從數(shù)據(jù)庫(kù)獲取用戶詳細(xì)信息 const user = await this.ctx.db.query("select * from user where uid = ?", uid); // 假定這里還有一些復(fù)雜的計(jì)算,然后返回需要的信息。 const picture = await this.getPicture(uid); return { name: user.user_name, age: user.age, picture, }; } async getPicture(uid) { const result = await this.ctx.curl(`http://photoserver/uid=${uid}`, { dataType: "json" }); return result.data; } } module.exports = UserService; // curl http://127.0.0.1:7001/user/1234helper
app/extend文件夾里面存放工具類
//app/extend/getName.js "use strict" module.exports = { getUserName(id) { return list.find(i=>i.id===id).name; } } //app/extend/helper.js "use strict" const getName = require("./getName"); module.exports = { showName() { return getName.getUserName("2221"); } } //controller引用helper "use strict" const Controller = require("egg").Controller; class CustomController extends Controller { async customIndex() { ////this.ctx.helper拿到helper內(nèi)置對(duì)象也就是進(jìn)入helper.js這個(gè)文件 this.ctx.body = this.ctx.helper.showName(); } } module.exports = CustomController;頁(yè)面渲染
egg.js使用的是nunjucks頁(yè)面模板
//在config/plugin.js里面添加 "use strict" exports.nunjucks = { enable: true, package: "egg-view-nunjucks" } //config/config/default.js 添加 "use strict" ... module.exports = app => { ... config.view = { mapping: { ".html": "nunjucks" }, root: path.join(appInfo.baseDir, "app/view") } ... return config; } //app/routes/sign.js "use strict"; module.exports = (router, controller) => { router.get("/sign/modifyPassword", controller.sign.modifyPassword); }; //app/controller/sign.js "use strict"; const Controller = require("egg").Controller; class SignController extends Controller { async modifyPassword() { const { ctx } = this; //渲染view/sign/modifyPassword.html await ctx.render("sign/modifyPassword.html"); } } module.exports = SignController;
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/97733.html
摘要:因?yàn)槠匠i_發(fā)都是前后端分離的模式,就想著使用創(chuàng)建后臺(tái)服務(wù),寫一套接口配合其他的項(xiàng)目。復(fù)雜數(shù)據(jù)的處理,比如要展現(xiàn)的信息需要從數(shù)據(jù)庫(kù)獲取或者是第三方服務(wù)的調(diào)用。更新用戶信息用戶信息已更改一個(gè)簡(jiǎn)單的應(yīng)用結(jié)構(gòu)就是這樣,如此便實(shí)現(xiàn)了用負(fù)責(zé)接口服務(wù)。 寫在前面的話 最近在學(xué)習(xí)Egg.js,它是阿里推出的基于Koa的node開發(fā)框架,為企業(yè)級(jí)框架和應(yīng)用而生。Egg.js 的官方文檔已經(jīng)很完善了,想學(xué)...
摘要:因?yàn)槠匠i_發(fā)都是前后端分離的模式,就想著使用創(chuàng)建后臺(tái)服務(wù),寫一套接口配合其他的項(xiàng)目。復(fù)雜數(shù)據(jù)的處理,比如要展現(xiàn)的信息需要從數(shù)據(jù)庫(kù)獲取或者是第三方服務(wù)的調(diào)用。更新用戶信息用戶信息已更改一個(gè)簡(jiǎn)單的應(yīng)用結(jié)構(gòu)就是這樣,如此便實(shí)現(xiàn)了用負(fù)責(zé)接口服務(wù)。 寫在前面的話 最近在學(xué)習(xí)Egg.js,它是阿里推出的基于Koa的node開發(fā)框架,為企業(yè)級(jí)框架和應(yīng)用而生。Egg.js 的官方文檔已經(jīng)很完善了,想學(xué)...
摘要:前言之前對(duì)的整體設(shè)計(jì)有過(guò)自己的理解,在中方便的插件機(jī)制也是這個(gè)框架的一大亮點(diǎn),本文主要就是從的插件開始,對(duì)后臺(tái)中的插件機(jī)制做一些分析和總結(jié)。插件的特點(diǎn)它包含了中間件配置框架擴(kuò)展等等。插件其余部分的運(yùn)行原理也是類似的。 前言 之前對(duì)egg.js的整體設(shè)計(jì)有過(guò)自己的理解,在egg.js中方便的插件機(jī)制也是這個(gè)框架的一大亮點(diǎn),本文主要就是從egg.js的插件開始,對(duì)node后臺(tái)中的插件機(jī)制做...
摘要:我為了方便直接就指定了淘寶倉(cāng)庫(kù)地址運(yùn)行服務(wù)運(yùn)行項(xiàng)目就比較簡(jiǎn)單了,運(yùn)行的命令在瀏覽器中打開地址,就能看到服務(wù)已經(jīng)啟動(dòng)完成。 傳送門:學(xué)習(xí)node.js服務(wù)開發(fā)這一篇就夠了系列文章 1.創(chuàng)建工程目錄 1.1 創(chuàng)建一個(gè)文件夾叫 my-egg-application $ mkdir my-egg-application 不熟悉命令行的同學(xué)也可以手動(dòng)創(chuàng)建文件夾 2.初始化項(xiàng)目模板 2.1 進(jìn)...
閱讀 805·2021-10-09 09:44
閱讀 2081·2021-09-22 15:54
閱讀 5198·2021-09-22 10:55
閱讀 1504·2019-08-29 18:41
閱讀 823·2019-08-29 11:24
閱讀 2164·2019-08-28 18:20
閱讀 1095·2019-08-26 11:51
閱讀 3111·2019-08-26 11:00