-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfeed.json
289 lines (289 loc) · 501 KB
/
feed.json
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
{
"version": "https://jsonfeed.org/version/1.1",
"title": "UMajs",
"home_page_url": "https://umajs.github.io/",
"feed_url": "https://umajs.github.io/feed.json",
"description": "Umajs,an easy-to-use NodeJS framework base on Typescript.",
"items": [
{
"title": "面向切面(AOP)",
"url": "https://umajs.github.io/development/AOP.html",
"id": "https://umajs.github.io/development/AOP.html",
"content_html": "<h1 id=\"面向切面-aop\" tabindex=\"-1\"> 面向切面(AOP)</h1>\n<p>AOP(Aspect Oriented Programming)面向切面编程是与 OOP(Object Oriented Programming)面向对象编程并列的编程思想。相对于 IOC(依赖注入)而言,AOP 是一种可以在不修改源代码的情况下给程序动态添加功能的一种方式。</p>\n<p>使用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。</p>\n<h2 id=\"什么是切面-aspect\" tabindex=\"-1\"> 什么是切面(Aspect)</h2>\n<p>AOP 称为<code>面向切面编程</code>,所以切面(Aspect)是 AOP 中一个很关键的点。</p>\n<p>假设我们有一个订单系统,有如下两条线的功能,提交订单和查询订单,每个事件流都需要执行“验证用户信息”的操作,将这个功能框起来后,你可以把它当块板子,这块板子插入了一些控制流程,这块板子就可以当成是 AOP 中的一个切面。</p>\n<p><img src=\"@source/../public/images/AOP-aspect.png\" alt=\"AOP\"></p>\n<h2 id=\"通知\" tabindex=\"-1\"> 通知</h2>\n<p><code>通知</code>是 AOP 中一个很重要的概念,所谓通知指的就是在拦截到方法之后要执行的代码。通知分为前置(before)、后置(after)、异常(afterThrowing)、最终(afterReturning)、环绕(around)通知五类。</p>\n<ul>\n<li>前置通知:在目标方法之前执行</li>\n<li>后置通知:在目标方法之后执行</li>\n<li>异常通知:当执行目标方法出现异常时执行</li>\n<li>最终通知:当目标方法有返回值之后执行,在后置通知之后</li>\n<li>环绕通知:在最开始调用时执行,会将目标方法作为参数传入,对目标方法(proceed)及入参(args)、出参(result)进行拦截,此方法必须返回 Result</li>\n</ul>\n<blockquote>\n<p>在 Uma 的 V1 版本我们实现了5个通知,在 V2 版本我们对通知进行了简化,减少用户对 AOP 理解的成本,保留了使用最多最灵活的 环绕<code>around</code>通知</p>\n</blockquote>\n<h2 id=\"around修饰器\" tabindex=\"-1\"> @Around修饰器</h2>\n<p>在 Uma 中,可以通过修饰器<code>@Around</code>的方式为方法添加环绕通知,Around修饰器接收一个参数,作为通知方法</p>\n<h3 id=\"类型声明\" tabindex=\"-1\"> 类型声明</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">/**</span></span>\n<span><span style=\"color: #8B949E\"> * </span><span style=\"color: #FF7B72\">@param</span><span style=\"color: #8B949E\"> </span><span style=\"color: #C9D1D9\">around</span><span style=\"color: #8B949E\"> 要执行的通知方法,方法需要return Uma 提供的 Result结果</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #D2A8FF\">Around</span><span style=\"color: #C9D1D9\">(around: (</span><span style=\"color: #FFA657\">point</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IProceedJoinPoint</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">Promise</span><span style=\"color: #FF7B72\"><</span><span style=\"color: #C9D1D9\">Result</span><span style=\"color: #FF7B72\"><</span><span style=\"color: #C9D1D9\">any</span><span style=\"color: #FF7B72\">>></span><span style=\"color: #C9D1D9\">)</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><h3 id=\"示例\" tabindex=\"-1\"> 示例</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Result, Around } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { method } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../aspect/method.aspect'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">// 为index方法添加around修饰,method为对应要执行的around通知方法</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Around</span><span style=\"color: #FFA657\">(</span><span style=\"color: #C9D1D9\">method</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'ok'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// /aspect/method.aspect.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { IProceedJoinPoint } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">function</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">method</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">proceedPoint</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IProceedJoinPoint</span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">>) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 执行around before方法,即在被修饰方法执行前操作,当做一些前置校验的时候如果不满足可以直接return</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is around'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 执行被修饰的方法</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">result</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> proceedPoint.</span><span style=\"color: #D2A8FF\">proceed</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> </span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 执行around after方法,即在被修饰方法执行后操作</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is around after'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> result;</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br></div></div><h3 id=\"middlewaretoaround\" tabindex=\"-1\"> middlewareToAround</h3>\n<p>Uma 提供了将<code>Middleware(中间件)转Around(环绕)</code>的方法<code>middlewareToAround</code>,将中间件转为 Around 修饰器后,我们可以以 AOP 的装饰器形式使用中间件。 在V2版本之后,我们可以直接使用@Middleware修饰器直接将koa中间件作用于方法。具体参考 <a href=\"/development/Middleware.html#aop-%E8%A3%85%E9%A5%B0%E5%99%A8%E5%BD%A2%E5%BC%8F\">Middleware 参考文档</a></p>\n",
"date_modified": "2023-03-17T10:20:25.146Z",
"authors": [],
"tags": []
},
{
"title": "配置(Config)",
"url": "https://umajs.github.io/development/Config.html",
"id": "https://umajs.github.io/development/Config.html",
"content_html": "<h1 id=\"配置-config\" tabindex=\"-1\"> 配置(Config)</h1>\n<h2 id=\"config-loader\" tabindex=\"-1\"> config loader</h2>\n<p>Uma 的配置通过自动合并 app 及框架的配置,并根据不同环境读取不同的配置,最终配置通过<code>Uma.config</code>获取。</p>\n<blockquote>\n<p>插件的配置的 <code>options</code> 最终会和对应名称的 <code>config</code>(*.config.ts) 合并后传给插件</p>\n<p><code>config</code> 的优先级最高,会将 <code>options</code> 中相同的配置覆盖、不同的合并</p>\n</blockquote>\n<h3 id=\"配置目录\" tabindex=\"-1\"> 配置目录</h3>\n<p>框架默认会加载<code>${URSA_ROOT}/config</code>目录下以<code>xx.config.xx</code>命名的配置文件</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #c9d1d9\">|- config\n |- plugin.config.ts\n</span></span></code></pre><div><span>1</span><br><span>2</span><br></div></div><p>你也可以根据需求在实例化时通过<code>configPath</code>来指定配置目录</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">uma</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> Uma.</span><span style=\"color: #D2A8FF\">instance</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> Router,</span></span>\n<span><span style=\"color: #C9D1D9\"> ROOT: __dirname,</span></span>\n<span><span style=\"color: #C9D1D9\"> configPath: path.</span><span style=\"color: #D2A8FF\">join</span><span style=\"color: #C9D1D9\">(__dirname, </span><span style=\"color: #A5D6FF\">'defaultConfig'</span><span style=\"color: #C9D1D9\">),</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><h3 id=\"cli-初始化配置\" tabindex=\"-1\"> cli 初始化配置</h3>\n<p>通过 <code>uma</code> 命令可以快速的给工程添加插件或者可发布的插件工程</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">uma config init [configName]</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"配置获取\" tabindex=\"-1\"> 配置获取</h3>\n<p><code>xx.config.ts</code>需 export 一个 default 值,配置将以文件名为 key,default 值为 value 存在实例上,可以通过<code>Uma</code>的 config 属性来获取到所有 config 值</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">Uma.config </span><span style=\"color: #8B949E\">// 获取 config 所有数据</span></span>\n<span><span style=\"color: #C9D1D9\">Uma.config.status </span><span style=\"color: #8B949E\">// 获取 status 配置</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.146Z",
"authors": [],
"tags": []
},
{
"title": "控制器(Controller)",
"url": "https://umajs.github.io/development/Controller.html",
"id": "https://umajs.github.io/development/Controller.html",
"content_html": "<h1 id=\"控制器-controller\" tabindex=\"-1\"> 控制器(Controller)</h1>\n<h2 id=\"什么是控制器\" tabindex=\"-1\"> 什么是控制器</h2>\n<p>控制器负责解析用户输入,并向用户返回处理结果。</p>\n<p>在控制器中,我们可以指定什么时候(<strong>路由</strong>)去响应,怎么样(<strong>服务</strong>)去返回结果。</p>\n<h2 id=\"控制器加载与编写\" tabindex=\"-1\"> 控制器加载与编写</h2>\n<h3 id=\"加载\" tabindex=\"-1\"> 加载</h3>\n<p>控制器也是通过约定的策略进行加载:默认加载<code>${URSA_ROOT}/controller</code>下所有<code>*.controller</code>文件。</p>\n<h3 id=\"控制器编写\" tabindex=\"-1\"> 控制器编写</h3>\n<p><code>Uma</code>的控制器需要通过类的继承的方式实现,方法必须都返回框架内置的 Result 静态方法,如下代码</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 等同于 return Result.send('this is index router');</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br></div></div><p>命中路由规则的控制器,在请求时会被实例化,以下属性可以通过<code>this</code>获取:</p>\n<ol>\n<li><code>ctx</code>: 当前请求上下文</li>\n<li><code>req</code>: <code>Request</code>实例</li>\n<li><code>res</code>: <code>Response</code>实例</li>\n</ol>\n<h2 id=\"获取请求参数\" tabindex=\"-1\"> 获取请求参数</h2>\n<h3 id=\"query-和路由参数\" tabindex=\"-1\"> query 和路由参数</h3>\n<p>详见 Router#@Param、@Query 修饰器</p>\n<h3 id=\"header\" tabindex=\"-1\"> header</h3>\n<p>获取 header 参数可以用<code>this.header(name)</code>方法获取。</p>\n<h3 id=\"cookie\" tabindex=\"-1\"> cookie</h3>\n<p>在控制器中,可以通过<code>this.ctx.cookies.get</code>方法获取 cookie。</p>\n<h3 id=\"session\" tabindex=\"-1\"> session</h3>\n<p>默认情况下,<code>Uma</code>的 Session 插件通过 cookie 存储 session,详细的配置和用法可以通过 Plugin#Session 获取。</p>\n<p>在控制器中,可以通过<code>this.ctx.session</code>对象获取相应的 session 值。</p>\n<h3 id=\"body-和上传文件的获取\" tabindex=\"-1\"> body 和上传文件的获取</h3>\n<h2 id=\"发送响应\" tabindex=\"-1\"> 发送响应</h2>\n<p>返回的数据都可以通过<code>Result</code>来返回。 <code>BaseController</code>也内置了<code>Result</code>一样的方法,还内置了一些方便使用的方法。</p>\n<h3 id=\"set-status-status-number\" tabindex=\"-1\"> set status(status: number);</h3>\n<p>正确的设置 http 的状态码,可以增强请求的语义性。可以通过<code>this.status = code</code>设置返回的状态码。</p>\n<h3 id=\"get-useragent-any\" tabindex=\"-1\"> get userAgent(): any;</h3>\n<p>获取请求的 user-agent</p>\n<h3 id=\"get-param-any\" tabindex=\"-1\"> get param(): any;</h3>\n<p>获取请求的参数</p>\n<h3 id=\"setheader-name-string-any-value-string-string-void\" tabindex=\"-1\"> setHeader(name: string | any, value: string | string[]): void;</h3>\n<p>设置请求 header</p>\n<h3 id=\"getheader-name-string-any-any\" tabindex=\"-1\"> getHeader(name: string | any): any;</h3>\n<p>获取请求 header</p>\n<h3 id=\"统一返回-result\" tabindex=\"-1\"> 统一返回 Result</h3>\n<p>在 controller 中可以 <code>return Result[...](...)</code>,也可以 <code>return this[...](...)</code>,更多介绍见<a href=\"/development/Result.html\">Result</a>。</p>\n<h4 id=\"this-send-val-status\" tabindex=\"-1\"> <code>this.send(val, status)</code></h4>\n<p>用于快捷返回文本内容,第二个参数为返回状态码。</p>\n<h4 id=\"this-json-data\" tabindex=\"-1\"> <code>this.json(data)</code></h4>\n<p>返回 json 数据,并将<code>content-type</code>设置为<code>application/json</code>。</p>\n<h4 id=\"this-jsonp-data-callback\" tabindex=\"-1\"> <code>this.jsonp(data, callback)</code></h4>\n<p>以 jsonp 的形式返回数据。</p>\n<h4 id=\"this-view-templatepath-data\" tabindex=\"-1\"> <code>this.view(templatePath, data)</code></h4>\n<p>通过渲染模板的方式将数据返回。</p>\n<h4 id=\"this-stream-data-filename\" tabindex=\"-1\"> <code>this.stream(data, fileName)</code></h4>\n<p>将文件以流(stream)的方式返回</p>\n<h4 id=\"this-download-filepath-opts\" tabindex=\"-1\"> <code>this.download(filePath, opts)</code></h4>\n<p>下载文件</p>\n<h4 id=\"this-done\" tabindex=\"-1\"> <code>this.done()</code></h4>\n<p>使用 ctx 进行完了操作,不需要使用 Result 进行其它的返回时使用此方法,常用于框架的迁移。</p>\n",
"date_modified": "2023-03-17T10:20:25.146Z",
"authors": [],
"tags": []
},
{
"title": "修饰器(Decorator)",
"url": "https://umajs.github.io/development/Decorator.html",
"id": "https://umajs.github.io/development/Decorator.html",
"content_html": "<h1 id=\"修饰器-decorator\" tabindex=\"-1\"> 修饰器(Decorator)</h1>\n<p>框架大量功能都是以 Decorator(修饰器)的方式使用。</p>\n<h2 id=\"resource、-inject-修饰器\" tabindex=\"-1\"> @Resource、@Inject 修饰器</h2>\n<p><a href=\"/development/IOC.html#resource%E3%80%81-inject-%E4%BF%AE%E9%A5%B0%E5%99%A8\">IOC 参考文档</a></p>\n<h2 id=\"service-修饰器\" tabindex=\"-1\"> @Service 修饰器</h2>\n<p><a href=\"/development/IOC.html#service%E4%BF%AE%E9%A5%B0%E5%99%A8\">Service 参考文档</a></p>\n<h2 id=\"around-修饰器\" tabindex=\"-1\"> @Around 修饰器</h2>\n<p><a href=\"/development/AOP.html#around%E4%BF%AE%E9%A5%B0%E5%99%A8\">Acpect 参考文档</a></p>\n<h2 id=\"middleware-修饰器\" tabindex=\"-1\"> Middleware 修饰器</h2>\n<p><a href=\"/development/Middleware.html#middleware%E8%A3%85%E9%A5%B0%E5%99%A8\">Middleware 参考文档</a></p>\n<h2 id=\"path\" tabindex=\"-1\"> @Path</h2>\n<p><a href=\"/development/Router.html#path%E4%BF%AE%E9%A5%B0%E5%99%A8\">Router 参考文档</a></p>\n<h2 id=\"参数装饰器-param-query-body\" tabindex=\"-1\"> 参数装饰器 <a href=\"/other/ArgDecorator.html\">@Param , @Query, @Body</a></h2>\n<h2 id=\"自定义参数装饰器-createargdecorator\" tabindex=\"-1\"> 自定义参数装饰器 createArgDecorator</h2>\n<h3 id=\"注意\" tabindex=\"-1\"> 注意</h3>\n<blockquote>\n<p>从 v1.1.* 版本开始,<code>createArgDecorator</code> 更新了参数方式,使传入参数不受一个的限制。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// v1.0.*</span></span>\n<span><span style=\"color: #FF7B72\">function</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">createArgDecorator</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #D2A8FF\">fn</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">argKey</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">)</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FF7B72\">...</span><span style=\"color: #FFA657\">argProps</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">[]) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">ParameterDecorator</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// v1.1.*</span></span>\n<span><span style=\"color: #FF7B72\">function</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">createArgDecorator</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #D2A8FF\">fn</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FF7B72\">...</span><span style=\"color: #FFA657\">argProps</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">[]) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">)</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FF7B72\">...</span><span style=\"color: #FFA657\">argProps</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">[]) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">ParameterDecorator</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><h3 id=\"示例如下\" tabindex=\"-1\"> 示例如下</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// user.controller.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Param } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { AgeCheck } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../decorator/AgeCheck'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> User </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">save</span><span style=\"color: #FFA657\">(@</span><span style=\"color: #D2A8FF\">Param</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'name'</span><span style=\"color: #FFA657\">) name</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #FFA657\">, @</span><span style=\"color: #D2A8FF\">AgeCheck</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'age'</span><span style=\"color: #FFA657\">) age</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">number</span><span style=\"color: #FFA657\">) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// ...</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// decorator/AgeCheck.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { createArgDecorator, Result, IContext } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">/**</span></span>\n<span><span style=\"color: #8B949E\"> * 1、参数的聚合 Model</span></span>\n<span><span style=\"color: #8B949E\"> * 2、参数的校验</span></span>\n<span><span style=\"color: #8B949E\"> * 3、参数的转换</span></span>\n<span><span style=\"color: #8B949E\"> * 4、便捷方法</span></span>\n<span><span style=\"color: #8B949E\"> * 5、utils、config 等也可以通过此装饰器快速引用</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">AgeCheck</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">createArgDecorator</span><span style=\"color: #C9D1D9\">((</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">ageKey</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">let</span><span style=\"color: #C9D1D9\"> age </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> ctx.query[ageKey]</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">if</span><span style=\"color: #C9D1D9\"> (age </span><span style=\"color: #FF7B72\">===</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">undefined</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">json</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> code: </span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> msg: </span><span style=\"color: #A5D6FF\">'请加上 age 参数'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> })</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> age </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">+</span><span style=\"color: #C9D1D9\">age</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">if</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #79C0FF\">Number</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">isNaN</span><span style=\"color: #C9D1D9\">(age) </span><span style=\"color: #FF7B72\">||</span><span style=\"color: #C9D1D9\"> age </span><span style=\"color: #FF7B72\"><</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">||</span><span style=\"color: #C9D1D9\"> age </span><span style=\"color: #FF7B72\">></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">120</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">json</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> code: </span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> msg: </span><span style=\"color: #A5D6FF\">'请传入正确的 age 参数'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> })</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> age</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br><span>24</span><br><span>25</span><br><span>26</span><br><span>27</span><br><span>28</span><br><span>29</span><br><span>30</span><br><span>31</span><br><span>32</span><br><span>33</span><br><span>34</span><br><span>35</span><br><span>36</span><br><span>37</span><br><span>38</span><br><span>39</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.147Z",
"authors": [],
"tags": []
},
{
"title": "依赖注入(IOC)",
"url": "https://umajs.github.io/development/IOC.html",
"id": "https://umajs.github.io/development/IOC.html",
"content_html": "<h1 id=\"依赖注入-ioc\" tabindex=\"-1\"> 依赖注入(IOC)</h1>\n<p>IOC(Inversion of Control)控制反转,是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。</p>\n<h2 id=\"什么是-ioc\" tabindex=\"-1\"> 什么是 IOC</h2>\n<p><code>控制反转(Inversion of Control)</code>是一种借助于<code>第三方容器</code>,实现对具有依赖关系的<code>对象之间解耦</code>的一种<code>代码设计思路</code>。</p>\n<p>例如我们的程序中有对象 A、B、C、D 像齿轮一样相互依赖的运作着,如下图:</p>\n<p><img src=\"@source/../public/images/IOC-di4.png\" alt=\"images\"></p>\n<p>我们可以看到,在这样的齿轮组中,如果有一个齿轮出了问题,就可能会影响到整个齿轮组的正常运转。</p>\n<p>为了解决对象之间的耦合度过高的问题,软件专家 Michael Mattson 提出了 IOC 理论,借助于“第三方容器”实现对象之间的解耦,如下图:</p>\n<p><img src=\"@source/../public/images/IOC-di5.png\" alt=\"images\"></p>\n<p>由于引进了中间位置的“第三方容器”,也就是<code>IOC容器</code>,使得 A、B、C、D 这 4 个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方容器”了,全部对象的控制权全部上缴给“第三方”IOC 容器。</p>\n<p>当对象 A 需要用到对象 B 的时候,只需要通过 IOC 容器来获取<code>对象B的实例</code>,而不需要自己创建一个对象 B 实例。而 IOC 容器又通过<code>依赖注入</code>的方式将对象 A 需要的对象 B 实例<code>注入</code>到对象 A 中。</p>\n<p><img src=\"@source/../public/images/IOC-di3.png\" alt=\"images\"></p>\n<h2 id=\"resource、-inject-修饰器\" tabindex=\"-1\"> @Resource、@Inject 修饰器</h2>\n<p>Uma 提供了<code>@Resource修饰器</code>和<code>@Inject修饰器</code>来实现<code>IOC容器</code>和<code>依赖注入</code></p>\n<p>@Resource 修饰器可以修饰<code>${URSA_ROOT}中的任意class</code>,被@Resource 修饰的 class,将会在 IOC 容器中加入一个该<code>class的实例</code></p>\n<blockquote>\n<p>Resource 装饰器还可以传入参数作为 class 的实例化参数。\nexport declare function Resource(...props: any[]): Function;</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Resource</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'user'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #FF7B72\">class</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Test</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">constructor</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FF7B72\">readonly</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">tablename</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><p>@Inject 修饰器可以将<code>被@Resource修饰过</code>的 class 的<code>实例</code>注入到指定变量中</p>\n<p>例如,我们在<code>${URSA_ROOT}/model</code>中创建一个<code>user.model.ts</code>,并使用@Resource 将该类实例化后加入到资源容器中.</p>\n<p><strong>注意</strong><code>inject</code>装饰器在V2版本之后只接受函数类型参数。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Resource } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// ===> @Resource修饰器</span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Resource</span><span style=\"color: #C9D1D9\">()</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> UserModel {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">findAll</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// ...</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> []</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><p>然后我们可以在 controller 中获取该 model 实例</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> BaseController,</span></span>\n<span><span style=\"color: #C9D1D9\"> Path,</span></span>\n<span><span style=\"color: #C9D1D9\"> Inject,</span></span>\n<span><span style=\"color: #C9D1D9\">} </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> UserModel </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../model/user.model'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">// ===> 获取实例,实例的名称为@Resource修饰的class所在的文件名</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Inject</span><span style=\"color: #FFA657\">(</span><span style=\"color: #C9D1D9\">UserModel</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> user</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> UserModel</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/getUser'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">testModel</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// ===> 这里不需要创建user实例,@Resource已经将userModel实例化保存在容器中</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">userList</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.user.</span><span style=\"color: #D2A8FF\">findAll</span><span style=\"color: #C9D1D9\">()</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">json</span><span style=\"color: #C9D1D9\">(userList)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br></div></div><p>@Resource 可以对<code>任何class进行修饰</code>,即任何资源都可以加入到容器中,然后通过依赖注入的方式使用。</p>\n<p><code>@Resource修饰器支持传入参数</code>,传入的参数将会被作为修饰类实例化时的<code>构造参数</code>使用。</p>\n<h2 id=\"service修饰器\" tabindex=\"-1\"> @Service修饰器</h2>\n<p>除了提供的 <code>Resource</code> 和 <code>Inject</code> 装饰器,还有一个特殊的依赖注入装饰器 <code>Service</code>,<code>@Service</code> 装饰器仅提供 <code>Controller</code> 使用,为了方便使用,Service 注入中内置了 ctx,框架默认将<code>${URSA_ROOT}/service</code>下的文件实例化加入到<code>service的容器中</code>,当我们使用的时候,通过<code>@Service修饰器</code>去获取该实例。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> DemoService </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../service/demo.service'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Service</span><span style=\"color: #FFA657\">(</span><span style=\"color: #C9D1D9\">DemoService</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> demoService</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> DemoService</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/demo'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">demoService</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// return this.demoService.loadAll();</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseService } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Demp </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseService</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">loadAll</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// return</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><blockquote>\n<p>@Service 和@Resource 最大的不同是,在@Service 修饰的方法中可以访问到<code>ctx</code>上下文对象,而@Resource 没有</p>\n</blockquote>\n<h3 id=\"非-controller-中使用-service-时-必须传入-ctx-进行实例化才能使用或者-service-类不继承-baseservice-使用-resource-容器修饰此-class。\" tabindex=\"-1\"> 非 Controller 中使用 @Service 时,必须传入 ctx 进行实例化才能使用或者 service 类不继承 BaseService,使用@Resource 容器修饰此 class。</h3>\n<p><a href=\"/development/Service.html\">Service 参考文档</a></p>\n",
"date_modified": "2023-03-17T10:20:25.147Z",
"authors": [],
"tags": []
},
{
"title": "中间件(Middleware)",
"url": "https://umajs.github.io/development/Middleware.html",
"id": "https://umajs.github.io/development/Middleware.html",
"content_html": "<h1 id=\"中间件-middleware\" tabindex=\"-1\"> 中间件(Middleware)</h1>\n<p>Uma 基于 Koa2,兼容 middleware。在已有中间件的基础上提供两种使用形式:插件形式、AOP 形式。</p>\n<h2 id=\"插件形式\" tabindex=\"-1\"> 插件形式</h2>\n<h3 id=\"使用\" tabindex=\"-1\"> 使用</h3>\n<p><code>Uma</code> 的插件机制很大部分是借用了 <code>Koa</code> 的中间件,通过插件来使用中间件更易于开发和维护,请尽量用插件形式来使用中间件,插件开发和使用请参阅\n<a href=\"/development/Plugin.html#%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91\">Plugin 参考文档</a></p>\n<h3 id=\"其它\" tabindex=\"-1\"> 其它</h3>\n<p>为了方便插件使用已发布的中间件,插件配置(plugin.config.ts)可以配置中间件便捷使用,配置如下</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// types</span></span>\n<span><span style=\"color: #C9D1D9\">[middlewareName: string]: {</span></span>\n<span><span style=\"color: #C9D1D9\"> type: </span><span style=\"color: #A5D6FF\">'middleware'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 仅在使用中间件的时候配置 type</span></span>\n<span><span style=\"color: #C9D1D9\"> handler: Koa.Middleware,</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #8B949E\">// 基于 koa-views 配置模板中间件</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">as</span><span style=\"color: #C9D1D9\"> views </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'koa-views'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">view: {</span></span>\n<span><span style=\"color: #C9D1D9\"> type: </span><span style=\"color: #A5D6FF\">'middleware'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> handler: </span><span style=\"color: #D2A8FF\">views</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'./views'</span><span style=\"color: #C9D1D9\">, {</span></span>\n<span><span style=\"color: #C9D1D9\"> map: { html: </span><span style=\"color: #A5D6FF\">'nunjucks'</span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }),</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br></div></div><blockquote>\n<p>请不要在插件配置( plugin.config.ts )中进行中间件的开发,让插件的配置更加纯粹。如需要请使用插件开发。<a href=\"/development/Plugin.html#%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91\">Plugin 参考文档</a></p>\n<p>如果要动态的加载中间件,请使用复合插件形式。<a href=\"/development/Plugin.html#%E5%A4%8D%E5%90%88%E6%8F%92%E4%BB%B6%E5%BD%A2%E5%BC%8F\">Plugin 参考文档</a></p>\n</blockquote>\n<h2 id=\"middleware装饰器\" tabindex=\"-1\"> Middleware装饰器</h2>\n<blockquote>\n<p>Middleware装饰器(v2+)目前只支持函数装饰,可将koa中间件作用于特定的controller函数。这可以更灵活的控制避免全局中间件的影响;将中间件局部应用于单一或者多个路由。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span></span>\n<span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">middleware</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #C9D1D9\">,</span><span style=\"color: #FFA657\">next</span><span style=\"color: #C9D1D9\">)</span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">"****** middleware before ******"</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">"****** middleware after *******"</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Middleware</span><span style=\"color: #FFA657\">(</span><span style=\"color: #C9D1D9\">middleware</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">view</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'index.html'</span><span style=\"color: #C9D1D9\">, {</span></span>\n<span><span style=\"color: #C9D1D9\"> frameName: </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.testService.</span><span style=\"color: #D2A8FF\">returnFrameName</span><span style=\"color: #C9D1D9\">(),</span></span>\n<span><span style=\"color: #C9D1D9\"> });</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br></div></div><h2 id=\"aop-装饰器形式\" tabindex=\"-1\"> AOP 装饰器形式</h2>\n<p>中间件和 Around 方式很相似,都是包裹异步方法。中间件是 next,around 是 proceed,但是他们有一些区别:</p>\n<blockquote>\n<p>1、中间件不能处理参数,不能处理返回结果</p>\n<p>2、切面可以对参数进行修改、判断、注入等操作,还可以对返回结果进行修改、校验、统一封装等操作</p>\n</blockquote>\n<p>对于在中间件需要对参数,返回结构进行统一处理和校验,推荐使用 AOP 形式代码结构更清晰,可读性更强。<a href=\"/development/AOP.html\">AOP 参考文档</a></p>\n",
"date_modified": "2023-03-17T10:20:25.147Z",
"authors": [],
"tags": []
},
{
"title": "插件(Plugin)",
"url": "https://umajs.github.io/development/Plugin.html",
"id": "https://umajs.github.io/development/Plugin.html",
"content_html": "<h1 id=\"插件-plugin\" tabindex=\"-1\"> 插件(Plugin)</h1>\n<h2 id=\"为什么使用插件\" tabindex=\"-1\"> 为什么使用插件</h2>\n<p><code>Uma</code> 的插件内部机制就是借用了 <code>Koa</code> 的中间件,但是仅有中间件无法满足框架的扩展,另外中间件的配置对于业务多样性解决也偏单一。</p>\n<p><code>Uma</code> 使用插件进行框架层面拓展,不仅可以使用中间件模式进行扩展,还可以采用复合模式对 context、request、response 进行扩展,还可以对中间件的使用场景进行快速开发,例如 results(返回值)、use(无设定场景)、filter(对符合条件的路由加载中间件)、ignore(对符合条件之外的路由加载中间件)、method(对 MethodType 符合的请求加载中间件)</p>\n<h2 id=\"插件使用\" tabindex=\"-1\"> 插件使用</h2>\n<h3 id=\"插件安装\" tabindex=\"-1\"> 插件安装</h3>\n<p>插件可以通过 npm 方式进行安装。<code>Uma</code>官方提供的插件一般使用<code>@umajs/plugin-</code>作为前缀,方便我们去搜索。同时<code>Uma</code>也可以加载应用目录内的用户自定义插件<code>plugins</code>目录。框架在读取配置后,插件的加载优先级如下:</p>\n<ol>\n<li>{URSA_ROOT}/plugins/{packageName}</li>\n<li>{URSA_ROOT}/node_modules/{packageName}</li>\n</ol>\n<h3 id=\"插件配置\" tabindex=\"-1\"> 插件配置</h3>\n<p>插件一般有默认配置,我们也可以通过自定义配置来覆盖原有配置。</p>\n<p>插件的配置在 config 目录下的<code>plugin.config.ts</code>文件中,插件顺序按照 <code>config/plugin.config.ts</code> 配置的顺序进行加载。</p>\n<blockquote>\n<p>注意:插件的顺序会影响到插件调用其它插件的功能。</p>\n</blockquote>\n<h4 id=\"插件配置说明\" tabindex=\"-1\"> 插件配置说明</h4>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TPluginConfig</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">enable</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 是否开启插件,默认值false</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">name</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 插件名,可选</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">packageName</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// npm包名,可选,如不填写时,默认值为`@umajs/plugin-$</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">options</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">object</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 框架会将此配置用参数形式传给插件</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br></div></div><blockquote>\n<p>当 [pluginName].config.ts 存在时, 会和配置混合后传给插件</p>\n</blockquote>\n<h4 id=\"插件配置实例\" tabindex=\"-1\"> 插件配置实例</h4>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// config/plugin.config.ts</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #A5D6FF\">'error-handler'</span><span style=\"color: #C9D1D9\">: {</span></span>\n<span><span style=\"color: #C9D1D9\"> enable: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> name: </span><span style=\"color: #A5D6FF\">'error-handler'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> packageName: </span><span style=\"color: #A5D6FF\">'@umajs/plugin-error-handler'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> options: {</span></span>\n<span><span style=\"color: #C9D1D9\"> foo: </span><span style=\"color: #A5D6FF\">'1'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> }, </span><span style=\"color: #8B949E\">// 插件的实际配置</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br></div></div><p>如果只需开启插件或关闭插件,可以简化配置写法:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// config/plugin.config.ts</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #A5D6FF\">'error-handler'</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><p>插件实际上是一个接收uma对象和option参数的函数,函数必须返回中间件函数或复合插件格式<a href=\"/plugin/dev.html#%E5%A4%8D%E5%90%88%E6%8F%92%E4%BB%B6%E5%BD%A2%E5%BC%8F\">对象</a></p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin/error-handler/index.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> (uma</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Uma, options</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> TView </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #FFA657\"> {})</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Koa.Middleware </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// uma 实例化对象;options 插件配置的 options,等同于 uma.plugin['error-handler'].options</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #C9D1D9\">,</span><span style=\"color: #FFA657\">next</span><span style=\"color: #C9D1D9\">)</span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">try</span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FF7B72\">catch</span><span style=\"color: #C9D1D9\">(e){</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">error</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'error-handler插件捕获异常'</span><span style=\"color: #C9D1D9\">,e);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\">};</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><h2 id=\"插件开发\" tabindex=\"-1\"> <a href=\"/plugin/dev.html\">插件开发</a></h2>\n",
"date_modified": "2023-03-17T10:20:25.147Z",
"authors": [],
"tags": []
},
{
"title": "统一返回(Result)",
"url": "https://umajs.github.io/development/Result.html",
"id": "https://umajs.github.io/development/Result.html",
"content_html": "<h1 id=\"统一返回-result\" tabindex=\"-1\"> 统一返回(Result)</h1>\n<p>在 koa 和大多数框架中,没有统一返回,这样在使用框架返回数据的时候需要额外处理,如果要对返回结果做处理可能需要修改很多地方,但是在进行了统一返回之后这些都变得很简单。</p>\n<h2 id=\"result\" tabindex=\"-1\"> Result</h2>\n<h4 id=\"result-send-val-status\" tabindex=\"-1\"> <code>Result.send(val, status)</code></h4>\n<p>用于快捷返回文本内容,第二个参数为返回状态码。</p>\n<h4 id=\"result-json-data\" tabindex=\"-1\"> <code>Result.json(data)</code></h4>\n<p>返回 json 数据,并将<code>content-type</code>设置为<code>application/json</code>。</p>\n<h4 id=\"result-jsonp-data-callback\" tabindex=\"-1\"> <code>Result.jsonp(data, callback)</code></h4>\n<p>以 jsonp 的形式返回数据。</p>\n<h4 id=\"result-view-templatepath-data\" tabindex=\"-1\"> <code>Result.view(templatePath, data)</code></h4>\n<p>通过渲染模板的方式将数据返回。</p>\n<h4 id=\"result-stream-data-filename\" tabindex=\"-1\"> <code>Result.stream(data, fileName)</code></h4>\n<p>将文件以流(stream)的方式返回</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/stream'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">donwStream</span><span style=\"color: #C9D1D9\">() {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">rs</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> fs.</span><span style=\"color: #D2A8FF\">createReadStream</span><span style=\"color: #C9D1D9\">(path.</span><span style=\"color: #D2A8FF\">resolve</span><span style=\"color: #C9D1D9\">(__dirname, </span><span style=\"color: #A5D6FF\">'./template.controller.ts'</span><span style=\"color: #C9D1D9\">));</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">stream</span><span style=\"color: #C9D1D9\">(rs, </span><span style=\"color: #A5D6FF\">'controller.ts'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><h4 id=\"result-download-filepath-opts\" tabindex=\"-1\"> <code>Result.download(filePath, opts)</code></h4>\n<p>下载文件</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/download'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">downFile</span><span style=\"color: #C9D1D9\">() {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">download</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/src/controller/template.controller.ts'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><h4 id=\"result-done\" tabindex=\"-1\"> <code>Result.done()</code></h4>\n<p>使用 ctx 进行完了操作,不需要使用 Result 进行其它的返回时使用此方法,常用于框架的迁移。</p>\n<blockquote>\n<p>例如下面两个方法 <code>json1</code> 和 <code>json2</code> 表示的意思是一样的。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">json1</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.body </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'Hello'</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// ctx 响应</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">done</span><span style=\"color: #C9D1D9\">()</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">json2</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'Hello'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><h2 id=\"实例\" tabindex=\"-1\"> 实例</h2>\n<h3 id=\"controller-实例\" tabindex=\"-1\"> controller 实例</h3>\n<p>Uma 在需要的模板返回的数据中加入 version,这里我们用 Around 可以很容易做到。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// version.aspect.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { IJoinPoint, IProceedJoinPoint, Result } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">version</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">proceedPoint</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IProceedJoinPoint</span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">>) {</span></span>\n<span><span style=\"color: #C9D1D9\"> const result: Result </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> proceedPoint.</span><span style=\"color: #D2A8FF\">proceed</span><span style=\"color: #C9D1D9\">();</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> result.data.version </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'v1.0.0'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> return result;</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// info.controller.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Aournd, Result } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { version } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'./aspect/version.aspect'</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Info </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Aournd</span><span style=\"color: #FFA657\">(</span><span style=\"color: #C9D1D9\">version</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">info</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">view</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'info.html'</span><span style=\"color: #C9D1D9\">, {});</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br></div></div><h3 id=\"controller-参数实例\" tabindex=\"-1\"> controller 参数实例</h3>\n<p><a href=\"/development/Decorator.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8F%82%E6%95%B0%E8%A3%85%E9%A5%B0%E5%99%A8-createargdecorator\">createArgDecorator 参考文档</a></p>\n<h2 id=\"扩展\" tabindex=\"-1\"> 扩展</h2>\n<p>想要扩展 <code>Result</code> 的返回方法,请使用 <code>plugin</code> 的扩展方式,示例如下:</p>\n<blockquote>\n<p>扩展带状态的 redirect 方法</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">redirect: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugins/redirect/index.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { IContext, TPlugin, RequestMethod, Result </span><span style=\"color: #FF7B72\">as</span><span style=\"color: #C9D1D9\"> R } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TRedirect2</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">url</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">status</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">number</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Result</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">R</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">static</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">redirect2</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">url</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">status</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">number</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">Result</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> type: </span><span style=\"color: #A5D6FF\">'redirect2'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> data: {</span></span>\n<span><span style=\"color: #C9D1D9\"> url,</span></span>\n<span><span style=\"color: #C9D1D9\"> status,</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> })</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> ()</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> TPlugin </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> results: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">redirect2</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">data</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TRedirect2</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> { </span><span style=\"color: #79C0FF\">url</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #79C0FF\">status</span><span style=\"color: #C9D1D9\"> } </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> data</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> ctx.status </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> status</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> ctx.</span><span style=\"color: #D2A8FF\">redirect</span><span style=\"color: #C9D1D9\">(url)</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br><span>24</span><br><span>25</span><br><span>26</span><br><span>27</span><br><span>28</span><br><span>29</span><br><span>30</span><br><span>31</span><br><span>32</span><br><span>33</span><br></div></div><div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// index.controller.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Result } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../plugins/test/index'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/r'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">extendResult</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">redirect2</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #79C0FF\">301</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.148Z",
"authors": [],
"tags": []
},
{
"title": "路由(Router)",
"url": "https://umajs.github.io/development/Router.html",
"id": "https://umajs.github.io/development/Router.html",
"content_html": "<h1 id=\"路由-router\" tabindex=\"-1\"> 路由(Router)</h1>\n<p>路由主要用于确认如何响应客户端的请求,当用户访问一个地址时,需要找到指定的 controller 的指定方法对用户请求进行处理。确认一个请求主要对请求的两部分:路径和特定 HTTP 请求方法,进行判断。</p>\n<h2 id=\"使用\" tabindex=\"-1\"> 使用</h2>\n<p>为了方便用户对路由的选择,Router 被作为参数的方式传入到 Uma 中。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Router } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/router'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">uma</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> Uma.</span><span style=\"color: #D2A8FF\">instance</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> Router,</span></span>\n<span><span style=\"color: #C9D1D9\"> ROOT: __dirname,</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">uma.</span><span style=\"color: #D2A8FF\">start</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">8058</span><span style=\"color: #C9D1D9\">)</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br></div></div><h2 id=\"path-修饰器\" tabindex=\"-1\"> @Path 修饰器</h2>\n<p>如果你不想通过默认路由的方式访问时,<code>Uma</code>提供了<code>@Path修饰器</code>来指定 controller 方法被访问的 URI 格式。</p>\n<blockquote>\n<p>可以装饰 class,作为跟路由,只装饰 class 不生效,必须和 method 装饰配合使用。装饰 class 只有能有一个 string 参数\n可以装饰 method,没有根路由的时候直接作为路由使用,有根路由的时候和根路由组合使用</p>\n<p>export declare function Path(...args: [...string[]] | [TPathObjArgs]): Function;</p>\n<p>args 路由参数 eg:</p>\n<p>Path() // 仅在 class 有路由装饰时 装饰 method 使用</p>\n<p>Path('/p1')</p>\n<p>Path('/p1', 'p2')</p>\n<p>Path({ value: '/p1' })</p>\n<p>Path({ value: '/p1', method: RequestMethod.GET })</p>\n<p>Path({ value: ['/p1', '/p2'], method: RequestMethod.GET })</p>\n<p>Path({ value: ['/p1', '/p2'], method: [RequestMethod.GET, RequestMethod.POST] })</p>\n</blockquote>\n<h3 id=\"修饰-class\" tabindex=\"-1\"> 修饰 class</h3>\n<p>@Path 修饰器除了能修饰方法外,还可以修饰 controller 的 class,被修饰后的 class,如果内层的方法同时也添加了 @Path 修饰器,那么该方法的访问路径将和 class 上的 @Path 指定路径合并使用。</p>\n<p>例如我们对上面创建的 test.controller.ts 文件做以下修改:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/page'</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #8B949E\">// 根路由</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Test </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">() </span><span style=\"color: #8B949E\">// 路由: /page</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/home'</span><span style=\"color: #FFA657\">) </span><span style=\"color: #8B949E\">// 路由: /page/home</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is page/index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">test</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is test/index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br></div></div><p>在浏览器地址栏通过访问<code>127.0.0.1:端口号/page/home</code> 或 <code>127.0.0.1:端口号/page/</code>就可以看到页面显示出<code>this is page/index router</code>。</p>\n<blockquote>\n<p>注意:v2.0 版本之后,框架取消了文件默认路由,即我们不能通过<code>127.0.0.1:端口号/page/test</code>访问到目标函数,接口将会返回 Not Found。请确保所有路由都被<code>@Path</code>装饰。</p>\n<p>同时,访问<code>127.0.0.1:端口号/page</code>也可以看到页面显示出<code>this is test/index router</code></p>\n</blockquote>\n<h3 id=\"修饰方法\" tabindex=\"-1\"> 修饰方法</h3>\n<p>例如我们对上面创建的 test.controller.ts 文件做以下修改:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Test </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/home'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is test/index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br></div></div><p>在浏览器地址栏通过访问<code>127.0.0.1:端口号/home</code>就可以看到页面显示出<code>this is test/index router</code>。</p>\n<blockquote>\n<p>注意:此时,在浏览器地址栏访问<code>127.0.0.1:端口号/test/index</code>就不能访问到 index 方法了,因为在<code>Uma</code>中,被@Path 修饰器修饰过的方法,不能再通过默认路由的方式访问。</p>\n</blockquote>\n<h3 id=\"methodtype\" tabindex=\"-1\"> MethodType</h3>\n<p>在很多访问中,我们需要加入 MethodType 的限制,示例如下:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path, RequestMethod } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Test </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">({ </span><span style=\"color: #C9D1D9\">value: </span><span style=\"color: #A5D6FF\">'/home'</span><span style=\"color: #FFA657\">, </span><span style=\"color: #C9D1D9\">method: RequestMethod.</span><span style=\"color: #79C0FF\">POST</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">})</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is test/index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br></div></div><p>在浏览器地址栏通过访问<code>127.0.0.1:端口号/home</code>会展示 NOT FOUND,这是因为限制了只能采用 POST 访问。</p>\n<blockquote>\n<p>注意:框架内置了 POST 请求处理 <code>koa-body</code>,如果需要开启,实例化 <code>Uma</code> 时需要传入 <code>bodyParse</code> 参数,并且安装 <code>koa-body</code> 依赖</p>\n</blockquote>\n<h3 id=\"指定多个路径\" tabindex=\"-1\"> 指定多个路径</h3>\n<p>同一个方法上允许设置多个 Path 路径。</p>\n<p>例如我们对上面创建的 test.controller.ts 文件做以下修改:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/page'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Test </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/home'</span><span style=\"color: #FFA657\">, </span><span style=\"color: #A5D6FF\">'/abc'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is test/index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br></div></div><p>在浏览器地址栏通过访问<code>127.0.0.1:端口号/page/home</code>或者<code>127.0.0.1:端口号/page/abc</code>都可以看到页面显示出<code>this is test/index router</code>。</p>\n<p>也可以通过多个@Path 修饰器修饰的方式指定多个路径。</p>\n<p>例如我们对上面创建的 test.controller.ts 文件做以下修改:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/page'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Test </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/home'</span><span style=\"color: #FFA657\">, </span><span style=\"color: #A5D6FF\">'/abc'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/test'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is test/index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><p>在浏览器地址栏通过访问<code>127.0.0.1:端口号/page/home</code>或者<code>127.0.0.1:端口号/page/abc</code>或者<code>127.0.0.1:端口号/page/test</code>都可以看到页面显示出<code>this is test/index router</code>。</p>\n<p>和方法不同,一个 class 只允许使用一个@Path 修饰器,同时一个@Path 修饰器只接收一个参数。</p>\n<p>例如我们对上面创建的 test.controller.ts 文件做以下修改:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/page'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/tpl'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Test </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/home'</span><span style=\"color: #FFA657\">, </span><span style=\"color: #A5D6FF\">'/abc'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/test'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is test/index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><p>此时,只有最上面的<code>@Path('/page')</code>生效了,因为修饰器会先执行最接近自己的,@Path('/tpl')先被作用,但是@Path('/page')又将它覆盖了。</p>\n<p>同样,如果你在 class 上设置<code>@Path('/page', '/tpl')</code>这种传入多个参数的格式,程序会报错,因为修饰 class 时,@Path 只接收一个参数。</p>\n<h3 id=\"正则匹配\" tabindex=\"-1\"> 正则匹配</h3>\n<p>我们对上面这种直接使用具体字符串形式设置的路由称为<code>静态路由</code>,路径除了使用<code>/home</code>这种字符串的格式外,还支持使用正则形式,我们称之为<code>正则路由</code>。</p>\n<p>例如我们对上面创建的 test.controller.ts 文件做以下修改:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/page'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Test </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/:name'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is test/index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br></div></div><p>在浏览器地址栏通过访问<code>127.0.0.1:端口号/page/任意字符</code>都可以看到页面显示出<code>this is test/index router</code>。同时,我们可以通过<code>@Param修饰器</code>或者<code>ctx.params</code>的方式获取到当前<code>name</code>的值,@Param 修饰器会在后面介绍。</p>\n<p>正则路由通过<a href=\"https://github.com/pillarjs/path-to-regexp\" target=\"_blank\" rel=\"noopener noreferrer\">path-to-regexp</a>库进行匹配,具体格式格式参考 path-to-regexp 库。</p>\n<h3 id=\"匹配顺序\" tabindex=\"-1\"> 匹配顺序</h3>\n<p><code>Uma</code>会按照的指定顺序去匹配路由,当命中某一规则时,即进入该 controller 的方法中,了解匹配的顺序当我们设置了重复的路由时很有帮助。</p>\n<p><code>Uma</code>匹配路由的顺序如下:</p>\n<p><img src=\"@source/../public/images/Router-rule.png\" alt=\"images\"></p>\n<p>请求进来时,会先从静态路由中查找是否有匹配到的,没有的话会从正则路由中匹配是否有满足的,还未找到的话会按照静态路由的格式查找是否有匹配的,当这几种情况都不满足时,返回 Not Found。</p>\n<h3 id=\"path-扩展\" tabindex=\"-1\"> Path 扩展</h3>\n<p>框架在 <code>@Path</code> 装饰器的基础上还提供了一些其它快捷的路由装饰器 <a href=\"/other/path.html\">@umajs/path</a></p>\n<h2 id=\"路由参数处理\" tabindex=\"-1\"> 路由参数处理</h2>\n<p>在上面的正则路由中我们提到过@Param 修饰器,<code>UMajs</code>中默认只提供了两种修饰器@Param 和@Query 来方便的获取请求中的参数。对于更丰富的参数处理场景,框架提供了一个专门处理参数的装饰器工具包,<a href=\"/other/ArgDecorator.html\">@umajs/arg-decorator</a>;方便开发者对参数进行接收,校验判断和类型转换。</p>\n<h3 id=\"param-query-参数处理\" tabindex=\"-1\"> @Param,@Query 参数处理</h3>\n<p>例如我们对上面创建的 test.controller.ts 文件做以下修改:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Param, Query } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/arg-decorator'</span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/page'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Test </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/:name'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">(@</span><span style=\"color: #D2A8FF\">Param</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'name'</span><span style=\"color: #FFA657\">) name</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #FFA657\">, @</span><span style=\"color: #D2A8FF\">Query</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'name'</span><span style=\"color: #FFA657\">) title</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #FFA657\">) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">`name: ${</span><span style=\"color: #C9D1D9\">name</span><span style=\"color: #A5D6FF\">}`</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">`title: ${</span><span style=\"color: #C9D1D9\">title</span><span style=\"color: #A5D6FF\">}`</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is test/index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><p>在浏览器中访问<code>127.0.0.1:端口号/page/test?name=uma</code>,我们可以看到控制台打印出:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">name: </span><span style=\"color: #79C0FF\">test</span></span>\n<span><span style=\"color: #C9D1D9\">title: uma</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br></div></div><p>@Param 和@Query 修饰器可以快捷的获取到请求中的 param 和 query 参数,@Param 传入的名称要和@Path 中设置的名称一致,@Query 传入的名称要和请求的 query 参数名称一致,才能正确获取到。</p>\n<p>同时,使用@Param 和@Query 修饰器不区分参数顺序</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #C9D1D9\">(@</span><span style=\"color: #D2A8FF\">Param</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'name'</span><span style=\"color: #C9D1D9\">) name: string, @</span><span style=\"color: #D2A8FF\">Query</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'name'</span><span style=\"color: #C9D1D9\">) title: string)</span></span>\n<span><span style=\"color: #8B949E\">// 参数顺序变化也可以正确获取</span></span>\n<span><span style=\"color: #FF7B72\">+</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #C9D1D9\">(@</span><span style=\"color: #D2A8FF\">Query</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'name'</span><span style=\"color: #C9D1D9\">) title: string, @</span><span style=\"color: #D2A8FF\">Param</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'name'</span><span style=\"color: #C9D1D9\">) name: string)</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br></div></div><p>当然,除了通过@Param 和@Query 修饰器的方式获取参数外,<code>Uma</code>还保留了 koa 的参数获取方式,可以从上下文中获取:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Param, Query } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/arg-decorator'</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/page'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Test </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/:name'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">(@</span><span style=\"color: #D2A8FF\">Param</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'name'</span><span style=\"color: #FFA657\">) name</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #FFA657\">, @</span><span style=\"color: #D2A8FF\">Query</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'name'</span><span style=\"color: #FFA657\">) title</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #FFA657\">) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// ====> 从ctx中获取参数</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.param.name)</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.query.title)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'this is test/index router'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br></div></div><p><strong>对于POST类型路由请求,参数获取和处理请查看<a href=\"/other/ArgDecorator.html#%E7%A4%BA%E4%BE%8B\">@Body</a></strong></p>\n",
"date_modified": "2023-03-17T10:20:25.148Z",
"authors": [],
"tags": []
},
{
"title": "服务(Service)",
"url": "https://umajs.github.io/development/Service.html",
"id": "https://umajs.github.io/development/Service.html",
"content_html": "<h1 id=\"服务-service\" tabindex=\"-1\"> 服务(Service)</h1>\n<h2 id=\"使用\" tabindex=\"-1\"> 使用</h2>\n<h3 id=\"cli-工具在初始化会自动生成-service-目录-可直接在-service-目录中编写-service\" tabindex=\"-1\"> cli 工具在初始化会自动生成 service 目录,可直接在 service 目录中编写 service</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #c9d1d9\">app\n|- src\n |-middleware\n |-config\n |-controller\n |-service\n |-demo.service.ts\n</span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><h3 id=\"命名规范-service-ts\" tabindex=\"-1\"> 命名规范: <code>*.service.ts</code></h3>\n<h3 id=\"编写-service-时需继承默认-baseservice-以便我们将-service-挂载到-ctx-中\" tabindex=\"-1\"> 编写 service 时需继承默认 baseService 以便我们将 service 挂载到 ctx 中</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseService } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> demo </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseService</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">demoService</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'this is demo service'</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><h3 id=\"controller-中使用\" tabindex=\"-1\"> controller 中使用</h3>\n<ul>\n<li>引入 service</li>\n<li>依赖注入 <code>@Service(serviceClazz)</code> , <em>注意</em>:在V2之后,Service参数装饰器只接受class类型参数。不再支持传入文件名字符串。</li>\n<li>注入之后可直接使用无需再进行实例</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// controller</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> DemoService </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../service/demo.service'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Service</span><span style=\"color: #FFA657\">(</span><span style=\"color: #C9D1D9\">DemoService</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> demoService</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> DemoService</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/demo'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">demoService</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// return this.demoService.loadAll();</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br></div></div><div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// service</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseService } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Demp </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseService</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">loadAll</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// return</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br></div></div><h3 id=\"在非-controller-中使用-service-时-必须传入-ctx-进行实例化才能使用。\" tabindex=\"-1\"> 在非 Controller 中使用 Service 时,必须传入 ctx 进行实例化才能使用。</h3>\n<blockquote>\n<p>如果<code>Service</code>不需要传入<code>ctx</code> ,则无需继承<code>BaseService</code></p>\n</blockquote>\n<ul>\n<li>在插件中使用</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> DemoService </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../service/demo.service'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> (uma</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Uma, options</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #FFA657\"> {})</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Koa.Middleware </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> (ctx, next) </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> const demoService: DemoService </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">DemoService</span><span style=\"color: #C9D1D9\">(ctx);</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// ...</span></span>\n<span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\">};</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br></div></div><ul>\n<li>在 Around 面向切面编程时使用</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// src/aspect/demo.aspect.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> DemoService </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../service/demo.service'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">async</span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">around</span><span style=\"color: #FFA657\">(</span><span style=\"color: #C9D1D9\">proceedPoint</span><span style=\"color: #FFA657\">: </span><span style=\"color: #C9D1D9\">IProceedJoinPoint</span><span style=\"color: #FFA657\">) {</span></span>\n<span><span style=\"color: #FFA657\"> const { </span><span style=\"color: #C9D1D9\">target</span><span style=\"color: #FFA657\">, </span><span style=\"color: #C9D1D9\">proceed</span><span style=\"color: #FFA657\">, </span><span style=\"color: #C9D1D9\">args </span><span style=\"color: #FFA657\">} </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">proceedPoint</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">demoService</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">DemoService</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">DemoService</span><span style=\"color: #C9D1D9\">(target.ctx)</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">result</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">proceed</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FF7B72\">...</span><span style=\"color: #C9D1D9\">args)</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> result</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br></div></div><p><strong>此外,框架还提供了@Resource 和@Inject 装饰器来实现<code>IOC容器</code>和<code>依赖注入</code></strong></p>\n<p><a href=\"/development/IOC.html\">IOC 参考文档</a></p>\n",
"date_modified": "2023-03-17T10:20:25.148Z",
"authors": [],
"tags": []
},
{
"title": "Uma 对象",
"url": "https://umajs.github.io/development/Uma.html",
"id": "https://umajs.github.io/development/Uma.html",
"content_html": "<h1 id=\"uma-对象\" tabindex=\"-1\"> Uma 对象</h1>\n<p>框架向外暴露了 Uma 对象,方便在项目中随时调用</p>\n<h2 id=\"api\" tabindex=\"-1\"> API</h2>\n<h3 id=\"uma-env\" tabindex=\"-1\"> uma.env</h3>\n<p>当前运行环境,可以在入口文件中定义</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// app.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> Uma </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Router } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/router'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">uma</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> Uma.</span><span style=\"color: #D2A8FF\">instance</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> Router,</span></span>\n<span><span style=\"color: #C9D1D9\"> ROOT: __dirname,</span></span>\n<span><span style=\"color: #C9D1D9\"> env: process.argv.</span><span style=\"color: #D2A8FF\">indexOf</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'production'</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #79C0FF\">1</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">?</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'production'</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'development'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">uma.</span><span style=\"color: #D2A8FF\">start</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">8058</span><span style=\"color: #C9D1D9\">)</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><h3 id=\"uma-config\" tabindex=\"-1\"> uma.config</h3>\n<p>当前项目正在使用的配置信息,对 <code>config</code> 目录下的配置进行处理后得到</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">"plugin"</span><span style=\"color: #C9D1D9\">: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">"logger"</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">"model"</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">true</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">"status"</span><span style=\"color: #C9D1D9\">: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">"_404"</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">"[object, function]"</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br></div></div><h3 id=\"uma-options\" tabindex=\"-1\"> uma.options</h3>\n<p>初始化<code>Uma</code>时传入的参数,参数包括</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TUmaOption</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 路由</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">Router</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Function</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 代码根路径,用于加载代码</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">ROOT</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 运行环境</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">env</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'development'</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'production'</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 配置文件夹路径</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">configPath</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 需要拿到真实用户ip时设置为true</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">proxy</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">subdomainOffset</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">number</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">jsonpBody</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TJsonpBody</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 自带 koa-body 时的配置,不配置时 koa-body 中间件不生效</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">bodyParser</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">bodyParser</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #FFA657\">IKoaBodyOptions</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">createServer</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> (</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">cb</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> (</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">req</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IncomingMessage</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Http2ServerRequest</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">res</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">ServerResponse</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Http2ServerResponse</span></span>\n<span><span style=\"color: #C9D1D9\"> ) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">void</span></span>\n<span><span style=\"color: #C9D1D9\"> ) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Server</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">beforeLoad</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">uma</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Uma</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">void</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">afterLoaded</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">uma</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Uma</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">void</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br><span>24</span><br></div></div><h3 id=\"uma-app\" tabindex=\"-1\"> uma.app</h3>\n<p><code>Koa Application</code>对象的实例,初始化时生成</p>\n<h3 id=\"uma-start-port-number-8058\" tabindex=\"-1\"> uma.start(port: number = 8058)</h3>\n<p><code>Uma</code>启动方法,需要在初始化时调用,默认端口是 8058</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// app.ts</span></span>\n<span><span style=\"color: #8B949E\">// ===> 调用start方法启动项目</span></span>\n<span><span style=\"color: #C9D1D9\">uma.</span><span style=\"color: #D2A8FF\">start</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">8058</span><span style=\"color: #C9D1D9\">)</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br></div></div><h3 id=\"beforeload-afterload\" tabindex=\"-1\"> beforeLoad, afterLoad</h3>\n<p>服务启动前后的钩子函数,传入当前 uma 实例</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">uma</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> Uma.</span><span style=\"color: #D2A8FF\">instance</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> ROOT: __dirname,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">beforeLoad</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">uma</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Uma</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 服务开始启动</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">afterLoad</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">uma</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Uma</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 服务启动完成</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br></div></div><h2 id=\"静态方法\" tabindex=\"-1\"> 静态方法</h2>\n<h3 id=\"instance\" tabindex=\"-1\"> instance</h3>\n<p>获取/实例化 Uma,实例化必须传参,获取实例化后的 Uma 不用传参</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static </span><span style=\"color: #D2A8FF\">instance</span><span style=\"color: #C9D1D9\">(options</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> TUmaOption): Uma;</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"获取运行环境\" tabindex=\"-1\"> 获取运行环境</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static get </span><span style=\"color: #D2A8FF\">env</span><span style=\"color: #C9D1D9\">(): string;</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"获取-app\" tabindex=\"-1\"> 获取 app</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static get </span><span style=\"color: #D2A8FF\">app</span><span style=\"color: #C9D1D9\">(): Koa</span><span style=\"color: #FF7B72\"><</span><span style=\"color: #C9D1D9\">Koa.DefaultState, IContext</span><span style=\"color: #FF7B72\">></span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"获取-server\" tabindex=\"-1\"> 获取 server</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static get </span><span style=\"color: #D2A8FF\">server</span><span style=\"color: #C9D1D9\">(): http.Server </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> https.Server;</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"options\" tabindex=\"-1\"> options</h3>\n<p>获取运行 Uma 的参数</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static get </span><span style=\"color: #D2A8FF\">options</span><span style=\"color: #C9D1D9\">(): TUmaOption;</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"config\" tabindex=\"-1\"> config</h3>\n<p>获取所有 Uma 的配置</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static get </span><span style=\"color: #D2A8FF\">config</span><span style=\"color: #C9D1D9\">(): TConfig;</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"获取插件配置\" tabindex=\"-1\"> 获取插件配置</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static get </span><span style=\"color: #D2A8FF\">pluginConfig</span><span style=\"color: #C9D1D9\">(): {</span></span>\n<span><span style=\"color: #C9D1D9\"> [pluginName: string]: boolean </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">"../types/TPluginConfig"</span><span style=\"color: #C9D1D9\">).TPluginConfig;</span></span>\n<span><span style=\"color: #C9D1D9\"> };</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br></div></div><h3 id=\"获取生效的-plugin-key\" tabindex=\"-1\"> 获取生效的 plugin key</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static get </span><span style=\"color: #D2A8FF\">pluginKeys</span><span style=\"color: #C9D1D9\">(): any[];</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"或者某个插件的参数\" tabindex=\"-1\"> 或者某个插件的参数</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static </span><span style=\"color: #D2A8FF\">pluginOptions</span><span style=\"color: #C9D1D9\">(pluginName: string): object;</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"context\" tabindex=\"-1\"> context</h3>\n<p>获取 context,可以对 context 进行扩展等。实例化之后就是我们使用的 ctx</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static get </span><span style=\"color: #D2A8FF\">context</span><span style=\"color: #C9D1D9\">(): Koa.BaseContext </span><span style=\"color: #FF7B72\">&</span><span style=\"color: #C9D1D9\"> IContext;</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"controllersinfo\" tabindex=\"-1\"> controllersInfo</h3>\n<p>获取实例化之后的 controller 信息,包括 controller、route 等</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> static get </span><span style=\"color: #D2A8FF\">controllersInfo</span><span style=\"color: #C9D1D9\">(): IterableIterator</span><span style=\"color: #FF7B72\"><import</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">".."</span><span style=\"color: #C9D1D9\">).TControllerInfo</span><span style=\"color: #FF7B72\">></span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.149Z",
"authors": [],
"tags": []
},
{
"title": "Uma 与 Koa",
"url": "https://umajs.github.io/newbieGuide/Uma.html",
"id": "https://umajs.github.io/newbieGuide/Uma.html",
"content_html": "<h1 id=\"uma-与-koa\" tabindex=\"-1\"> Uma 与 Koa</h1>\n<blockquote>\n<p>使用客户端与服务端通用开发语言的问题是一直是开发者需要面临的问题,而 NodeJs 的出现使得 JavaScript 一跃成为最流行的 web 开发语言。各类 node web 框架层出不穷,其中不乏著名的 Express、Koa......</p>\n</blockquote>\n<h2 id=\"koa\" tabindex=\"-1\"> Koa</h2>\n<p>Express 无疑是使用最广泛的 node 框架,从 github start 可以看出来其受欢迎的程度,但基于 ECMAScript 版本的变化,Express 很多功能受到 ES5 的约束,比如一直令人头疼的<a href=\"http://callbackhell.com/\" target=\"_blank\" rel=\"noopener noreferrer\">Callback Hell</a>。</p>\n<p>为解决一系列问题,<a href=\"https://github.com/tj\" target=\"_blank\" rel=\"noopener noreferrer\">TJ</a>发现对 Express 进行重构似乎更加困难,于是就有了现在的 Koa。</p>\n<h3 id=\"架构设计\" tabindex=\"-1\"> 架构设计</h3>\n<p>Express 一体式的架构设计能够让开发者快速的搭建一个 node server,其自身集成了例如\n<a href=\"https://expressjs.com/en/starter/static-files.html\" target=\"_blank\" rel=\"noopener noreferrer\">static</a>、\n<a href=\"https://expressjs.com/en/guide/routing.html\" target=\"_blank\" rel=\"noopener noreferrer\">router</a>、\n<a href=\"https://expressjs.com/en/guide/using-template-engines.html\" target=\"_blank\" rel=\"noopener noreferrer\">views</a>\n等功能,能够为开发者提供静态文件、路由方法、模板引擎等服务。庞大的社区也为其提供了众多中间件模块,其成熟稳定的生态环境是众多开发者选择的关键因素。但是这也使整个框架显得较为厚重,毕竟一部分功能开发者可能并不会使用到。</p>\n<p>而 Koa 则是摒弃了原有思想,致力于实现一个轻量级应用框架,事实上它确实非常轻巧,只有大约 550 行代码。它将原有功能进行拆分,分包成各个模块,因此拥有大量有用的方法但占用空间很小,开发者可以根据需要进行引用。</p>\n<h3 id=\"middleware\" tabindex=\"-1\"> Middleware</h3>\n<p>核心设计的不同也使得 Koa 与 Express 风格的中间件不兼容,大量原社区资源无法直接利用。</p>\n<ul>\n<li><strong>模型</strong></li>\n</ul>\n<p>相比 Express 中间件执行的线性流程,Koa 采用堆栈形式的先进后出,可以更全面的对 HTTP 流程做出响应,下图为 Koa 洋葱模型:<br>\n<img src=\"@source/../public/images/koaOnion.png\" alt=\"Koa onion\"></p>\n<p>Express 中间件只有两个参数 request 与 response,Koa 2.x 比 Express 增加了一个上下文的对象\n<a href=\"https://github.com/koajs/koa/blob/master/docs/api/context.md\" target=\"_blank\" rel=\"noopener noreferrer\">Context</a>,\n并且将 request 与 response 挂载在 context 上作为第一个参数传入。</p>\n<p>在 Koa 中开发者可以很方便地对 ctx 对象进行拓展,并且在所有中间件中进行共享。</p>\n<h3 id=\"error-handling\" tabindex=\"-1\"> Error handling</h3>\n<p>Express 附带一个错误处理程序,但使用起来较为繁琐,对于异步代码需要手动调用 next 传递错误信息。<br>\nKoa 配合 <code>try..catch..</code> 的错误处理方式便显得更加优雅。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">app.</span><span style=\"color: #D2A8FF\">use</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">next</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">try</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">()</span></span>\n<span><span style=\"color: #C9D1D9\"> } </span><span style=\"color: #FF7B72\">catch</span><span style=\"color: #C9D1D9\"> (err) {</span></span>\n<span><span style=\"color: #C9D1D9\"> ctx.status </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> err.status </span><span style=\"color: #FF7B72\">||</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">500</span></span>\n<span><span style=\"color: #C9D1D9\"> ctx.body </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> { info: </span><span style=\"color: #A5D6FF\">'error...'</span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> ctx.app.</span><span style=\"color: #D2A8FF\">emit</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'error'</span><span style=\"color: #C9D1D9\">, err, </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br></div></div><h2 id=\"uma\" tabindex=\"-1\"> Uma</h2>\n<p>使用 Koa,你可以很快构建出性能出色的 Web 应用程序,不再被回调所困扰、更快的处理错误......但 Koa 作为一个轻量级框架它更多地只是提供一些基础性服务。</p>\n<p>Uma 在 Koa 2 的基础上对其进行了拓展,致力于为开发者提供一个更加强大、便捷、易于开发和维护的企业级 Web 应用框架。</p>\n<h2 id=\"架构\" tabindex=\"-1\"> 架构</h2>\n<p><img src=\"@source/../public/images/design.png\" alt=\"image\"></p>\n<h2 id=\"流程图\" tabindex=\"-1\"> 流程图</h2>\n<p><img src=\"@source/../public/images/process.png\" alt=\"image\"></p>\n<blockquote>\n<p>用户请求达到 router</p>\n<p>router 解析请求穿过 plugin 中的中间件,然后到达 controller</p>\n<p>controller 可以通过 IOC 调用 service 和 resource</p>\n<p>controller、service、resource 等可以通过 AOP 的 Around 进行切面开发</p>\n<p>controller 返回 Result,Umajs 解析 Result 按 Koa 框架格式返回数据</p>\n<p>AOP 可以对 controller、service、resource 进行切面开发,还可以将 middleware 封装成 Around 对 controller 进行切页面开发</p>\n<p>中间件(middleware)有提供两种形式使用,一种是插件配置(plugin.config.ts),一种是封装成 Around 以装饰器形式使用</p>\n<p>Plugin 有两种形式进行扩展,一种中间件形式、一种复合形式</p>\n</blockquote>\n<h2 id=\"特性\" tabindex=\"-1\"> 特性</h2>\n<h3 id=\"typescript\" tabindex=\"-1\"> TypeScript</h3>\n<p>如果你有过 Java 开发经验,那你一定体会过静态语言所带来的优势。\n<a href=\"https://www.typescriptlang.org/\" target=\"_blank\" rel=\"noopener noreferrer\">TypeScript</a>\n作为 JavaScript 的超集,使得 JS 能够实现静态类型检测,更加有利于构建复杂的大型项目。</p>\n<p>Uma 使用 TS 进行源码开发,我们强烈建议开发者配合使用 <code>Uma</code> + <code>TS</code> 。</p>\n<ul>\n<li><strong>易于理解</strong></li>\n</ul>\n<p>代码中有函数参数类型、返回值类型、变量类型以及泛型约束这些类型信息作为辅助,能让生疏的代码更易于理解。这在接手新项目、阅读开源代码以及代码评审实践中都能带来很多便利。</p>\n<ul>\n<li><strong>IDE 支持</strong></li>\n</ul>\n<p>由于静态类型的原因,一些 IDE 能够为开发者提供比往常更多的预测性辅助功能,如智能补全与路径跟踪。如果你不想在运行时才发现一堆错误提示,那么 TS 将是一个很好的选择。</p>\n<ul>\n<li><strong>新特性与兼容</strong></li>\n</ul>\n<p>TS 较好的兼容了一些未来语法,你可以使用 ES6、ES7 及更高版本中的新功能,编译器会为你将他们转换为 ES5 或者你所指定的内容。</p>\n<h3 id=\"ioc-di\" tabindex=\"-1\"> IOC / DI</h3>\n<p>事实上\n<a href=\"https://www.tutorialsteacher.com/ioc/inversion-of-control\" target=\"_blank\" rel=\"noopener noreferrer\">控制反转</a>与\n<a href=\"https://www.tutorialsteacher.com/ioc/dependency-injection\" target=\"_blank\" rel=\"noopener noreferrer\">依赖注入</a>\n是同一个概念,Uma 框架设计继承了这样的思想,你可以将与核心业务无关的代码抽离出去交给系统来为你寻找依赖,这对于代码解耦有着重要的意义。</p>\n<p>对于某几个类,你可以选择不使用 DI,但是对于一个大型项目来说依赖管理要复杂得多,而 Uma 框架可以很好的来帮助你管理你的依赖项和对象之间的交互。特别是在编写单元测试时,你可以独立于其他对象添加和测试对象,而不需要设置任何无关项。</p>\n<h3 id=\"aop\" tabindex=\"-1\"> AOP</h3>\n<p>AOP(面向切面编程)扩展了传统的 OOP(面向对象编程)模型,以改善跨不同对象层次结构的代码重用。AOP 基本概念是一个切面,这是一种常见的行为,通常分散在方法,类,对象层次结构甚至整个对象模型中。</p>\n<p>例如:我们需要在代码中添加日志功能,但日志打印并不是我们核心业务需要关注的。<br>\n在 AOP 中,日志功能作为横切关注点,会建议将其抽象化并封装到一个切面中去。</p>\n<p>Uma 提供 @Around 装饰器作为 IOC 容器,你可以在 aspect 文件夹下新建自己的切面,实现5 类通知:</p>\n<ul>\n<li>前置通知:在目标方法之前执行</li>\n<li>后置通知:在目标方法之后执行</li>\n<li>异常通知:当执行目标方法出现异常时执行</li>\n<li>最终通知:当目标方法有返回值之后执行,在后置通知之后</li>\n<li>环绕通知:在最开始调用时执行,会将目标方法作为参数传入,对目标方法(proceed)及入参(args)、出参(result)进行拦截。</li>\n</ul>\n\n<p>开发者可以通过调用@Around(func)的方式在类或方法中织入切面。</p>\n<p>更多使用方式可查看<a href=\"/development/AOP.html\">AOP</a>一节。</p>\n",
"date_modified": "2023-03-17T10:20:25.164Z",
"authors": [],
"tags": []
},
{
"title": "框架介绍",
"url": "https://umajs.github.io/newbieGuide/introduce.html",
"id": "https://umajs.github.io/newbieGuide/introduce.html",
"content_html": "<h1 id=\"框架介绍\" tabindex=\"-1\"> 框架介绍</h1>\n<p><img src=\"@source/../public/images/UMajsV2.png\" alt=\"image\"></p>\n<p><code>Umajs</code> 是基于 Koa2 使用 TypeScript 开发、通过装饰器使用大部分功能的 Web 框架。</p>\n<h2 id=\"特性\" tabindex=\"-1\"> 特性</h2>\n<ul>\n<li>基于 Koa2,兼容 middleware</li>\n<li>统一响应 (Result), 让 Controller 响应数据更便捷清晰</li>\n<li>装饰器 (Decorator),代码组织更优雅方便</li>\n<li>自定义装饰器 (createArgDecorator), 可以快速的扩展参数装饰器,用于参数校验、参数转换、参数聚合等</li>\n<li>面向切面 (AOP),基于装饰器的 <code>Around</code> 可以很方便的对任意方法进行拦截、修改等,并且能将中间件转换成 <code>Around</code> 使用</li>\n<li>依赖注入 (IOC),模块依赖不再需要引入和实例化</li>\n<li>插件、切面形式让中间件(Middleware)使用更优雅</li>\n<li>高稳定高性能,单元测试覆盖全</li>\n<li>路由分层,优化路由寻址</li>\n<li>推荐 TS 开发,开发维护更清晰,对于依赖注入的方法使用也更便捷</li>\n<li>统一约束和规范</li>\n</ul>\n<h2 id=\"特性展示\" tabindex=\"-1\"> 特性展示</h2>\n<p>下面代码展示了以下几个特性:</p>\n<blockquote>\n<p>1、通过 <code>createArgDecorator</code> 创建参数装饰器,对 <code>age</code> 参数进行校验和类型转换</p>\n<p>2、controller 通过框架提供的 <code>Result</code> 便捷的响应数据</p>\n<p>3、<code>Around</code>切面装饰器方法进行方法的拦截,对方法的 <code>参数</code> 进行校验, 对 <code>返回值</code> 进行校验/修改</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// index.controller.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> Method </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'./method.aspect'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { AgeCheck } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'./ArgDecorator'</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Around</span><span style=\"color: #C9D1D9\">(Method) </span><span style=\"color: #8B949E\">// 可以装饰在类上对所有方法进行装饰</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">// @Around(Method) // 可以装饰在方法上对单一方法进行装饰</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/hello'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">(@</span><span style=\"color: #D2A8FF\">Query</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'name'</span><span style=\"color: #FFA657\">) name</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #FFA657\">, @</span><span style=\"color: #D2A8FF\">AgeCheck</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'age'</span><span style=\"color: #FFA657\">) age</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">number</span><span style=\"color: #FFA657\">) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">json</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> name,</span></span>\n<span><span style=\"color: #C9D1D9\"> age,</span></span>\n<span><span style=\"color: #C9D1D9\"> })</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br></div></div><div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// ArgDecorator.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">AgeCheck</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">createArgDecorator</span><span style=\"color: #C9D1D9\">((</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">ageKey</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">let</span><span style=\"color: #C9D1D9\"> age </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">number</span><span style=\"color: #C9D1D9\">><</span><span style=\"color: #7EE787\">unknown</span><span style=\"color: #C9D1D9\">>ctx.query[ageKey];</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> if (age === undefined) return Result.json({</span></span>\n<span><span style=\"color: #C9D1D9\"> code: </span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> msg: </span><span style=\"color: #A5D6FF\">'请加上 age 参数'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> });</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> age = +age;</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> if (Number.isNaN(age) || age < 0 || age > 120) return Result.json({</span></span>\n<span><span style=\"color: #C9D1D9\"> code: </span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> msg: </span><span style=\"color: #A5D6FF\">'请传入正确的 age 参数'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> });</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> return age;</span></span>\n<span><span style=\"color: #C9D1D9\">});</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br></div></div><div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// method.aspect.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { IProceedJoinPoint } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">method</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">proceedPoint</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IProceedJoinPoint</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> const { proceed, args } </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> proceedPoint;</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 校验参数</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">if</span><span style=\"color: #C9D1D9\"> (args[</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\">] </span><span style=\"color: #FF7B72\">!==</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'Umajs'</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'name 必须为 Umajs'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">result</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">proceed</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FF7B72\">...</span><span style=\"color: #C9D1D9\">args);</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">if</span><span style=\"color: #C9D1D9\"> (result.type </span><span style=\"color: #FF7B72\">===</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'json'</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 为 JSON 返回值加上时间戳</span></span>\n<span><span style=\"color: #C9D1D9\"> result.data.time </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">Date</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> result;</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.164Z",
"authors": [],
"tags": []
},
{
"title": "快速开始",
"url": "https://umajs.github.io/newbieGuide/quickstart.html",
"id": "https://umajs.github.io/newbieGuide/quickstart.html",
"content_html": "<h1 id=\"快速开始\" tabindex=\"-1\"> 快速开始</h1>\n<h2 id=\"环境准备\" tabindex=\"-1\"> 环境准备</h2>\n<ul>\n<li>操作系统:支持 macOS,Linux,Windows</li>\n<li>运行环境:支持 Node.js 8.x 及以上版本。</li>\n</ul>\n<h2 id=\"初始化工程\" tabindex=\"-1\"> 初始化工程</h2>\n<h3 id=\"安装-uma-命令\" tabindex=\"-1\"> 安装 Uma 命令</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">$ npm i @umajs/cli -g</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">$ uma</span></span>\n<span><span style=\"color: #C9D1D9\">or</span></span>\n<span><span style=\"color: #C9D1D9\">$ umajs</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><h3 id=\"卸载旧版本命令\" tabindex=\"-1\"> 卸载旧版本命令</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">npm uninstall @umajs/cli -g</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"使用\" tabindex=\"-1\"> 使用</h3>\n<h4 id=\"查看版本\" tabindex=\"-1\"> 查看版本</h4>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">uma -V</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h4 id=\"初始化工程-1\" tabindex=\"-1\"> 初始化工程</h4>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">uma project [projectName]</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h4 id=\"初始化目录结构\" tabindex=\"-1\"> 初始化目录结构</h4>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #79C0FF\">cd</span><span style=\"color: #C9D1D9\"> [projectname]</span></span>\n<span><span style=\"color: #C9D1D9\">npm install</span></span>\n<span><span style=\"color: #C9D1D9\">npm start</span></span>\n<span><span style=\"color: #C9D1D9\">http://127.0.0.1:8058</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><h4 id=\"项目结构\" tabindex=\"-1\"> 项目结构</h4>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">├── src</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── app.ts // 入口</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── aspect // 切面</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── index.aspect.ts</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── config // 配置文件目录</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├──plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── controller // 控制器目录</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├──index.controller.ts</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── plugins //插件</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── error-handler</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── index.ts</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── service //服务</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── test.service.ts</span></span>\n<span><span style=\"color: #C9D1D9\">├── static //静态目录</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── index.html</span></span>\n<span><span style=\"color: #C9D1D9\">├── views //模板目录</span></span>\n<span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> ├── index.html</span></span>\n<span><span style=\"color: #C9D1D9\">├── .eslintrc.js</span></span>\n<span><span style=\"color: #C9D1D9\">├── README.md</span></span>\n<span><span style=\"color: #C9D1D9\">├── package.json</span></span>\n<span><span style=\"color: #C9D1D9\">├── tsconfig.json // ts配置文件</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br></div></div><h4 id=\"保留目录\" tabindex=\"-1\"> 保留目录</h4>\n<blockquote>\n<p>src 中 config、controller、plugins 三个目录为保留目录</p>\n</blockquote>\n<h2 id=\"服务部署\" tabindex=\"-1\"> 服务部署</h2>\n<h3 id=\"生产环境构建\" tabindex=\"-1\"> 生产环境构建</h3>\n<blockquote>\n<p>生产环境部署时,将会把 typescript 编译成 js 后运行。默认构建后 js 源码目录是 app</p>\n</blockquote>\n<h3 id=\"构建并启动命令\" tabindex=\"-1\"> 构建并启动命令</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">npm run build // 会自动先执行lint校验和build命令,然后才启动生产环境代码</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"如何区分多环境配置\" tabindex=\"-1\"> 如何区分多环境配置</h3>\n<blockquote>\n<p>参考 <a href=\"/development/Config.html\">config</a></p>\n</blockquote>\n<h2 id=\"文档和社区\" tabindex=\"-1\"> 文档和社区</h2>\n<ul>\n<li><a href=\"https://github.com/Umajs\" target=\"_blank\" rel=\"noopener noreferrer\">官方站点 && 文档</a></li>\n</ul>\n",
"date_modified": "2023-03-17T10:20:25.164Z",
"authors": [],
"tags": []
},
{
"title": "参数装饰器(ArgDecorator)",
"url": "https://umajs.github.io/other/ArgDecorator.html",
"id": "https://umajs.github.io/other/ArgDecorator.html",
"content_html": "<h1 id=\"参数装饰器-argdecorator\" tabindex=\"-1\"> 参数装饰器(ArgDecorator)</h1>\n<p><code>Umajs</code> 提供了 <code>createArgDecorator</code> 可以很方便的创建自定义参数装饰器,并且框架还提供了如下装饰器直接使用。</p>\n<h2 id=\"使用\" tabindex=\"-1\"> 使用</h2>\n<blockquote>\n<p>安装 <code>npm install -S @umajs/arg-decorator</code></p>\n</blockquote>\n<h2 id=\"示例\" tabindex=\"-1\"> 示例</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Query, Body } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/arg-decorator'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// url参数类型修饰校验</span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/saveUser'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #D2A8FF\">saveUser</span><span style=\"color: #C9D1D9\">(@Query.</span><span style=\"color: #D2A8FF\">ToNumber</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'age'</span><span style=\"color: #C9D1D9\">) age :number) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">`This router queryParms is ${</span><span style=\"color: #C9D1D9\">userId</span><span style=\"color: #A5D6FF\">} ${</span><span style=\"color: #C9D1D9\">age</span><span style=\"color: #A5D6FF\">}`</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// POST参数类型修饰校验</span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">({value:</span><span style=\"color: #A5D6FF\">'/post'</span><span style=\"color: #C9D1D9\">,method:RequestMethod.</span><span style=\"color: #79C0FF\">POST</span><span style=\"color: #C9D1D9\">})</span></span>\n<span><span style=\"color: #D2A8FF\">saveUser</span><span style=\"color: #C9D1D9\">(@Body.</span><span style=\"color: #D2A8FF\">ToNumber</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'age'</span><span style=\"color: #C9D1D9\">) age: number){</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">`This Post body info is ${</span><span style=\"color: #79C0FF\">JSON</span><span style=\"color: #A5D6FF\">.</span><span style=\"color: #79C0FF\">stringify</span><span style=\"color: #A5D6FF\">(</span><span style=\"color: #C9D1D9\">userInfo</span><span style=\"color: #A5D6FF\">)</span><span style=\"color: #A5D6FF\">}`</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br></div></div><p>当接口访问<code>localhost:port//saveUser?age=str</code>时,controller方法将终止执行,并默认返回客户端提示信息</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">"code"</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">"msg"</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">"age 参数必须为数据类型。入参值str"</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><h2 id=\"校验参数装饰器\" tabindex=\"-1\"> 校验参数装饰器</h2>\n<table>\n<thead>\n<tr>\n<th><div style=\"width:450px\">修饰器</div></th>\n<th><div style=\"width:200px\">使用说明</div></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>@Param(id:string)</td>\n<td>动态路由参数修饰</td>\n</tr>\n<tr>\n<td>@Query(id:string)</td>\n<td>url参数修饰器</td>\n</tr>\n<tr>\n<td>@Body(id?:string or Function or string[] or class)</td>\n<td>POST请求参数修饰器 <code>@Body() body:class</code> or <code>@Body('id') id:any</code> or <code>@Body(['name','age']) user: {name:any,age:any}</code></td>\n</tr>\n<tr>\n<td>@Require(id: string,message?:string)</td>\n<td>url参数修饰并做必填校验</td>\n</tr>\n<tr>\n<td>@ToNumber(id: string,message?: string)</td>\n<td>参数修饰并类型转换为number类型 类型转换失败则会终止函数执行并返回提示内容</td>\n</tr>\n<tr>\n<td>@ToBoolean(id: string,message?: string)</td>\n<td>参数修饰并类型转换布尔类型 类型转换失败则会终止函数执行并返回提示内容</td>\n</tr>\n<tr>\n<td>@ToArray(id: string, split?:string ,message?: string)</td>\n<td>参数修饰并类型转换数组 类型转换失败则会终止函数执行并返回提示内容</td>\n</tr>\n<tr>\n<td>@ToDate(id: string,message?: string)</td>\n<td>参数修饰并类型转换为date类型 类型转换失败则会终止函数执行并返回提示内容 备注:参数接受如果为数字也会按照时间强制转换为时间格式。</td>\n</tr>\n<tr>\n<td>@Equals(id: string,comparison?: any)</td>\n<td>参数修饰并做值对比校验</td>\n</tr>\n<tr>\n<td>@NotNull(id: string,message?: string)</td>\n<td>限制必须不为null</td>\n</tr>\n<tr>\n<td>@AssertFalse(id: string,message?: string)</td>\n<td>限制必须为false</td>\n</tr>\n<tr>\n<td>@AssertTrue(id: string,message?: string)</td>\n<td>限制必须为true</td>\n</tr>\n<tr>\n<td>@DecimalMax(id: string,value: number,message?: string)</td>\n<td>限制必须为一个不大于指定值的数字</td>\n</tr>\n<tr>\n<td>@DecimalMin(id: string,value: number,message?: string)</td>\n<td>限制必须为一个不小于指定值的数字</td>\n</tr>\n<tr>\n<td>@Future(id: string,message?: string)</td>\n<td>限制必须是一个将来的日期</td>\n</tr>\n<tr>\n<td>@Max(id: string,value: number,message?: string)</td>\n<td>限制必须为一个不大于指定值的数字</td>\n</tr>\n<tr>\n<td>@Min(id: string,value: number,message?: string)</td>\n<td>限制必须为一个不小于指定值的数字</td>\n</tr>\n<tr>\n<td>@Past(id: string,message?: string)</td>\n<td>限制必须是一个过去的日期</td>\n</tr>\n<tr>\n<td>@Pattern(id: string,pattern: RegExp,message?: string)</td>\n<td>限制必须符合指定的正则表达式</td>\n</tr>\n<tr>\n<td>@Size(id: string,max: number,min: number,message?: string)</td>\n<td>限制字符长度必须在min到max之间</td>\n</tr>\n<tr>\n<td>@NotEmpty(id: string,message?: string)</td>\n<td>验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)</td>\n</tr>\n<tr>\n<td>@NotBlank(id: string,message?: string)</td>\n<td>验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格</td>\n</tr>\n<tr>\n<td>@Email(id: string,message?: string)</td>\n<td>验证注解的元素值是Email</td>\n</tr>\n<tr>\n<td>@Phone(id: string,message?: string)</td>\n<td>验证元素值是手机号 具体格式参考<code>https://github.com/validatorjs/validator.js/blob/master/src/lib/isMobilePhone.js</code></td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"非校验参数修饰器\" tabindex=\"-1\"> 非校验参数修饰器</h2>\n<table>\n<thead>\n<tr>\n<th><div style=\"width:450px\">修饰器</div></th>\n<th>使用说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>@Cookies(id:string)</td>\n<td>cookies 参数修饰器</td>\n</tr>\n<tr>\n<td>@Headers(id:string)</td>\n<td>headers 请求头参数修饰器</td>\n</tr>\n<tr>\n<td>@RequestParam(id:string)</td>\n<td>GET/POST 通用参数修饰器,POST 请求类型时参数获取优先级为:Body < Query 相同参数 url 携带参数覆盖 body 请求体中的属性值</td>\n</tr>\n<tr>\n<td>@RequestFile(field: string)</td>\n<td>文件上传时文件参数修饰器</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"高阶\" tabindex=\"-1\"> 高阶</h2>\n<h3 id=\"body参数装饰器接受class类\" tabindex=\"-1\"> Body参数装饰器接受class类</h3>\n<blockquote>\n<p>当Body传递为class类时,会将请求参数中获取到的数据作为参数调用类构造函数,同时也会进行属性类型校验,校验成功则返回实例化对象。更多class的使用请参考<a href=\"https://github.com/Umajs/class-validator\" target=\"_blank\" rel=\"noopener noreferrer\"><code>@umajs/class-validator</code></a></p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// 定义class</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Type, Required, Min, Model } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/class-validator'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> UserInfo </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">Model</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">constructor</span><span style=\"color: #FFA657\">({ id, name, age }</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> UserInfo, isValid</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #FFA657\">) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">super</span><span style=\"color: #C9D1D9\">(isValid);</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.id </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> id;</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.name </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> name;</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.age </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> age;</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Type</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'number'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> id</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">number</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">123</span><span style=\"color: #FFA657\">;</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Required</span><span style=\"color: #FFA657\">()</span></span>\n<span><span style=\"color: #FFA657\"> name</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #FFA657\">;</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Min</span><span style=\"color: #FFA657\">(</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> age</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">number</span><span style=\"color: #FFA657\">;</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// 参数装饰器使用</span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">({ value: </span><span style=\"color: #A5D6FF\">'/post'</span><span style=\"color: #C9D1D9\">, method: RequestMethod.</span><span style=\"color: #79C0FF\">POST</span><span style=\"color: #C9D1D9\"> })</span></span>\n<span><span style=\"color: #D2A8FF\">model</span><span style=\"color: #C9D1D9\">(@</span><span style=\"color: #D2A8FF\">Body</span><span style=\"color: #C9D1D9\">(UserInfo) userInfo: user) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">`This Post body info is ${</span><span style=\"color: #79C0FF\">JSON</span><span style=\"color: #A5D6FF\">.</span><span style=\"color: #79C0FF\">stringify</span><span style=\"color: #A5D6FF\">(</span><span style=\"color: #C9D1D9\">userInfo</span><span style=\"color: #A5D6FF\">)</span><span style=\"color: #A5D6FF\">}`</span><span style=\"color: #C9D1D9\">);</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// >> {"code":0,"msg":{"validate":{"id":["id must be of type number."],"name":["name is required."],"age":["age must be greater than 0."]},"parms":{"id":"1","age":-10}}}</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br><span>24</span><br><span>25</span><br><span>26</span><br><span>27</span><br><span>28</span><br></div></div><h3 id=\"自定义校验提示内容\" tabindex=\"-1\"> 自定义校验提示内容</h3>\n<p>框架默认修饰器提示信息可以通过配置文件<code>src/config/argDecorator.config.ts</code>进行覆盖。通过<code>Result</code>模块用户可以自定义校验失败时返回的数据格式或者方式,比如json,或者状态码。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Result } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">Require: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">err</span><span style=\"color: #C9D1D9\">({</span><span style=\"color: #FFA657\">key</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">tip</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">val</span><span style=\"color: #C9D1D9\">}) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(tip </span><span style=\"color: #FF7B72\">||</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">`请求${</span><span style=\"color: #C9D1D9\">key</span><span style=\"color: #A5D6FF\">} 参数不能为空。入参值为${</span><span style=\"color: #C9D1D9\">val</span><span style=\"color: #A5D6FF\">}`</span><span style=\"color: #C9D1D9\">,</span><span style=\"color: #79C0FF\">403</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">ToNumber: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">err</span><span style=\"color: #C9D1D9\">({</span><span style=\"color: #FFA657\">key</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">tip</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">val</span><span style=\"color: #C9D1D9\">}) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">json</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> code: </span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> msg: tip </span><span style=\"color: #FF7B72\">||</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">`请求${</span><span style=\"color: #C9D1D9\">key</span><span style=\"color: #A5D6FF\">} 参数必须为数字类型。入参值为${</span><span style=\"color: #C9D1D9\">val</span><span style=\"color: #A5D6FF\">}`</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> });</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.165Z",
"authors": [],
"tags": []
},
{
"title": "断点调试(Debugger)",
"url": "https://umajs.github.io/other/debug.html",
"id": "https://umajs.github.io/other/debug.html",
"content_html": "<h1 id=\"断点调试-debugger\" tabindex=\"-1\"> 断点调试(Debugger)</h1>\n<p>为了方便用户的调试,通过 cli 工具生成的项目中,为大家预置了调试配置。</p>\n<h2 id=\"开启调试\" tabindex=\"-1\"> 开启调试</h2>\n<h3 id=\"vscode\" tabindex=\"-1\"> vscode</h3>\n<p>开启断点调试要求开发者使用<code>VSCode</code>作为开发工具,在 VSCode 中按<code>F5</code>快捷键即可 debug 断点调试模式,此时在代码中设置断点,即可拦截客户端发来的请求。</p>\n<h3 id=\"chrome\" tabindex=\"-1\"> chrome</h3>\n<p>1、打开两个命令窗口,分别顺序执行下面两行命令(如果想要热调试,可以把 node 替换成 supervisor 等热部署的命令)</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">$ tsc -w --inlineSourceMap</span></span>\n<span><span style=\"color: #C9D1D9\">$ node --inspect lib/app.js</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br></div></div><p>然后就会得到下面的输出</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #c9d1d9\">Debugger listening on ws://127.0.0.1:9229/4dc825ec-a204-46f8-8edc-4afadc8da61a\nFor help see https://nodejs.org/en/docs/inspector\n</span></span></code></pre><div><span>1</span><br><span>2</span><br></div></div><p>2、在 Chrome 中打开 chrome://inspect/#devices,可以看到页面右边的 Remote Target,在 Target 中选中启动文件下方的 inspect 就可以进入调试。</p>\n",
"date_modified": "2023-03-17T10:20:25.165Z",
"authors": [],
"tags": []
},
{
"title": "错误处理(ErrorHandler)",
"url": "https://umajs.github.io/other/errorHandling.html",
"id": "https://umajs.github.io/other/errorHandling.html",
"content_html": "<h1 id=\"错误处理-errorhandler\" tabindex=\"-1\"> 错误处理(ErrorHandler)</h1>\n<p>程序在执行过程中总会遇到一些可预测或者不可预测的异常,如果对这些异常不做处理,可能会导致程序的崩溃,所以我们需要对程序的异常进行捕获并做相应的处理。下面介绍下在使用 Uma 进行开发时有哪些方法可以捕获程序的异常。</p>\n<h2 id=\"在方法中-try-catch\" tabindex=\"-1\"> 在方法中 try-catch</h2>\n<p>在需要的地方进行<code>try-catch</code>是开发语言为我们提供的捕获错误方法,我们将可能出错的代码通过<code>try-catch</code>进行包裹,在<code>catch</code>中对异常进行处理。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">try</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// ......</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">json</span><span style=\"color: #C9D1D9\">({ code: </span><span style=\"color: #79C0FF\">100</span><span style=\"color: #C9D1D9\">, msg: </span><span style=\"color: #A5D6FF\">'success'</span><span style=\"color: #C9D1D9\"> })</span></span>\n<span><span style=\"color: #C9D1D9\"> } </span><span style=\"color: #FF7B72\">catch</span><span style=\"color: #C9D1D9\"> (err) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 出现错误时处理</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">json</span><span style=\"color: #C9D1D9\">({ code: </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #79C0FF\">100</span><span style=\"color: #C9D1D9\">, msg: </span><span style=\"color: #A5D6FF\">'error'</span><span style=\"color: #C9D1D9\"> })</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br></div></div><h2 id=\"使用around\" tabindex=\"-1\"> 使用Around</h2>\n<p>Uma 提供的 Aspect 中,我们可以通过<code>Around</code>来处理异常。</p>\n<p>在<a href=\"/other/AOP.html#%E9%80%9A%E7%9F%A5\">AOP</a>一节中我们介绍了,当方法执行过程中,Around装饰器传入的函数可以拦截目标函数的执行,我们可以在函数执行过程中通过try,catch捕获异常并且进行统一返回处理。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// ${URSA_ROOT}/aspect/err.aspect.ts</span></span>\n<span><span style=\"color: #8B949E\">// /aspect/method.aspect.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { IProceedJoinPoint } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">function</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">throwErr</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">proceedPoint</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IProceedJoinPoint</span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">>) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">let</span><span style=\"color: #C9D1D9\"> result;</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">try</span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 执行被修饰的方法</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">result</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> proceedPoint.</span><span style=\"color: #D2A8FF\">proceed</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FF7B72\">catch</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">e</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\">Error</span><span style=\"color: #C9D1D9\">){</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">json</span><span style=\"color: #C9D1D9\">({code:</span><span style=\"color: #79C0FF\">1</span><span style=\"color: #C9D1D9\">,message:</span><span style=\"color: #A5D6FF\">'执行方法异常!'</span><span style=\"color: #C9D1D9\">,stack:e.stack})</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> </span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> result;</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// ${URSA_ROOT}/controller/index.controller.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">// 添加异常处理切面方法,当index执行出错时会执行afterThrowing</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Around</span><span style=\"color: #FFA657\">(</span><span style=\"color: #C9D1D9\">throwErr</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">throw</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">Error</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'error'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br><span>24</span><br></div></div><h2 id=\"中间件方式\" tabindex=\"-1\"> 中间件方式</h2>\n<p>在<a href=\"/development/Plugin.html#%E6%8F%92%E4%BB%B6%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B\">plugin</a>中,我们可以通过插件加载全局中间件,而在中间件中我们可以对next中间件进行捕获,因为插件中引入的中间件执行顺序总是在controller函数被调用之前。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin/error-handler/index.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> (uma</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Uma, options</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> TView </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #FFA657\"> {})</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Koa.Middleware </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// uma 实例化对象;options 插件配置的 options,等同于 uma.plugin['error-handler'].options</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #C9D1D9\">,</span><span style=\"color: #FFA657\">next</span><span style=\"color: #C9D1D9\">)</span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">try</span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FF7B72\">catch</span><span style=\"color: #C9D1D9\">(e){</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">error</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'error-handler插件捕获异常'</span><span style=\"color: #C9D1D9\">,e);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\">};</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><h2 id=\"使用-plugin-status\" tabindex=\"-1\"> 使用 plugin-status</h2>\n<p><a href=\"/plugin/Status.html\">plugin-status</a>是 Uma 为了方便用户对 response<code>不同状态码</code>情况和<code>错误</code>进行处理提供的插件。</p>\n<p>具体使用方法可以参考<a href=\"/plugin/Status.html\">插件/Status</a>一章</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// status.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">// 针对状态码进行处理</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">_404</span><span style=\"color: #FFA657\">(ctx) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> ctx.</span><span style=\"color: #D2A8FF\">render</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'404.html'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">// 针对未被捕获错误进行处理</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">_error</span><span style=\"color: #FFA657\">(e</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Error, ctx) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// ...</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><h2 id=\"三种错误处理方式的使用场景\" tabindex=\"-1\"> 三种错误处理方式的使用场景</h2>\n<ul>\n<li>try-catch: 适合对方法<code>单独</code>进行错误处理</li>\n<li>Around: 更具<code>可复用性</code>,可以对多个方法进行错误处理</li>\n<li>中间件方式: 属于全局异常兜底策略,适用于全局范围内未知异常捕获处理</li>\n<li>plugin-status: 对整个系统在运行中未被捕获的错误的<code>兜底操作</code>,让系统更健壮,同时除了错误处理外,更多的是<code>对不同状态码的统一处理</code></li>\n</ul>\n",
"date_modified": "2023-03-17T10:20:25.165Z",
"authors": [],
"tags": []
},
{
"title": "express迁移",
"url": "https://umajs.github.io/other/expressUpdate.html",
"id": "https://umajs.github.io/other/expressUpdate.html",
"content_html": "<h1 id=\"express迁移\" tabindex=\"-1\"> express迁移</h1>\n<blockquote>\n<p>对于一些历史项目,我们可以采取逐步升级,将 umajs 集成到 express 项目中。新的接口和逻辑通过 Umajs 来写,然后再慢慢将老的逻辑迁移到 Umajs 中。</p>\n</blockquote>\n<h2 id=\"uma-callback\" tabindex=\"-1\"> Uma.callback</h2>\n<blockquote>\n<p>通过 uma.callback 函数可以获取到框架实例化后的 koa.callback.然后采用中间件形式集成到 express,connect 框架中。</p>\n</blockquote>\n<h2 id=\"接入方式步骤\" tabindex=\"-1\"> 接入方式步骤</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">//app.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Uma } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> express </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'express'</span></span>\n<span><span style=\"color: #C9D1D9\">;(</span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> () </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">callback</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">></span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> Uma.</span><span style=\"color: #D2A8FF\">callback</span><span style=\"color: #C9D1D9\">(options)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">app</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">express</span><span style=\"color: #C9D1D9\">()</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** 老项目中间件加载 **/</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// callback在express放到最后一个中间件中</span></span>\n<span><span style=\"color: #C9D1D9\"> app.</span><span style=\"color: #D2A8FF\">use</span><span style=\"color: #C9D1D9\">((</span><span style=\"color: #FFA657\">req</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">res</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">next</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">callback</span><span style=\"color: #C9D1D9\">(req, res).</span><span style=\"color: #D2A8FF\">then</span><span style=\"color: #C9D1D9\">(() </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">if</span><span style=\"color: #C9D1D9\"> (res.headersSent) </span><span style=\"color: #FF7B72\">return</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">()</span></span>\n<span><span style=\"color: #C9D1D9\"> })</span></span>\n<span><span style=\"color: #C9D1D9\"> )</span></span>\n<span><span style=\"color: #C9D1D9\">})()</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br></div></div><h2 id=\"注意事项\" tabindex=\"-1\"> 注意事项</h2>\n<p>1、建议在 umajs 中间件中重置 ctx.status=200 状态码。</p>\n<p>2、umajs 中配置的 view 插件和 express 中使用的模板引擎保持一致.或者直接通过插件挂载到 context 和 Result 对象</p>\n<p>3、express 老项目中如果有存储的 token 和 session 建议通过 umajs 自定义插件转移到 ctx 后再 uma 逻辑中进行复用</p>\n<p>4、在 express 中使用 Umajs 时,Umajs 中间件的执行顺序需要在 express 所有中间件之后,如果之前项目有设置 404 路由需要删掉 404 中间件。</p>\n<h2 id=\"其他方案\" tabindex=\"-1\"> 其他方案</h2>\n<blockquote>\n<p>对于只想使用 express 框架路线的项目,框架也提供了 express 版本的 Umajs.API 几乎与 Umajs 保持一致,详情查看<a href=\"https://github.com/Umajs/umajs-express\" target=\"_blank\" rel=\"noopener noreferrer\">umajs-express</a></p>\n</blockquote>\n",
"date_modified": "2023-03-17T10:20:25.165Z",
"authors": [],
"tags": []
},
{
"title": "koa渐进迁移",
"url": "https://umajs.github.io/other/preMigration.html",
"id": "https://umajs.github.io/other/preMigration.html",
"content_html": "<h1 id=\"koa渐进迁移\" tabindex=\"-1\"> koa渐进迁移</h1>\n<p>Uma 提供了中间件,方便 Koa 或者 Koa 衍生框架采用渐进迁移的方式迁移至 Umajs 框架。</p>\n<h2 id=\"中间件\" tabindex=\"-1\"> 中间件</h2>\n<h3 id=\"使用\" tabindex=\"-1\"> 使用</h3>\n<p><code>Uma</code> 提供了 <code>middleware(options: TUmaOption, app: Koa)</code> 静态方法返回中间件供使用,示例如下:</p>\n<h3 id=\"方式-1\" tabindex=\"-1\"> 方式 1</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">app</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">Koa</span><span style=\"color: #C9D1D9\">()</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">Uma.</span><span style=\"color: #D2A8FF\">middleware</span><span style=\"color: #C9D1D9\">(options, app).</span><span style=\"color: #D2A8FF\">then</span><span style=\"color: #C9D1D9\">((</span><span style=\"color: #FFA657\">mw</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> app.</span><span style=\"color: #D2A8FF\">use</span><span style=\"color: #C9D1D9\">(mw)</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> app.</span><span style=\"color: #D2A8FF\">listen</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">8058</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><h3 id=\"方式-2\" tabindex=\"-1\"> 方式 2</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">;(</span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> () </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">app</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">Koa</span><span style=\"color: #C9D1D9\">()</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> app.</span><span style=\"color: #D2A8FF\">use</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> Uma.</span><span style=\"color: #D2A8FF\">middleware</span><span style=\"color: #C9D1D9\">(options, app))</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> app.</span><span style=\"color: #D2A8FF\">listen</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">8058</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">})()</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><h2 id=\"迁移\" tabindex=\"-1\"> 迁移</h2>\n<p>配置完 <code>Umajs</code> 中间件后,<code>Umajs</code> 就可以在框架中完整运行,这时就可以将代码按照 <code>Umajs</code> 的规则逐步迁移。例如先迁移 <code>Controller</code>……</p>\n",
"date_modified": "2023-03-17T10:20:25.165Z",
"authors": [],
"tags": []
},
{
"title": "v1迁移指南",
"url": "https://umajs.github.io/other/v1Update.html",
"id": "https://umajs.github.io/other/v1Update.html",
"content_html": "<h1 id=\"v1迁移指南\" tabindex=\"-1\"> v1迁移指南</h1>\n<blockquote>\n<p>本文档介绍从V1版本升级到V2.0的迁移指南,想要了解V2中的变化,请查看<a href=\"https://github.com/Umajs/Umajs/pull/74\" target=\"_blank\" rel=\"noopener noreferrer\">PR</a>。</p>\n</blockquote>\n<p>V2版本和V1的最大改动是对目录文件夹的文件的默认约束,在V1时,框架对<code>controller,service,aspect,plugin,config</code>目录都进行了强制命名约束。这导致UMajs在启动时将不得不分配额外的时间去提前扫描加载文件;在V2中我们只保留了<code>controller</code>,<code>plugin</code>,<code>config</code>三个文件目录的约束不变。这导致我们在升级V2时,注意以下功能需要修改成V2最新的使用方法。</p>\n<ul>\n<li>取消默认文件路由,所有路由必须被@Path修饰使用</li>\n<li>Aspect装饰器替换为Around</li>\n<li>Service,Inject装饰器只能接受函数引用</li>\n<li>删除@umajs/path包</li>\n<li>Private装饰器已从@umajs/core中移除</li>\n</ul>\n<h2 id=\"取消默认文件路由-所有路由必须被-path修饰使用\" tabindex=\"-1\"> 取消默认文件路由,所有路由必须被@Path修饰使用</h2>\n<blockquote>\n<p>在V2版本中,为了降低开发者对路由的了解;默认取消了基于文件的路由。</p>\n</blockquote>\n<p>以下路由匹配规则在V2版本中将无法匹配访问到资源。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">class</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">User</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// url: /user</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #C9D1D9\">() {}</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// url: /user/list</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">list</span><span style=\"color: #C9D1D9\">() {}</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><p>修改成:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/user'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #FF7B72\">class</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">User</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">() </span><span style=\"color: #8B949E\">// url: /user</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #C9D1D9\">() {}</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'/list'</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #8B949E\">// url: /user/list</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">list</span><span style=\"color: #C9D1D9\">() {}</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br></div></div><p>所有被映射成路由的函数,都需要通过<code>@Path</code>装饰器进行修饰;这样的目的也是为了规范和对项目路由的管理,减少由于缺乏管理导致函数暴露的情况发生。</p>\n<h2 id=\"aspect装饰器替换为around\" tabindex=\"-1\"> Aspect装饰器替换为Around</h2>\n<blockquote>\n<p>@umajs/core v2.0移除 before,after,afterReturing, afterThrowing钩子函数。对于之前使用Aspect装饰器的代码,升级使用Around进行装饰;这意味着你不能继续使用Aspect装饰器。</p>\n</blockquote>\n<p>之前:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// src/aspect/method.aspect.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { IAspect, IJoinPoint, IProceedJoinPoint } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Method </span><span style=\"color: #FF7B72\">implements</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">IAspect</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">before</span><span style=\"color: #FFA657\">(point</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> IJoinPoint) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 前置通知</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">after</span><span style=\"color: #FFA657\">(point</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> IJoinPoint) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 后置通知</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">around</span><span style=\"color: #FFA657\">(proceedPoint</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> IProceedJoinPoint) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> { </span><span style=\"color: #79C0FF\">proceed</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #79C0FF\">args</span><span style=\"color: #C9D1D9\"> ,} </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> proceedPoint</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 环绕通知before</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">proceed</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FF7B72\">...</span><span style=\"color: #C9D1D9\">args)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 环绕通知after</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">afterThrowing</span><span style=\"color: #FFA657\">(e</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Error) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 异常通知</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">afterReturning</span><span style=\"color: #FFA657\">(point</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> IJoinPoint, result</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #FFA657\">) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 返回通知</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br></div></div><p>现在:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// src/aspect/method.aspect.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { IProceedJoinPoint } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">function</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">method</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">proceedPoint</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IProceedJoinPoint</span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">>) {</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'method: this is around'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> { </span><span style=\"color: #79C0FF\">proceed</span><span style=\"color: #C9D1D9\"> , </span><span style=\"color: #79C0FF\">target</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #79C0FF\">arg</span><span style=\"color: #C9D1D9\"> } </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> proceedPoint;</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// proceed 路由函数</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// target 等同于controller实例 this</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// arg 路由函数参数 数组类型</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">result</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">proceed</span><span style=\"color: #C9D1D9\">(); </span><span style=\"color: #8B949E\">// 继续执行method函数</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'method: this is around after'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> result;</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br></div></div><p>也可通过middlewareToAround转换成中间件的形式</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { middlewareToAround } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">mw</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">middlewareToAround</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">next</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">"****** mw before ******"</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">"****** mw after *******"</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\">});</span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br></div></div><p>同时,v2版本中提供了Middleware装饰器,可为路由函数在执行之前调用指定koa中间件,具体使用请查看文档。</p>\n<p>现在,你在controller中需要将Aspect用法修改使用为Around装饰器方式。注:Aspect在V2中彻底被删除。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path, Around, Result } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { method } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../aspect/method.aspect'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> \t</span><span style=\"color: #8B949E\">// before</span></span>\n<span><span style=\"color: #FFA657\"> \t@</span><span style=\"color: #D2A8FF\">Get</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/reg/:name*'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Aspect</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'method'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">methodOld</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">`this is reg router`</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\"> </span></span>\n<span><span style=\"color: #FFA657\"> \t</span><span style=\"color: #8B949E\">// after</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Get</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/reg/:name*'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Around</span><span style=\"color: #FFA657\">(</span><span style=\"color: #C9D1D9\">method</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">method</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">`this is reg router`</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\"> }</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br></div></div><h2 id=\"service-inject装饰器只能接受函数引用\" tabindex=\"-1\"> Service,Inject装饰器只能接受函数引用</h2>\n<blockquote>\n<p>当使用IOC时,在V1版本中,我们可以通过<code>xxx.service.ts</code>文件命名约束,在<code>controller</code>中,我们在使用时可通过<code>@Service('xxx')</code>实现Service实例的注入。这很方便;但对于TS环境,我们不得不需要手动<code>import</code>对<code>Service</code>文件的类型声明。而在文件类型声明时我们将再次导入该文件的引用。所以在V2中我们直接取消了对<code>Service</code>的文件命名的<code>强制约束</code>,启动时也不再提前预加载扫描该目录。这带来的改变就是,<strong><code>Service,Inject</code>装饰器不在支持字符串方式实现class注入。</strong></p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// before </span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path, Around, Result } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> UserService </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../service/user.service'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">// before</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Service</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'user'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> userService</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> UserService;</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">indexOld</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.userService.</span><span style=\"color: #D2A8FF\">getDefaultUserAge</span><span style=\"color: #C9D1D9\">());</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\"> </span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">// after</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Service</span><span style=\"color: #FFA657\">(</span><span style=\"color: #C9D1D9\">UserService</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> userService</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> UserService;</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.userService.</span><span style=\"color: #D2A8FF\">getDefaultUserAge</span><span style=\"color: #C9D1D9\">());</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br></div></div><p>虽然框架默认取消了对文件命名的强制约束,但为了更好的阅读体验和一致的风格。我们依然建议的Service进行统一风格的命名和定义。</p>\n",
"date_modified": "2023-03-17T10:20:25.166Z",
"authors": [],
"tags": []
},
{
"title": "跨域处理(Cors)",
"url": "https://umajs.github.io/plugin/Cors.html",
"id": "https://umajs.github.io/plugin/Cors.html",
"content_html": "<h1 id=\"跨域处理-cors\" tabindex=\"-1\"> 跨域处理(Cors)</h1>\n<p>跨域处理插件</p>\n<h2 id=\"安装\" tabindex=\"-1\"> 安装</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">$ npm install -S @umajs/plugin-cors</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h2 id=\"开启\" tabindex=\"-1\"> 开启</h2>\n<p>在 plugin.config.ts 中开启 plugin-cors 插件</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">cors: </span><span style=\"color: #79C0FF\">true</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><blockquote>\n<p>具体开启方式请参考<a href=\"/development/Plugin.html\">plugin</a>一节中的配置方式</p>\n</blockquote>\n",
"date_modified": "2023-03-17T10:20:25.166Z",
"authors": [],
"tags": []
},
{
"title": "日志(Logger)",
"url": "https://umajs.github.io/plugin/Logger.html",
"id": "https://umajs.github.io/plugin/Logger.html",
"content_html": "<h1 id=\"日志-logger\" tabindex=\"-1\"> 日志(Logger)</h1>\n<h2 id=\"日志\" tabindex=\"-1\"> 日志</h2>\n<p>日志对于 Web 项目的运行状态、问题排查等都非常重要。框架的<code>@umajs/logger</code>模块提供日志支持。并且提供<code>@umajs/plugin-logger</code>模块,以插件的机制将 logger 实例绑定在 ctx 上,方便用户使用。</p>\n<p>主要特性:</p>\n<ul>\n<li>日志分级</li>\n<li>统一错误日志,所有 logger 中使用 .error() 打印的 ERROR 级别日志都会打印到统一的错误日志文件中,便于追踪</li>\n<li>自定义日志</li>\n<li>自动切割日志</li>\n</ul>\n<h2 id=\"使用plugin-logger\" tabindex=\"-1\"> 使用<code>plugin-logger</code></h2>\n<ul>\n<li>安装插件 <code>npm install -S @umajs/plugin-logger</code></li>\n<li>插件配置:</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">//app/src/config/default/plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">as</span><span style=\"color: #C9D1D9\"> path </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'path'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> { </span><span style=\"color: #79C0FF\">ROOT</span><span style=\"color: #C9D1D9\"> } </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> Uma.options</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">logger: {</span></span>\n<span><span style=\"color: #C9D1D9\"> enable: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> options: {</span></span>\n<span><span style=\"color: #C9D1D9\"> level: </span><span style=\"color: #A5D6FF\">'DEBUG'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//日志输出级别</span></span>\n<span><span style=\"color: #C9D1D9\"> file: path.</span><span style=\"color: #D2A8FF\">resolve</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">ROOT</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #A5D6FF\">'../log/logger.log'</span><span style=\"color: #C9D1D9\">),</span></span>\n<span><span style=\"color: #C9D1D9\"> allowDebugAtProd: </span><span style=\"color: #79C0FF\">false</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 是否允许打印debug日志</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br></div></div><ul>\n<li>在 Controller 中使用 logger</li>\n</ul>\n<p><code>plugin-logger</code>插件将 logger 实例绑定在 ctx 上,因此可在项目中使用<code>this.ctx.logger</code>使用;</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// app/src/controller/index.controller.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/index'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">RequestMethod</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'GET'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">info</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.testService.</span><span style=\"color: #D2A8FF\">return1</span><span style=\"color: #C9D1D9\">())</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">debug</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'debug'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">warn</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'warn'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">error</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'error'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'这里是首页'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br></div></div><ul>\n<li>在 Service 中使用 logger 【 v0.0.5 版本后支持】</li>\n</ul>\n<p><code>plugin-logger</code>绑定到 ctx 上的 logger 实例可通过<code>UmaLogger.instance()</code>获取</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// app/src/service/test.service.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseService } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { UmaLogger } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/logger'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> test </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseService</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">return1</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> UmaLogger.</span><span style=\"color: #D2A8FF\">instance</span><span style=\"color: #C9D1D9\">().</span><span style=\"color: #D2A8FF\">info</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'service test'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">1</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span><span style=\"color: #8B949E\">// [INFO 51449] 2020-04-10 18:42:21,179 bogon [::1/GET /]: service test</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><h2 id=\"使用-umalogger\" tabindex=\"-1\"> 使用 UmaLogger</h2>\n<p><code>UmaLogger</code>可单独使用,具体提供如下几种使用方式:</p>\n<ol>\n<li>通过 <code>new UmaLogger()</code> 独立创建日志实例</li>\n</ol>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// app/src/controller/index.controller.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { UmaLogger } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/logger'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">as</span><span style=\"color: #C9D1D9\"> path </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'path'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">logger</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">UmaLogger</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> level: </span><span style=\"color: #A5D6FF\">'ALL'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> consoleLevel: </span><span style=\"color: #A5D6FF\">'ALL'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> encoding: </span><span style=\"color: #A5D6FF\">'utf-8'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> file: path.</span><span style=\"color: #D2A8FF\">resolve</span><span style=\"color: #C9D1D9\">(__dirname, </span><span style=\"color: #A5D6FF\">'../log/logger.log'</span><span style=\"color: #C9D1D9\">),</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">debug</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'debug'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">info</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'info GET'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">warn</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'warn'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">error</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'error'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br></div></div><ol start=\"2\">\n<li>直接使用 <code>@umajs/logger</code> 模块默认导出的实例 【 v0.0.5 版本后支持】</li>\n</ol>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">logger</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">require</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'@umajs/logger'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">init</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> level: </span><span style=\"color: #A5D6FF\">'ALL'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> consoleLevel: </span><span style=\"color: #A5D6FF\">'ALL'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> encoding: </span><span style=\"color: #A5D6FF\">'utf-8'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> file: path.</span><span style=\"color: #D2A8FF\">resolve</span><span style=\"color: #C9D1D9\">(__dirname, </span><span style=\"color: #A5D6FF\">'../log/logger.log'</span><span style=\"color: #C9D1D9\">),</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">debug</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'debug'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">info</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'info GET'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">warn</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'warn'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">error</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'error'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><ol start=\"3\">\n<li>通过单例模式使用 logger 【 v0.0.5 版本后支持】</li>\n</ol>\n<p>只需传入一次参数,其他地方可直接使用 <code>UmaLogger.instance()</code> 获取实例化后日志对象</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// app/src/controller/index.controller.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { UmaLogger } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/logger'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">as</span><span style=\"color: #C9D1D9\"> path </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'path'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">logger</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> UmaLogger.</span><span style=\"color: #D2A8FF\">instance</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> level: </span><span style=\"color: #A5D6FF\">'ALL'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> consoleLevel: </span><span style=\"color: #A5D6FF\">'ALL'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> encoding: </span><span style=\"color: #A5D6FF\">'utf-8'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> file: path.</span><span style=\"color: #D2A8FF\">resolve</span><span style=\"color: #C9D1D9\">(__dirname, </span><span style=\"color: #A5D6FF\">'../log/logger.log'</span><span style=\"color: #C9D1D9\">),</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">debug</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'debug'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">info</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'info GET'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">warn</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'warn'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">logger.</span><span style=\"color: #D2A8FF\">error</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'error'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br></div></div><h2 id=\"日志配置\" tabindex=\"-1\"> 日志配置</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #79C0FF\">exports</span><span style=\"color: #C9D1D9\">.logger </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> level: </span><span style=\"color: #A5D6FF\">'DEBUG'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//日志输出级别</span></span>\n<span><span style=\"color: #C9D1D9\"> dir: </span><span style=\"color: #A5D6FF\">'/path/to/your/custom/log'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//日志输出目录</span></span>\n<span><span style=\"color: #C9D1D9\"> errorLogName: </span><span style=\"color: #A5D6FF\">'errorlogger.log'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//error级别日志文件名</span></span>\n<span><span style=\"color: #C9D1D9\"> infoLogName: </span><span style=\"color: #A5D6FF\">'infologger.log'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//info级别日志文件名</span></span>\n<span><span style=\"color: #C9D1D9\"> warnLogName: </span><span style=\"color: #A5D6FF\">'warnlogger.log'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//warn级别日志文件名</span></span>\n<span><span style=\"color: #C9D1D9\"> file: </span><span style=\"color: #A5D6FF\">'/path/to/your/custom/log/logger.log'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//日志文件写入路径(所有级别日志)</span></span>\n<span><span style=\"color: #C9D1D9\"> encoding: </span><span style=\"color: #A5D6FF\">'utf-8'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//日志编码格式</span></span>\n<span><span style=\"color: #C9D1D9\"> outputJSON: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//是否格式化输出携带pid等信息 false仅输出msg</span></span>\n<span><span style=\"color: #C9D1D9\"> consoleLevel: </span><span style=\"color: #A5D6FF\">'debug'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//终端日志输出级别</span></span>\n<span><span style=\"color: #C9D1D9\"> allowDebugAtProd: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//是否允许打印debug日志</span></span>\n<span><span style=\"color: #C9D1D9\"> flushInterval: </span><span style=\"color: #79C0FF\">1000</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//文件流定时写入</span></span>\n<span><span style=\"color: #C9D1D9\"> maxBufferLength: </span><span style=\"color: #79C0FF\">1000</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//最大buffer 超出限制执行写入</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">formatter</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #FF7B72\">function</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">meta</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TConsoleMeta</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">`[${</span><span style=\"color: #C9D1D9\">meta</span><span style=\"color: #A5D6FF\">.</span><span style=\"color: #C9D1D9\">level</span><span style=\"color: #A5D6FF\">} ${</span><span style=\"color: #C9D1D9\">meta</span><span style=\"color: #A5D6FF\">.</span><span style=\"color: #C9D1D9\">pid</span><span style=\"color: #A5D6FF\">}] ${</span><span style=\"color: #C9D1D9\">meta</span><span style=\"color: #A5D6FF\">.</span><span style=\"color: #C9D1D9\">date</span><span style=\"color: #A5D6FF\">} ${</span><span style=\"color: #C9D1D9\">meta</span><span style=\"color: #A5D6FF\">.</span><span style=\"color: #C9D1D9\">hostname</span><span style=\"color: #A5D6FF\">} ${</span><span style=\"color: #C9D1D9\">meta</span><span style=\"color: #A5D6FF\">.</span><span style=\"color: #C9D1D9\">paddingMessage</span><span style=\"color: #A5D6FF\">}: ${</span><span style=\"color: #C9D1D9\">meta</span><span style=\"color: #A5D6FF\">.</span><span style=\"color: #C9D1D9\">message</span><span style=\"color: #A5D6FF\">}`</span></span>\n<span><span style=\"color: #C9D1D9\"> }, </span><span style=\"color: #8B949E\">//日志格式化输出</span></span>\n<span><span style=\"color: #C9D1D9\"> splitTime: </span><span style=\"color: #A5D6FF\">'00 00 * * * *'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//日志文件切割时间</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br></div></div><h2 id=\"日志路径\" tabindex=\"-1\"> 日志路径</h2>\n<ol>\n<li>默认日志文件路径:默认都放在<code>${APP_ROOT}/log/logger.log</code>路径下;</li>\n<li>自定义日志文件路径:\n<code>config.file</code>会把所有日志统一写入<code>file</code>所指定的文件中;</li>\n</ol>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// config/logger.config.ts</span></span>\n<span><span style=\"color: #79C0FF\">exports</span><span style=\"color: #C9D1D9\">.logger </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> file: </span><span style=\"color: #A5D6FF\">'/path/to/your/custom/log/logger.log'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//日志文件路径(所有级别日志统一写入)</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><ol start=\"3\">\n<li>不同级别日志分开打印</li>\n</ol>\n<p>日志按级别分开打印,需配置<code>config.dir config.errorLogName ...</code></p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// config/logger.config.ts</span></span>\n<span><span style=\"color: #79C0FF\">exports</span><span style=\"color: #C9D1D9\">.logger </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> dir: </span><span style=\"color: #A5D6FF\">'/path/to/your/custom/log'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//日志目录</span></span>\n<span><span style=\"color: #C9D1D9\"> errorLogName: </span><span style=\"color: #A5D6FF\">'errorlogger.log'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//error级别日志文件名</span></span>\n<span><span style=\"color: #C9D1D9\"> infoLogName: </span><span style=\"color: #A5D6FF\">'infologger.log'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//info级别日志文件名</span></span>\n<span><span style=\"color: #C9D1D9\"> warnLogName: </span><span style=\"color: #A5D6FF\">'warnlogger.log'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//warn级别日志文件名</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><p>所有级别的日志会写入<code>/path/to/your/custom/log/logger.log</code>文件</p>\n<p><code>Info</code>级别的日志会写入<code>/path/to/your/custom/log/infoLogName.log</code>文件</p>\n<p><code>Warn</code>级别的日志会写入<code>/path/to/your/custom/log/warnLogName.log</code>文件</p>\n<p><code>Error</code>级别的日志会写入<code>/path/to/your/custom/log/errorLogName.log</code>文件</p>\n<h2 id=\"日志分类\" tabindex=\"-1\"> 日志分类</h2>\n<p>框架内置了几种日志,分别在不同的场景下使用:</p>\n<ul>\n<li><code>ContextLogger</code>:默认开启,使用<code>this.ctx.logger.info()</code>可使用,可获取上下文</li>\n<li><code>errorLogger</code>:任何 logger 的<code>.error()</code>调用输出的日志都会走此逻辑,默认关闭不使用,开启需要配置<code>dir errorLogName</code></li>\n<li><code>infoLogger</code>:任何 logger 的<code>.info()</code>调用输出的日志都会走此逻辑,默认关闭不使用,开启需要配置<code>dir infoLogName</code></li>\n<li><code>warnLogger</code>:任何 logger 的<code>.warn()</code>调用输出的日志都会走此逻辑,默认关闭不使用,开启需要配置<code>dir warnLogName</code></li>\n</ul>\n<h2 id=\"如何打印日志\" tabindex=\"-1\"> 如何打印日志</h2>\n<h3 id=\"contextlogger\" tabindex=\"-1\"> <code>ContextLogger</code></h3>\n<p>如果我们在处理请求时需要打印日志,这是需要使用<code>ContextLogger</code>,用于记录 Web 行为相关的日志,日志内容会携带当前请求的一些基本信息。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">try</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">info1</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">12312323</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">} </span><span style=\"color: #FF7B72\">catch</span><span style=\"color: #C9D1D9\"> (error) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">error</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'错误:'</span><span style=\"color: #C9D1D9\">, error)</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">info</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.testService.</span><span style=\"color: #D2A8FF\">return1</span><span style=\"color: #C9D1D9\">())</span></span>\n<span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">debug</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'debug'</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #8B949E\">// only output to stdout</span></span>\n<span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">info</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'info'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">warn</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'warn'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.logger.</span><span style=\"color: #D2A8FF\">error</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'error'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><h2 id=\"日志级别\" tabindex=\"-1\"> 日志级别</h2>\n<p>日志分为<code>ALL DEBUG INFO WARN ERROR NONE</code>6 个级别。默认会同时打印<code>INFO</code>及以上级别的日志到文件和终端,可自定义日志输出级别:</p>\n<h3 id=\"_1-文件日志级别-默认info\" tabindex=\"-1\"> 1.文件日志级别(默认<code>INFO</code>)</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// config/logger.config.ts</span></span>\n<span><span style=\"color: #79C0FF\">exports</span><span style=\"color: #C9D1D9\">.logger </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> level: </span><span style=\"color: #A5D6FF\">'ALL'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 打印所有级别日志到文件中</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><h3 id=\"_2-终端日志级别-默认info\" tabindex=\"-1\"> 2.终端日志级别(默认<code>INFO</code>)</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// config/logger.config.ts</span></span>\n<span><span style=\"color: #79C0FF\">exports</span><span style=\"color: #C9D1D9\">.logger </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> consoleLevel: </span><span style=\"color: #A5D6FF\">'NONE'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//关闭日志终端输出</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><p><code>consoleLevel</code>优先级高于<code>level</code>,<code>consoleLevel</code>仅对终端输出生效。</p>\n<p><img src=\"@source/../public/images/logger/consoleprint.png\" alt=\"images\"></p>\n<h3 id=\"_3-生产环境关闭打印-debug-日志-默认关闭\" tabindex=\"-1\"> 3.生产环境关闭打印 debug 日志,默认关闭</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// config/logger.config.ts</span></span>\n<span><span style=\"color: #79C0FF\">exports</span><span style=\"color: #C9D1D9\">.logger </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> allowDebugAtProd: </span><span style=\"color: #79C0FF\">false</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 是否打印debug日志</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><h2 id=\"日志文件输出\" tabindex=\"-1\"> 日志文件输出</h2>\n<ol>\n<li>文件编码,默认编码为<code>utf-8</code>,可自定义</li>\n<li>日志文件输出格式默认为<code>[${meta.level} ${meta.pid}] ${meta.date} ${meta.hostname}: ${meta.message}</code></li>\n</ol>\n<p><img src=\"@source/../public/images/logger/fileprint.png\" alt=\"images\"></p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// config/logger.config.ts</span></span>\n<span><span style=\"color: #79C0FF\">exports</span><span style=\"color: #C9D1D9\">.logger </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> encoding: </span><span style=\"color: #A5D6FF\">'gbk'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> outputJSON: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><h2 id=\"日志切割\" tabindex=\"-1\"> 日志切割</h2>\n<ol>\n<li>默认按天切割,在每日<code>00:00</code>按照.log.YYYY-MM-DD 文件名切割。</li>\n<li>切割文件时间可配置,格式按照<code>node-schedule</code></li>\n</ol>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// config/logger.config.ts</span></span>\n<span><span style=\"color: #79C0FF\">exports</span><span style=\"color: #C9D1D9\">.logger </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> splitTime: </span><span style=\"color: #A5D6FF\">'00 00 * * * *'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><p>切割后日志文件如下所示:\n<img src=\"@source/../public/images/logger/loggers.png\" alt=\"images\"></p>\n",
"date_modified": "2023-03-17T10:20:25.166Z",
"authors": [],
"tags": []
},
{
"title": "会话(Session)",
"url": "https://umajs.github.io/plugin/Session.html",
"id": "https://umajs.github.io/plugin/Session.html",
"content_html": "<h1 id=\"会话-session\" tabindex=\"-1\"> 会话(Session)</h1>\n<p>为<code>Uma</code>简化会话中间件。默认为基于 cookie 的会话</p>\n<h2 id=\"快速开始\" tabindex=\"-1\"> 快速开始</h2>\n<h3 id=\"install\" tabindex=\"-1\"> install</h3>\n<blockquote>\n<p>$ npm install -S @umajs/plugin-session</p>\n</blockquote>\n<h2 id=\"开启服务\" tabindex=\"-1\"> 开启服务</h2>\n<p>请参照插件使用说明开启国际化支持</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">session: {</span></span>\n<span><span style=\"color: #C9D1D9\"> enable: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> options: <</span><span style=\"color: #7EE787\">sessionOptions</span><span style=\"color: #C9D1D9\">>{</span></span>\n<span><span style=\"color: #C9D1D9\"> secret: </span><span style=\"color: #A5D6FF\">'secret'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br></div></div><blockquote>\n<p>具体开启方式请参考<a href=\"/development/Plugin.html\">plugin</a>一节中的配置方式</p>\n</blockquote>\n<h3 id=\"options\" tabindex=\"-1\"> options</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">sessionOptions</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">key</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 保存session的Key,默认uma:sess</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">maxAge</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">number</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 单位ms, 默认保存1天</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">secret</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 加密签名,默认umasss,注意:不要使用默认值</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">overwrite</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Boolean</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 是否重复覆盖,默认为true</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">crypto</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">ICrypto</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 加密/解密方法,需要实现 ICrypto 接口(encrypt / decrypt),实例化后传入</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><blockquote>\n<p>注意: secret 不要使用默认值</p>\n</blockquote>\n<h3 id=\"api\" tabindex=\"-1\"> API</h3>\n<ul>\n<li>\n<p>set(key, value):</p>\n</li>\n<li>\n<p>get(key):</p>\n</li>\n<li>\n<p>remove(key):</p>\n</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">ctx.session.</span><span style=\"color: #D2A8FF\">set</span><span style=\"color: #C9D1D9\">(key, val) </span><span style=\"color: #8B949E\">// 根据 key,设置 value 到 session 中</span></span>\n<span><span style=\"color: #C9D1D9\">ctx.session.</span><span style=\"color: #D2A8FF\">get</span><span style=\"color: #C9D1D9\">(key) </span><span style=\"color: #8B949E\">// 根据 key 值获取 session 的值</span></span>\n<span><span style=\"color: #C9D1D9\">ctx.session.</span><span style=\"color: #D2A8FF\">remove</span><span style=\"color: #C9D1D9\">(key) </span><span style=\"color: #8B949E\">// 删除 session 中的 key 属性</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br></div></div><h3 id=\"example\" tabindex=\"-1\"> example</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">setss</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.session.</span><span style=\"color: #D2A8FF\">set</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'haha'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #A5D6FF\">'Hello World'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'set session done.'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">getss</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.session.</span><span style=\"color: #D2A8FF\">get</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'haha'</span><span style=\"color: #C9D1D9\">))</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">rmss</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.session.</span><span style=\"color: #D2A8FF\">remove</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'haha'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'remove session done.'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.166Z",
"authors": [],
"tags": []
},
{
"title": "静态资源(Static)",
"url": "https://umajs.github.io/plugin/Static.html",
"id": "https://umajs.github.io/plugin/Static.html",
"content_html": "<h1 id=\"静态资源-static\" tabindex=\"-1\"> 静态资源(Static)</h1>\n<p>静态资源返回插件</p>\n<h2 id=\"安装\" tabindex=\"-1\"> 安装</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">$ npm install -S @umajs/plugin-static</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h2 id=\"开启\" tabindex=\"-1\"> 开启</h2>\n<p>在 plugin.config.ts 中开启 plugin-status 插件</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">static: {</span></span>\n<span><span style=\"color: #C9D1D9\"> options: <</span><span style=\"color: #7EE787\">staticOptions</span><span style=\"color: #C9D1D9\">>{</span></span>\n<span><span style=\"color: #C9D1D9\"> root: </span><span style=\"color: #A5D6FF\">'./static'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> opts: {</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><blockquote>\n<p>具体开启方式请参考<a href=\"/development/Plugin.html\">plugin</a>一节中的配置方式</p>\n</blockquote>\n<h3 id=\"options-root\" tabindex=\"-1\"> options.root</h3>\n<p>静态资源的根路径</p>\n<h3 id=\"options-opts\" tabindex=\"-1\"> options.opts</h3>\n<p>静态资源插件配置</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">staticOptions</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** If true, serves after return next(), allowing any downstream middleware to respond first. */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">defer</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** Browser cache max-age in milliseconds. (defaults to 0) */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">maxage</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">number</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">maxAge</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">SendOptions</span><span style=\"color: #C9D1D9\">[</span><span style=\"color: #A5D6FF\">'maxage'</span><span style=\"color: #C9D1D9\">],</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** Tell the browser the resource is immutable and can be cached indefinitely. (defaults to false) */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">immutable</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** Allow transfer of hidden files. (defaults to false) */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">hidden</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** Root directory to restrict file access. (defaults to '') */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">root</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** Name of the index file to serve automatically when visiting the root location. (defaults to none) */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">index</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">false</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** Try to serve the gzipped version of a file automatically when gzip is supported by a client and if the requested file with .gz extension exists. (defaults to true). */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">gzip</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** Try to serve the brotli version of a file automatically when brotli is supported by a client and if the requested file with .br extension exists. (defaults to true). */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">brotli</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** If not false (defaults to true), format the path to serve static file servers and not require a trailing slash for directories, so that you can do both /directory and /directory/. */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">format</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** Function to set custom headers on response. */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">setHeaders</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">SetHeaders</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/** Try to match extensions from passed array to search for file when no extension is sufficed in URL. First found is served. (defaults to false) */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">extensions</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">[] </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">false</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br><span>24</span><br><span>25</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.166Z",
"authors": [],
"tags": []
},
{
"title": "状态(Status)",
"url": "https://umajs.github.io/plugin/Status.html",
"id": "https://umajs.github.io/plugin/Status.html",
"content_html": "<h1 id=\"状态-status\" tabindex=\"-1\"> 状态(Status)</h1>\n<p>为了方便用户对 response<code>不同状态码</code>情况和<code>错误</code>进行处理,<code>Uma</code>提供了状态处理插件 plugin-status</p>\n<h2 id=\"安装\" tabindex=\"-1\"> 安装</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">$ npm install -S @umajs/plugin-status</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h2 id=\"开启\" tabindex=\"-1\"> 开启</h2>\n<p>在 plugin.config.ts 中开启 plugin-status 插件</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">status: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><blockquote>\n<p>具体开启方式请参考<a href=\"/development/Plugin.html\">plugin</a>一节中的配置方式</p>\n</blockquote>\n<h2 id=\"配置\" tabindex=\"-1\"> 配置</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">statusOptions</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/**</span></span>\n<span><span style=\"color: #8B949E\"> * 前缀</span></span>\n<span><span style=\"color: #8B949E\"> * 默认:_</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">prefix</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">,</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/**</span></span>\n<span><span style=\"color: #8B949E\"> * 状态或者错误调用方法</span></span>\n<span><span style=\"color: #8B949E\"> * 错误方法参数 (err, ctx, next)</span></span>\n<span><span style=\"color: #8B949E\"> * 状态方法参数 (ctx, next)</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #C9D1D9\"> [</span><span style=\"color: #FFA657\">key</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">]</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Function</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br></div></div><p>plugin-status 插件通过<code>对不同状态码设置处理函数</code>的方式来实现统一处理,函数名需要按照<code>${prefix}状态码</code>的格式来命令</p>\n<p>例如,在<code>${URSA_ROOT}/config/${URSA_ENV}</code>目录下创建<code>status.config.ts</code>(也可以在 plugin.config.ts 的 status.options 配置)</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// status.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> <</span><span style=\"color: #7EE787\">statusOptions</span><span style=\"color: #FFA657\">></span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// ===> 404状态码处理方法</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">_404</span><span style=\"color: #C9D1D9\">(ctx) {</span></span>\n<span><span style=\"color: #C9D1D9\"> return ctx.render(</span><span style=\"color: #A5D6FF\">'404.html'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><p>上面的配置为状态码 404 的请求添加了统一处理,当请求 404 的时候会返回 404.html 页面,函数接收<code>ctx</code>作为参数,开发者可以根据自己业务情况进行不同处理</p>\n<p>除了对不同状态码情况进行处理外,插件还能<code>对未捕获的错误进行处理</code></p>\n<p>在上面的<code>status.config.ts</code>中添加<code>_error</code>方法可以捕获到未被捕获的错误</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// status.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { IContext } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">"@umajs/core"</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">_404</span><span style=\"color: #FFA657\">(ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> IContext) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> ctx.</span><span style=\"color: #D2A8FF\">render</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'404.html'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">// ===> 未被捕获错误</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">_error</span><span style=\"color: #FFA657\">(e</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Error, ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> IContext) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// ...</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br></div></div><blockquote>\n<p>在<a href=\"/other/errorHandling.html#%E4%BD%BF%E7%94%A8Around\">异常errorHanding</a>一节中我们介绍了@Around 可以用来处理方法调用时发生的异常,<code>当方法使用了@Around</code>进行修饰在代码中<code>使用了try-catch</code>,plugin-status 中配置的<code>_error方法就不会被调用</code>,plugin-status 的只会捕获到未 catch 住的错误</p>\n</blockquote>\n",
"date_modified": "2023-03-17T10:20:25.167Z",
"authors": [],
"tags": []
},
{
"title": "模板引擎(Views)",
"url": "https://umajs.github.io/plugin/Views.html",
"id": "https://umajs.github.io/plugin/Views.html",
"content_html": "<h1 id=\"模板引擎-views\" tabindex=\"-1\"> 模板引擎(Views)</h1>\n<p>模板引擎插件</p>\n<h2 id=\"安装\" tabindex=\"-1\"> 安装</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">$ npm install -S @umajs/plugin-views</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h2 id=\"开启\" tabindex=\"-1\"> 开启</h2>\n<p>在 plugin.config.ts 中开启 plugin-views 插件</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">views: {</span></span>\n<span><span style=\"color: #C9D1D9\"> options: <</span><span style=\"color: #7EE787\">viewsOptions</span><span style=\"color: #C9D1D9\">>{</span></span>\n<span><span style=\"color: #C9D1D9\"> root: </span><span style=\"color: #A5D6FF\">'./views'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> opts: {</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><h3 id=\"options-root\" tabindex=\"-1\"> options.root</h3>\n<p>模板文件的根路径</p>\n<h3 id=\"options-opts\" tabindex=\"-1\"> options.opts</h3>\n<p>模板文件插件配置</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TKoaViewsOptions</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/*</span></span>\n<span><span style=\"color: #8B949E\"> * autoRender the result into ctx.body, defaults to true</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">autoRender</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/*</span></span>\n<span><span style=\"color: #8B949E\"> * default extension for your views</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">extension</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/*</span></span>\n<span><span style=\"color: #8B949E\"> * these options will get passed to the view engine</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">options</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/*</span></span>\n<span><span style=\"color: #8B949E\"> * map a file extension to an engine</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">map</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">/*</span></span>\n<span><span style=\"color: #8B949E\"> * replace consolidate as default engine source</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">engineSource</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.167Z",
"authors": [],
"tags": []
},
{
"title": "插件开发",
"url": "https://umajs.github.io/plugin/dev.html",
"id": "https://umajs.github.io/plugin/dev.html",
"content_html": "<h1 id=\"插件开发\" tabindex=\"-1\"> 插件开发</h1>\n<p>任何 Koa 的中间件都可以直接被框架使用。在实际使用场景中,中间件有全局加载(模版渲染中间件)和局部加载(要忽略的路由规则)的需求。针对这种情况,插件形式的中间件有下面两种形式。</p>\n<h2 id=\"初始化插件\" tabindex=\"-1\"> 初始化插件</h2>\n<p>通过 <code>uma</code> 命令可以快速的给工程添加插件或者可发布的插件工程</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">uma plugin init [pluginName]</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h2 id=\"纯中间件形式\" tabindex=\"-1\"> 纯中间件形式</h2>\n<p>比如我们想使用模版渲染中间件 koa-views,就可以通过插件形式,示例如下:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// app/src/plugins/views/index.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">as</span><span style=\"color: #C9D1D9\"> Koa </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'koa'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">as</span><span style=\"color: #C9D1D9\"> views </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'koa-views'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Uma } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TView</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">root</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">opts</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// views options</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">};</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// options 是插件的配置及 [pluginName].config.ts 的配置结合配置</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> (uma</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Uma, options</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> TView </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #FFA657\"> {})</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Koa.Middleware </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// uma 实例化对象;options 插件配置的 options,等同于 uma.plugin['view'].options</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">views</span><span style=\"color: #C9D1D9\">(options.root, options.opts);</span></span>\n<span><span style=\"color: #C9D1D9\">};</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br></div></div><h2 id=\"复合插件形式\" tabindex=\"-1\"> 复合插件形式</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">export</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TPlugin</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">use</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">handler</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Function</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">filter</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">regexp</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">RegExp</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">handler</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Function</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">ignore</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">regexp</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">RegExp</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">handler</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Function</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">method</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">type</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">RequestMethod</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">|</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">RequestMethod</span><span style=\"color: #C9D1D9\">[];</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">handler</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Function</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">results</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> { [</span><span style=\"color: #FFA657\">key</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">]</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">context</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> { [</span><span style=\"color: #FFA657\">key</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">]</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">request</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> { [</span><span style=\"color: #FFA657\">key</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">]</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">response</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> { [</span><span style=\"color: #FFA657\">key</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">]</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br></div></div><p>复合插件形式不仅可以用中间件进行扩展,还可以对我们常用的 Context、Request、Response 进行扩展,扩展之后我们就可以在代码中使用 ctx、req、res 中使用我们扩展的方法。</p>\n<p>复合插件形式还提供了<code>use、filter、ignore、method</code>四种局部加载中间件的配置形式,具体配置局部加载规则如下:</p>\n<ul>\n<li>use 直接使用已有的中间件</li>\n<li>filter 通过 <code>regexp: RegExp;</code> 属性配置局部加载规则,仅对匹配的规则生效</li>\n<li>ignore 通过 <code>regexp: RegExp;</code> 属性配置局部加载规则,忽略匹配到的规则</li>\n<li>method 通过 <code>type: RequestMethod | RequestMethod[];</code> 属性配置局部加载规则</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugins/demo.plugin.ts</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Uma, IContext, TPlugin } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">"@umajs/core"</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> (uma</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> Uma, options</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">any</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #FFA657\"> {})</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> TPlugin </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> context: {</span></span>\n<span><span style=\"color: #C9D1D9\"> test: </span><span style=\"color: #79C0FF\">123</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 给 ctx 加上 test</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> request: {</span></span>\n<span><span style=\"color: #C9D1D9\"> fileName: </span><span style=\"color: #A5D6FF\">'a.png'</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 给 request 加上 fileName</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> use: { </span><span style=\"color: #8B949E\">// 全局加载</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">handler</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Function</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(ctx.test, ctx.req.fileName, options); </span><span style=\"color: #8B949E\">// >> 123 a.png {}</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'use before'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'use after'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> filter: { </span><span style=\"color: #8B949E\">// 局部加载 仅对/page/路由生效</span></span>\n<span><span style=\"color: #C9D1D9\"> regexp: </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">RegExp</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">/page/</span><span style=\"color: #C9D1D9\">),</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">handler</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Function</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'page get before'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'page get after'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> ignore: { </span><span style=\"color: #8B949E\">// 局部加载 忽略路由/Page/</span></span>\n<span><span style=\"color: #C9D1D9\"> regexp: </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">RegExp</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">/page/</span><span style=\"color: #C9D1D9\">),</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">handler</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Function</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'page ignore before'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'page ignore after'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> method: { </span><span style=\"color: #8B949E\">// 局部加载 仅对method=GET 生效</span></span>\n<span><span style=\"color: #C9D1D9\"> type: </span><span style=\"color: #A5D6FF\">'GET'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">handler</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">IContext</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">Function</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'method get before'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\"> console.</span><span style=\"color: #D2A8FF\">log</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'method get after'</span><span style=\"color: #C9D1D9\">);</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\">};</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br><span>24</span><br><span>25</span><br><span>26</span><br><span>27</span><br><span>28</span><br><span>29</span><br><span>30</span><br><span>31</span><br><span>32</span><br><span>33</span><br><span>34</span><br><span>35</span><br><span>36</span><br><span>37</span><br><span>38</span><br><span>39</span><br><span>40</span><br><span>41</span><br><span>42</span><br><span>43</span><br><span>44</span><br><span>45</span><br></div></div><h2 id=\"npm-包名规范\" tabindex=\"-1\"> npm 包名规范</h2>\n<blockquote>\n<p>欢迎大家在社区中发布支持 Umajs 的插件,为保持插件生态的统一。我们推荐使用<code>umajs-plugin-xxx</code>的命名方式发布自定义的插件包到 npm 中。以方便其他更多人搜索和使用。</p>\n</blockquote>\n",
"date_modified": "2023-03-17T10:20:25.167Z",
"authors": [],
"tags": []
},
{
"title": "国际化(I18n)",
"url": "https://umajs.github.io/plugin/i18n.html",
"id": "https://umajs.github.io/plugin/i18n.html",
"content_html": "<h1 id=\"国际化-i18n\" tabindex=\"-1\"> 国际化(I18n)</h1>\n<p>为了满足用户对于多语言应用的需求,本框架内置了国际化(I18n)支持</p>\n<h2 id=\"安装\" tabindex=\"-1\"> 安装</h2>\n<blockquote>\n<p>$ npm install -S @umajs/plugin-i18n</p>\n</blockquote>\n<h2 id=\"开启服务\" tabindex=\"-1\"> 开启服务</h2>\n<p>请参照插件使用说明开启国际化支持</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">i18n: {</span></span>\n<span><span style=\"color: #C9D1D9\"> enable: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> options: <</span><span style=\"color: #7EE787\">i18nOptions</span><span style=\"color: #C9D1D9\">>{</span></span>\n<span><span style=\"color: #C9D1D9\"> defaultLocale: </span><span style=\"color: #A5D6FF\">'zh-cn'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br></div></div><blockquote>\n<p>具体开启方式请参考 <a href=\"/development/Plugin.html\">plugin</a> 一节中的配置方式</p>\n</blockquote>\n<h2 id=\"options\" tabindex=\"-1\"> options</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">i18nOptions</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">defaultLocale</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 默认语言 默认值:en-US</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">queryField</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 接收的query字段 默认值:locale</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">cookieField</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 存储的cookie字段 默认值:locale</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">writeCookie</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 是否写入cookie 默认值:true</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">cookieMaxAge</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// cookie最大存储时间 默认值:1y</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">cookieDomain</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// cookie的域名 默认值:''</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">defaultDirName</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 多语言文件夹名 默认值:i18n</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">functionName</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 自定义函数名 默认值:i18n</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><h2 id=\"多语言文件\" tabindex=\"-1\"> 多语言文件</h2>\n<p>多语言独立配置成文件,默认放置于<code><root>/src/i18n/</code>文件夹下(可配置 defaultDirName 进行更改),结构如下:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #c9d1d9\">├── i18n\n| ├── zh-CN.js(ts)\n| ├── en-US.js(ts)\n| ├── ...\n</span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// en-US.js</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">function</span><span style=\"color: #FFA657\"> (template) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> welcome: </span><span style=\"color: #D2A8FF\">template</span><span style=\"color: #A5D6FF\">`HAHA, ${</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #A5D6FF\">} ${'name'}!`</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> bye: </span><span style=\"color: #D2A8FF\">template</span><span style=\"color: #A5D6FF\">`goodbye, ${</span><span style=\"color: #C9D1D9\">name</span><span style=\"color: #A5D6FF\">}`</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> hi: </span><span style=\"color: #A5D6FF\">'nice to see you'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// zh-CN.js</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">function</span><span style=\"color: #FFA657\"> (template) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> welcome: </span><span style=\"color: #D2A8FF\">template</span><span style=\"color: #A5D6FF\">`哈哈, ${</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #A5D6FF\">} ${'name'}!`</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> bye: </span><span style=\"color: #D2A8FF\">template</span><span style=\"color: #A5D6FF\">`再见, ${</span><span style=\"color: #C9D1D9\">name</span><span style=\"color: #A5D6FF\">}`</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> hi: </span><span style=\"color: #A5D6FF\">'很高兴见到你!'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br></div></div><ul>\n<li>template 参数为模板处理函数,在插件初始化时会自动调用</li>\n<li>当需要使用自定义变量时,请使用 template 处理字符串模板</li>\n<li>自定义变量提供两种传递方式\n<ul>\n<li>number 占位符 --> <code>${0}</code></li>\n<li>string 占位符 --> <code>${'name'}</code></li>\n</ul>\n</li>\n</ul>\n<h2 id=\"获取多语言文本\" tabindex=\"-1\"> 获取多语言文本</h2>\n<p>统一使用<code>context.i18n</code>来获取多语言描述</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// en-US.js</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">function</span><span style=\"color: #FFA657\"> (template) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> name: </span><span style=\"color: #D2A8FF\">template</span><span style=\"color: #A5D6FF\">`hi, ${</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #A5D6FF\">} ${</span><span style=\"color: #79C0FF\">1</span><span style=\"color: #A5D6FF\">}`</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> phone: </span><span style=\"color: #D2A8FF\">template</span><span style=\"color: #A5D6FF\">`phone: ${'phone'}`</span></span>\n<span><span style=\"color: #C9D1D9\"> time: </span><span style=\"color: #D2A8FF\">template</span><span style=\"color: #A5D6FF\">`today is ${'week'} at ${</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #A5D6FF\">}`</span></span>\n<span><span style=\"color: #C9D1D9\"> hi: nice to see you</span><span style=\"color: #FF7B72\">!</span></span>\n<span><span style=\"color: #C9D1D9\"> };</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">ctx.i18n.</span><span style=\"color: #D2A8FF\">name</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'Scarlett'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #A5D6FF\">'Johansson'</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">==></span><span style=\"color: #C9D1D9\"> hi, Scarlett Johansson</span></span>\n<span><span style=\"color: #C9D1D9\">ctx.i18n.</span><span style=\"color: #D2A8FF\">phone</span><span style=\"color: #C9D1D9\">({phone: </span><span style=\"color: #79C0FF\">123456</span><span style=\"color: #C9D1D9\">}) </span><span style=\"color: #FF7B72\">==></span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">phone</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">123456</span></span>\n<span><span style=\"color: #C9D1D9\">ctx.i18n.</span><span style=\"color: #D2A8FF\">time</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'12:00am'</span><span style=\"color: #C9D1D9\">, {week: </span><span style=\"color: #A5D6FF\">'Sunday'</span><span style=\"color: #C9D1D9\">}) </span><span style=\"color: #FF7B72\">==></span><span style=\"color: #C9D1D9\"> today is Sunday at </span><span style=\"color: #79C0FF\">12</span><span style=\"color: #C9D1D9\">:00am</span></span>\n<span><span style=\"color: #C9D1D9\">ctx.i18n.hi </span><span style=\"color: #FF7B72\">==></span><span style=\"color: #C9D1D9\"> nice to see you</span><span style=\"color: #FF7B72\">!</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// number占位符代表对应变量在调用时的参数位置(从0开始)</span></span>\n<span><span style=\"color: #8B949E\">// 当使用string占位符时,调用时变量使用对象形式传递,置于参数的最后一位</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br></div></div><h3 id=\"basecontroller-中使用\" tabindex=\"-1\"> BaseController 中使用</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">time</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.ctx.i18n.</span><span style=\"color: #D2A8FF\">time</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'12:00am'</span><span style=\"color: #C9D1D9\">, { week: </span><span style=\"color: #A5D6FF\">'Sunday'</span><span style=\"color: #C9D1D9\"> })</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">send</span><span style=\"color: #C9D1D9\">(time)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><h3 id=\"view-中使用\" tabindex=\"-1\"> View 中使用</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\"><!-- ejs --></span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">title</span><span style=\"color: #C9D1D9\">></span><span style=\"color: #FFA198; font-style: italic\"><</span><span style=\"color: #C9D1D9\">%= ctx.i18n.hi %></</span><span style=\"color: #7EE787\">title</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span><span style=\"color: #FFA198; font-style: italic\"><</span><span style=\"color: #C9D1D9\">%= ctx.i18n.phone({phone: 123456}) %></</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br></div></div><h2 id=\"切换语言\" tabindex=\"-1\"> 切换语言</h2>\n<p>插件提供了三种方式供切换多语言,他们的优先级分别是:</p>\n<p><code>query</code> > <code>cookie</code> > <code>header</code></p>\n<ol>\n<li>query: <code>url/?i18n=zh-CN</code></li>\n<li>cookie: <code>i18n=zh-CN</code> (在一次请求后会自动将此种语言记录到 cookie)</li>\n<li>header: <code>Accept-Language: zh-CN,zh;q=0.5</code></li>\n</ol>\n<blockquote>\n<p>当以上三种方式在一次请求中都未设置,则 i18n 会选取默认语言(en-US),可以通过配置进行修改,另外还提供了其他几项自定义配置,配置方法同插件使用方法</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">defaultLocale</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">'en-US'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 默认下使用的语言</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">queryField</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">'i18n'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// query字段名</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">cookieField</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">'i18n'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// cookie字段名</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">writeCookie</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 是否自动写入cookie</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">cookieMaxAge</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">'1y'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// cookie存储时间 <number>time(ms/s/m/h/d/w/y)</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><h3 id=\"手动切换\" tabindex=\"-1\"> 手动切换</h3>\n<p>某些特殊情况下如果需要手动设置语言,可调用<code>ctx.setLocale</code>方法</p>\n<blockquote>\n<p>注意:手动切换仅对当前访问有效</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">/** query: i18n = en-US */</span></span>\n<span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">en</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> ctx.i18n.hi </span><span style=\"color: #8B949E\">// 'nice to see you!'</span></span>\n<span><span style=\"color: #8B949E\">/** setLocale */</span></span>\n<span><span style=\"color: #C9D1D9\">ctx.</span><span style=\"color: #D2A8FF\">setLocale</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'zh-CN'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">zh</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> ctx.i18n.hi </span><span style=\"color: #8B949E\">// '很高兴见到你!'</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.167Z",
"authors": [],
"tags": []
},
{
"title": "定时任务(Schedule)",
"url": "https://umajs.github.io/plugin/schedule.html",
"id": "https://umajs.github.io/plugin/schedule.html",
"content_html": "<h1 id=\"定时任务-schedule\" tabindex=\"-1\"> 定时任务(Schedule)</h1>\n<p>例:我们在 app/schedule 目录下创建一个\npvSchedule.ts 文件</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> {AbstractSchedule} </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/plugin-schedule'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> PvSchedule </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">AbstractSchedule</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">constructor</span><span style=\"color: #FFA657\">(app)</span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">super</span><span style=\"color: #C9D1D9\">(app)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.scheduleInfo </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// rule:'0 0/1 * * * ?', // 每1分鐘更新一次</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// name:'PV', // 定时任务名称</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// switch:true, // 开启定时任务</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">/**</span></span>\n<span><span style=\"color: #8B949E\"> * 业务实现</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">public</span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">task</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// todo task</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br></div></div><h3 id=\"配置\" tabindex=\"-1\"> 配置</h3>\n<p>1,在 config/plugin.config.ts 开启</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'schedule'</span><span style=\"color: #C9D1D9\">: {</span></span>\n<span><span style=\"color: #C9D1D9\"> enable: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><p>2,新建 schedule.config.ts,在其中填入配置项</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> [</span></span>\n<span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">task: PvSchedule</span><span style=\"color: #FFA657\">, </span><span style=\"color: #8B949E\">// 定时任务类</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">auto: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #FFA657\">, </span><span style=\"color: #8B949E\">// true 代表自动执行,false代表手动执行</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">mark:</span><span style=\"color: #A5D6FF\">"pv"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 任务标记</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">},</span></span>\n<span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">...</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">}]</span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><p>3,controller 初始化定时任务参数配置</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> PvSchedule </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">AbstractSchedule</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">constructor</span><span style=\"color: #FFA657\">(app)</span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">super</span><span style=\"color: #C9D1D9\">(app)</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.scheduleInfo </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> rule:</span><span style=\"color: #A5D6FF\">'0 0/1 * * * ?'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 每1分鐘更新一次</span></span>\n<span><span style=\"color: #C9D1D9\"> name:</span><span style=\"color: #A5D6FF\">'PV'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 定时任务名称</span></span>\n<span><span style=\"color: #C9D1D9\"> switch:</span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// true:开启定时任务; false:关闭定时任务</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">...</span><span style=\"color: #C9D1D9\">app</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #8B949E\">/**</span></span>\n<span><span style=\"color: #8B949E\"> * 业务实现</span></span>\n<span><span style=\"color: #8B949E\"> */</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">public</span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">task</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// todo task</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br></div></div><h3 id=\"任务\" tabindex=\"-1\"> 任务</h3>\n<ul>\n<li>手动启动定时任务</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { umaTask } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/plugin-schedule'</span></span>\n<span></span>\n<span><span style=\"color: #D2A8FF\">umaTask</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'pv'</span><span style=\"color: #C9D1D9\">).</span><span style=\"color: #D2A8FF\">start</span><span style=\"color: #C9D1D9\">()</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br></div></div><ul>\n<li>自动启动</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FFA657\">auto</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">true</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><ul>\n<li>手动关闭定时任务</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #D2A8FF\">umaTask</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'pv'</span><span style=\"color: #C9D1D9\">).</span><span style=\"color: #D2A8FF\">cancel</span><span style=\"color: #C9D1D9\">()</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"定时方式\" tabindex=\"-1\"> 定时方式</h3>\n<ul>\n<li>Cron 风格定时器 (建议使用 Cron 风格,避免服务器时间不一致)</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">*</span></span>\n<span><span style=\"color: #C9D1D9\">┬ ┬ ┬ ┬ ┬ ┬</span></span>\n<span><span style=\"color: #C9D1D9\">│ │ │ │ │ </span><span style=\"color: #FF7B72\">|</span></span>\n<span><span style=\"color: #C9D1D9\">│ │ │ │ │ └ day </span><span style=\"color: #FF7B72\">of</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">week</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">7</span><span style=\"color: #C9D1D9\">) (</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\"> or </span><span style=\"color: #79C0FF\">7</span><span style=\"color: #C9D1D9\"> is Sun)</span></span>\n<span><span style=\"color: #C9D1D9\">│ │ │ │ └───── </span><span style=\"color: #D2A8FF\">month</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #79C0FF\">1</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">12</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">│ │ │ └────────── day </span><span style=\"color: #FF7B72\">of</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">month</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #79C0FF\">1</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">31</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">│ │ └─────────────── </span><span style=\"color: #D2A8FF\">hour</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">23</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">│ └──────────────────── </span><span style=\"color: #D2A8FF\">minute</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">59</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\">└───────────────────────── </span><span style=\"color: #D2A8FF\">second</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">59</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #79C0FF\">OPTIONAL</span><span style=\"color: #C9D1D9\">)</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\">6个占位符从左到右分别代表:秒、分、时、日、月、周几</span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br></div></div><ul>\n<li>interval 风格定时器,更多配置参考 node-schedule</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">as</span><span style=\"color: #C9D1D9\"> schedule </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'node-schedule'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #FF7B72\">let</span><span style=\"color: #C9D1D9\"> rule </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> schedule.</span><span style=\"color: #D2A8FF\">RecurrenceRule</span><span style=\"color: #C9D1D9\">();</span></span>\n<span><span style=\"color: #C9D1D9\">rule.second </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\">[</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\">,</span><span style=\"color: #79C0FF\">1</span><span style=\"color: #C9D1D9\">,</span><span style=\"color: #79C0FF\">2</span><span style=\"color: #C9D1D9\">,</span><span style=\"color: #79C0FF\">3.</span><span style=\"color: #FF7B72\">...</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #79C0FF\">.59</span><span style=\"color: #C9D1D9\">] 每秒执行</span></span>\n<span><span style=\"color: #C9D1D9\">rule.second </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\"> 每分钟0秒执行</span></span>\n<span><span style=\"color: #C9D1D9\">rule.minute </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\"> 每小时30分执行</span></span>\n<span></span>\n<span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.scheduleInfo </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> rule, </span><span style=\"color: #8B949E\">// 每1分鐘更新一次</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><h3 id=\"集群-分布式部署-执行定时任务\" tabindex=\"-1\"> 集群/分布式部署 执行定时任务</h3>\n<ul>\n<li>插件包含在分布式部署下,需要保证同一个定时任务只能运行一次,所以需要用事物锁来控制;</li>\n<li>插件采用的是分布式事务锁方案,支持单台 redis 和多台 redis 方案,基于 ioredis 实现</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">as</span><span style=\"color: #C9D1D9\"> RedLock </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'redlock'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">*</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">as</span><span style=\"color: #C9D1D9\"> Redis </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'ioredis'</span><span style=\"color: #C9D1D9\">;</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">client1</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">Redis</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> host: </span><span style=\"color: #A5D6FF\">'redis1.example.com'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> port: </span><span style=\"color: #79C0FF\">6379</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> family: </span><span style=\"color: #79C0FF\">4</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> db: </span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> pass: </span><span style=\"color: #A5D6FF\">'xxx'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> password: </span><span style=\"color: #A5D6FF\">'xxx'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\">});</span></span>\n<span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">client2</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">Redis</span><span style=\"color: #C9D1D9\">({</span></span>\n<span><span style=\"color: #C9D1D9\"> host: </span><span style=\"color: #A5D6FF\">'redis2.example.com'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> port: </span><span style=\"color: #79C0FF\">6378</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> family: </span><span style=\"color: #79C0FF\">4</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> db: </span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> pass: </span><span style=\"color: #A5D6FF\">'xxx'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> password: </span><span style=\"color: #A5D6FF\">'xxx'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\">});</span></span>\n<span></span>\n<span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.scheduleInfo</span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> rule: </span><span style=\"color: #A5D6FF\">'0 0/1 * * * ?'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 每1分鐘更新一次</span></span>\n<span><span style=\"color: #C9D1D9\"> name: </span><span style=\"color: #A5D6FF\">'pv'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 任务名称</span></span>\n<span><span style=\"color: #C9D1D9\"> switch: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 定时任务开启</span></span>\n<span><span style=\"color: #C9D1D9\"> redLock:</span><span style=\"color: #FF7B72\">new</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">RedLock</span><span style=\"color: #C9D1D9\">([client1,client2]), </span><span style=\"color: #8B949E\">// 采用redis锁 </span></span>\n<span><span style=\"color: #C9D1D9\"> redLockTKL:</span><span style=\"color: #79C0FF\">10000</span><span style=\"color: #C9D1D9\"> ,</span><span style=\"color: #8B949E\">//单位毫秒,锁的生存时间,在该时间内,若锁未释放,强行释放 避免死锁情况</span></span>\n<span><span style=\"color: #C9D1D9\"> sleep:</span><span style=\"color: #79C0FF\">1000</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">//单位毫秒,执行任务后主动释放锁的时间</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br><span>24</span><br><span>25</span><br><span>26</span><br><span>27</span><br><span>28</span><br></div></div>",
"date_modified": "2023-03-17T10:20:25.168Z",
"authors": [],
"tags": []
},
{
"title": "react-ssr",
"url": "https://umajs.github.io/ssr/React-ssr.html",
"id": "https://umajs.github.io/ssr/React-ssr.html",
"content_html": "<h1 id=\"react-ssr\" tabindex=\"-1\"> react-ssr</h1>\n<blockquote>\n<p><code>Umajs-react-ssr</code>是由<a href=\"https://github.com/Umajs/plugin-react-ssr\" target=\"_blank\" rel=\"noopener noreferrer\">@umajs/plugin-react-ssr</a> 搭配<a href=\"https://github.com/dazjean/Srejs\" target=\"_blank\" rel=\"noopener noreferrer\">Srejs</a>构建的轻量级,使用简单,灵活的<code>React</code>服务端渲染解决方案;可以在<code>controller</code>和<code>middleware</code>中灵活使用,通过模板引擎式的语法对<code>react</code>页面组件进行服务端渲染。</p>\n</blockquote>\n<h2 id=\"_1、插件介绍\" tabindex=\"-1\"> 1、插件介绍</h2>\n<p><code>plugin-react-ssr</code>插件扩展了<code>Umajs</code>中提供的统一返回处理<code>Result</code>对象,新增了<code>reactView</code>页面组件渲染方法,可在<code>controller</code>自由调用,使用类似传统模板引擎;也同时将方法挂载到了 koa 中间件中的<code>ctx</code>对象上;当一些公关的页面组件,比如 404、异常提示页面、登录或者需要在中间件中拦截跳转时可以在<code>middleware</code>中调用。</p>\n<h2 id=\"_2、特性\" tabindex=\"-1\"> 2、特性</h2>\n<ul>\n<li>不默认路由,不需区分前端路由和后端路由概念,且支持页面级组件 AB 测;<code>灵活</code></li>\n<li>页面组件中没有<code>__isBrowser__</code>之类变量对<code>ssr</code>和<code>csr</code>模式进行特殊区分处理;<code>统一</code>。</li>\n<li>自定义<code>HTML</code>采用<code>htmlWebpackPlugin</code>,没有<code>runtime</code>,页面响应速度更高;<code>高性能</code>。</li>\n<li>支持<code>html</code>中使用<code>nunjucks</code>类模板引擎语法实现<code>SEO</code>;<code>易上手</code>。</li>\n<li>页面开发不依赖框架包装的任何模块,保持原生的<code>React</code>开发体验;<code>友好,易升级</code>。</li>\n<li>数据获取由服务端统一处理加工,页面视图开发和数据加工分开处理;<code>逻辑更清晰</code>。</li>\n<li>支持<code>SSR</code>和<code>CSR</code>动态调整,支持<code>SSR</code>缓存,降级。<code>高可用</code>。</li>\n<li>支持其他<code>koa</code>开发框架使用。<code>可扩展</code>。</li>\n<li>支持 MPA,各页面组件可单独构建,<code>可页面级更新</code>。</li>\n</ul>\n<h2 id=\"_3、插件安装\" tabindex=\"-1\"> 3、插件安装</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">yarn add @umajs/plugin-react-ssr --save</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h2 id=\"_4、插件配置\" tabindex=\"-1\"> 4、插件配置</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> <{ [key</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #FFA657\">]</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> TPluginConfig }>{</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #A5D6FF\">'react-ssr'</span><span style=\"color: #C9D1D9\">: {</span></span>\n<span><span style=\"color: #C9D1D9\"> enable: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> options: {</span></span>\n<span><span style=\"color: #C9D1D9\"> rootDir: </span><span style=\"color: #A5D6FF\">'web'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 客户端页面组件根文件夹</span></span>\n<span><span style=\"color: #C9D1D9\"> rootNode: </span><span style=\"color: #A5D6FF\">'app'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 客户端页面挂载根元素ID</span></span>\n<span><span style=\"color: #C9D1D9\"> ssr: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 全局开启服务端渲染</span></span>\n<span><span style=\"color: #C9D1D9\"> cache: </span><span style=\"color: #79C0FF\">false</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 全局使用服务端渲染缓存 开发环境设置true无效</span></span>\n<span><span style=\"color: #C9D1D9\"> prefixCDN: </span><span style=\"color: #A5D6FF\">'/'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 客户端代码部署CDN前缀</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br></div></div><h2 id=\"_5、web-目录结构\" tabindex=\"-1\"> 5、web 目录结构</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> web # rootDir配置可修改</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> pages # 固定目录</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> home #页面名称</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> index.tsx</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">-</span><span style=\"color: #C9D1D9\"> index.scss</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><h2 id=\"_6、创建-react-页面组件\" tabindex=\"-1\"> 6、创建 react 页面组件</h2>\n<blockquote>\n<p>页面组件开发模式支持 js ,tsx。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'./home.scss'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> React </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'react'</span></span>\n<span><span style=\"color: #FF7B72\">type</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">typeProps</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">say</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">function</span><span style=\"color: #FFA657\"> (props</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> typeProps) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">const</span><span style=\"color: #C9D1D9\"> { </span><span style=\"color: #79C0FF\">say</span><span style=\"color: #C9D1D9\"> } </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> props</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">className</span><span style=\"color: #FF7B72\">=</span><span style=\"color: #A5D6FF\">"ts-demo"</span><span style=\"color: #C9D1D9\">>{say}</</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br></div></div><h2 id=\"_7、脚手架初始化模板工程【推荐】\" tabindex=\"-1\"> 7、脚手架初始化模板工程【推荐】</h2>\n<blockquote>\n<p>在 cli 中支持快速创建<code>umajs-react-ssr</code>模板工程。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">npm i @umajs/cli -g // 安装cli工具</span></span>\n<span><span style=\"color: #C9D1D9\">uma project umajs-react-demo //通过uma初始化工程,选择react模板工程</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br></div></div><p><img src=\"https://user-images.githubusercontent.com/10277671/119756060-8c888200-bed5-11eb-9dda-e0ab7a0410c8.png\" alt=\"image\"></p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #c9d1d9\">cd umajs-react-demo\nyarn install\nyarn start\n\n</span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><h2 id=\"_8、api\" tabindex=\"-1\"> 8、API</h2>\n<blockquote>\n<p>插件扩展了<code>Umajs</code>中提供的统一返回处理<code>Result</code>方法,新增了<code>reactView</code>页面组件可在<code>controller</code>自由调用,方式类似传统模板引擎使用方法;也同时将方法挂载到了 koa 中间件中的<code>ctx</code>对象上;当一些公关的页面组件,比如 404、异常提示页面、登录或者需要在中间件中拦截跳转时可以在<code>middleware</code>中调用。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">interface</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TviewOptions</span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">ssr</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 全局开启服务端渲染</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">cache</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 全局使用服务端渲染缓存</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">useEngine</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 渲染自定义html的页面组件时,选择性开启使用模板引擎</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">baseName</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">//客户端根路由 仅使用react-router时有效</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span><span style=\"color: #C9D1D9\">Result.</span><span style=\"color: #D2A8FF\">reactView</span><span style=\"color: #C9D1D9\">(viewName:string,initProps</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\">object,options</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\">TviewOptions);</span></span>\n<span><span style=\"color: #C9D1D9\">ctx.</span><span style=\"color: #D2A8FF\">reactView</span><span style=\"color: #C9D1D9\">(viewName:string,initProps</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\">object,options</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\">TviewOptions);</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br></div></div><p><em>如果 options 参数传递为空 则默认会使用全局配置属性,全局配置采用插件集成时传递的 options 参数</em></p>\n<p><strong>注意</strong> <code>cache</code>只在<code>生产环境</code>开启有效。</p>\n<h2 id=\"_9、controller中使用\" tabindex=\"-1\"> 9、<strong>controller</strong>中使用</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Result } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/plugin-react-ssr'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">reactView</span><span style=\"color: #C9D1D9\">(</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'home'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> { say: </span><span style=\"color: #A5D6FF\">'hi,I am a ReactView'</span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> { cache: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> )</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br></div></div><h2 id=\"_10、middleware中使用\" tabindex=\"-1\"> 10、<strong>middleware</strong>中使用</h2>\n<blockquote>\n<p>对于中间件的使用,引入顺序需要在插件之后。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">;</span><span style=\"color: #FF7B72\">async</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">ctx</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">next</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">try</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">await</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">next</span><span style=\"color: #C9D1D9\">()</span></span>\n<span><span style=\"color: #C9D1D9\"> } </span><span style=\"color: #FF7B72\">catch</span><span style=\"color: #C9D1D9\"> (e) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> ctx.</span><span style=\"color: #D2A8FF\">reactView</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'error'</span><span style=\"color: #C9D1D9\">, { msg: e.stack }, { cache: </span><span style=\"color: #79C0FF\">false</span><span style=\"color: #C9D1D9\"> })</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><h2 id=\"_11、客户端嵌套路由-react-router\" tabindex=\"-1\"> 11、<strong>客户端嵌套路由(react-router)</strong></h2>\n<blockquote>\n<p>在页面组件中使用 react-router 时,只能在 controller 中使用,切需要服务端对路由做支持。框架默认集成了 BrowserRouter,无需开发者在页面组件中引入</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// 页面组件 web/home/index.js</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> APP </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">Component</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">render</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> (</span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">Switch</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">Route</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">exact</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">path</span><span style=\"color: #FF7B72\">=</span><span style=\"color: #A5D6FF\">"/"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">component</span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\">{Home} /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">Route</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">exact</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">path</span><span style=\"color: #FF7B72\">=</span><span style=\"color: #A5D6FF\">"/about"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">component</span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\">{About} /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">Route</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">exact</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">path</span><span style=\"color: #FF7B72\">=</span><span style=\"color: #A5D6FF\">"/about/:msg"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">component</span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\">{About} /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">Route</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">component</span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\">{Home} /></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">Switch</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> );</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span>\n<span><span style=\"color: #8B949E\">// 服务端路由 前后端路由规则必须保持一致。</span></span>\n<span><span style=\"color: #C9D1D9\">@</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">"/home"</span><span style=\"color: #C9D1D9\">,</span><span style=\"color: #A5D6FF\">"/home/:path"</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #D2A8FF\">browserRouter</span><span style=\"color: #C9D1D9\">() {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">reactView</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'home'</span><span style=\"color: #C9D1D9\">,{say:</span><span style=\"color: #A5D6FF\">"hi,I am a ReactView"</span><span style=\"color: #C9D1D9\">},{cache:</span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,baseName:</span><span style=\"color: #A5D6FF\">'home'</span><span style=\"color: #C9D1D9\">});</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br></div></div><p><strong>注:<code>baseName</code>默认为页面组件标识名称。和 pages 下的页面文件名称保持一致,当服务端根路由和文件名称不一致时,需要给插件传递<code>baseName</code>属性,以确保服务端和客户端根路由一致。</strong></p>\n<h2 id=\"_12、seo-和自定义-html\" tabindex=\"-1\"> 12、<strong>SEO 和自定义 HTML</strong></h2>\n<blockquote>\n<p>在 SEO 场景时,需要动态修改页面的标题和关键字等信息时,我们可以在自定义 html 中使用模板引擎语法,使用模板引擎时需要先开启使用<code>@umajs/plugin-views</code>插件并设置<code>useEngine:true</code>;建议和<code>nunjucks</code>搭配使用。<a href=\"https://github.com/Umajs/umajs-react-ssr/tree/master/web/pages/template\" target=\"_blank\" rel=\"noopener noreferrer\">参考 demo</a>。</p>\n</blockquote>\n<ul>\n<li>插件配置</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #FFA657\">views</span><span style=\"color: #C9D1D9\">: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">enable</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">name</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">'views'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">options</span><span style=\"color: #C9D1D9\">: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">root</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">`${</span><span style=\"color: #C9D1D9\">process</span><span style=\"color: #A5D6FF\">.</span><span style=\"color: #D2A8FF\">cwd</span><span style=\"color: #A5D6FF\">()</span><span style=\"color: #A5D6FF\">}/views`</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">autoRender</span><span style=\"color: #C9D1D9\">:</span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">opts</span><span style=\"color: #C9D1D9\">: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">map</span><span style=\"color: #C9D1D9\">: { </span><span style=\"color: #FFA657\">html</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">'nunjucks'</span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br></div></div><ul>\n<li>设置 useEngine</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// src/index.controller</span></span>\n<span><span style=\"color: #8B949E\">//调用时开启使用模板引擎标识,为提高性能,对未动态修改模板数据的页面组件不要设置此属性</span></span>\n<span><span style=\"color: #C9D1D9\">Result.</span><span style=\"color: #D2A8FF\">reactView</span><span style=\"color: #C9D1D9\">(</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'index'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> { msg: </span><span style=\"color: #A5D6FF\">'This is the template text!'</span><span style=\"color: #C9D1D9\">, title: </span><span style=\"color: #A5D6FF\">'hi,umajs-react-ssr'</span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> { cache: </span><span style=\"color: #79C0FF\">false</span><span style=\"color: #C9D1D9\">, useEngine: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\">)</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><ul>\n<li>模板</li>\n</ul>\n<blockquote>\n<p>框架内置 HTMLWebpackPlugin 插件,开发者在页面组件同级目录下可以覆盖默认 html 模板自定义引入第三方资源和脚本。 更多规则使用请看<a href=\"https://github.com/dazjean/Srejs/blob/mian/doc/htmlTemplate.md\" target=\"_blank\" rel=\"noopener noreferrer\">自定义 HTML</a></p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\"><!-- web/pages/index/index.html --></span></span>\n<span><span style=\"color: #C9D1D9\"><!</span><span style=\"color: #7EE787\">DOCTYPE</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">html</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">html</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">head</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">http-equiv</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"Content-Type"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"text/html; charset=UTF-8"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">charset</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"utf-8"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"viewport"</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width"</span></span>\n<span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"format-detection"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"telephone=no"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"format-detection"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"email=no"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"format-detection"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"address=no;"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"apple-mobile-web-app-capable"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"yes"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"apple-mobile-web-app-status-bar-style"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"default"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"keywords"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"{{msg}}"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">title</span><span style=\"color: #C9D1D9\">>{{title}}</</span><span style=\"color: #7EE787\">title</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!-- 引入第三方组件库样式 --></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">head</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">body</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">id</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"app"</span><span style=\"color: #C9D1D9\">></</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!-- 引入第三方sdk脚本 --></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">body</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">html</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br><span>24</span><br></div></div><h2 id=\"_13、生产部署\" tabindex=\"-1\"> 13、生产部署</h2>\n<blockquote>\n<p>在部署生产环境之前,客户端代码需要提前编译。否则线上首次访问时会耗时比较长,影响用户体验。编译脚本命令为<code>npx srejs build</code></p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #A5D6FF\">"scripts"</span><span style=\"color: #C9D1D9\">: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">"dev"</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">"ts-node-dev --respawn src/app.ts"</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">"build"</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">"tsc && npx srejs build"</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">"prepublish"</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">"npm run build"</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">"prod"</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #A5D6FF\">"node app/app.js --production"</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br></div></div><p><strong>源码请查看<a href=\"https://github.com/Umajs/plugin-react-ssr\" target=\"_blank\" rel=\"noopener noreferrer\"><code>@umajs/plugin-react-ssr</code></a> 和 <a href=\"https://github.com/dazjean/Srejs\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Srejs</code></a> 欢迎 Star 和提供使用反馈。</strong></p>\n<h2 id=\"_14、案例\" tabindex=\"-1\"> 14、案例</h2>\n<ul>\n<li><a href=\"https://github.com/dazjean/Srejs/tree/mian/example/uma-css-module\" target=\"_blank\" rel=\"noopener noreferrer\">uma-css-module</a></li>\n<li><a href=\"https://github.com/dazjean/Srejs/tree/mian/example/uma-react-redux\" target=\"_blank\" rel=\"noopener noreferrer\">uma-react-redux</a></li>\n<li><a href=\"https://github.com/dazjean/Srejs/tree/mian/example/uma-useContext-useReducer\" target=\"_blank\" rel=\"noopener noreferrer\">uma-useContext-useReducer</a></li>\n</ul>\n<h2 id=\"_15、faq\" tabindex=\"-1\"> 15、FAQ</h2>\n<ul>\n<li>自定义覆盖框架webpack配置</li>\n</ul>\n<p>框架默认集成了常用的webpack配置,可满足日常开发使用,比如默认集成了Sass,less,tsx,ts,静态文件,字体等leader配置;当框架默认配置无法满足时,开发者可通过自定义webpack.config.js去覆盖。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #79C0FF\">module</span><span style=\"color: #C9D1D9\">.</span><span style=\"color: #79C0FF\">exports</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">=</span><span style=\"color: #C9D1D9\"> (</span><span style=\"color: #FFA657\">configureWebpack</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #FFA657\">type</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">if</span><span style=\"color: #C9D1D9\"> (type </span><span style=\"color: #FF7B72\">==</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'ssr'</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">//服务端渲染配置</span></span>\n<span><span style=\"color: #C9D1D9\"> } </span><span style=\"color: #FF7B72\">else</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">if</span><span style=\"color: #C9D1D9\"> (type </span><span style=\"color: #FF7B72\">===</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'csr'</span><span style=\"color: #C9D1D9\">) {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">//客户端构建配置</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// configureWebpack.module.rules[0].exclude = /\\/node_module\\/!(antd.*)/;</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> configureWebpack;</span></span>\n<span><span style=\"color: #C9D1D9\">};</span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><p><a href=\"https://github.com/dazjean/Srejs/blob/main/doc/react/webpackconfig.md#%E8%A6%86%E7%9B%96%E6%88%96%E8%80%85%E6%96%B0%E5%A2%9Ewebpack%E9%85%8D%E7%BD%AE\" target=\"_blank\" rel=\"noopener noreferrer\">自定义覆盖webpack配置文档</a></p>\n<ul>\n<li>引入插件后启动项目报错<code>TypeError:Cannot read property 'ROOT' of undefined</code>\n<img src=\"@source/../public/images/TypeError-Cannot-react-ssr.png\" alt=\"image\"></li>\n</ul>\n<blockquote>\n<p>此问题为项目<code>@umajs/core</code>版本冲突导致,解决方案为升级项目所依赖的包版本号,确保项目依赖的包版本号<strong>大于或者等于</strong><code>@umajs/plugin-react-ssr</code>所依赖的<code>@umajs/core</code>版本号</p>\n</blockquote>\n",
"image": "https://user-images.githubusercontent.com/10277671/119756060-8c888200-bed5-11eb-9dda-e0ab7a0410c8.png",
"date_modified": "2023-03-17T10:20:25.169Z",
"authors": [],
"tags": []
},
{
"title": "vue-ssr",
"url": "https://umajs.github.io/ssr/Vue-ssr.html",
"id": "https://umajs.github.io/ssr/Vue-ssr.html",
"content_html": "<h1 id=\"vue-ssr\" tabindex=\"-1\"> vue-ssr</h1>\n<blockquote>\n<p><code>Umajs-vue-ssr</code>是由<a href=\"https://github.com/Umajs/plugin-vue-ssr\" target=\"_blank\" rel=\"noopener noreferrer\">@umajs/plugin-vue-ssr</a> 搭配<a href=\"https://github.com/dazjean/Srejs\" target=\"_blank\" rel=\"noopener noreferrer\">Srejs</a>构建的轻量级,使用简单,灵活的<code>vue</code>服务端渲染解决方案;可以在<code>controller</code>和<code>middleware</code>中灵活使用,通过模板引擎式的语法对<code>vue</code>页面组件进行服务端渲染。</p>\n</blockquote>\n<h2 id=\"_1、插件介绍\" tabindex=\"-1\"> 1、插件介绍</h2>\n<p><code>plugin-vue-ssr</code>插件扩展了<code>Umajs</code>中提供的统一返回处理<code>Result</code>对象,新增了<code>Result.vue</code>页面组件渲染方法,可在<code>controller</code>自由调用,使用类似传统模板引擎;也同时将方法挂载到了 koa 中间件中的<code>ctx</code>对象上;当一些公关的页面组件,比如 404、异常提示页面、登录或者需要在中间件中拦截跳转时可以在<code>middleware</code>中调用。</p>\n<h2 id=\"_2、特性\" tabindex=\"-1\"> 2、特性</h2>\n<ul>\n<li>不默认路由,不需区分前端路由和后端路由概念,且支持页面级组件 AB 测;<code>灵活</code></li>\n<li>页面组件中没有<code>__isBrowser__</code>之类变量对<code>ssr</code>和<code>csr</code>模式进行特殊区分处理;<code>统一</code>。</li>\n<li>自定义<code>HTML</code>采用<code>htmlWebpackPlugin</code>,没有<code>runtime</code>,页面响应速度更高;<code>高性能</code>。</li>\n<li>支持<code>html</code>中使用<code>nunjucks</code>类模板引擎语法实现<code>SEO</code>;<code>易上手</code>。</li>\n<li>页面开发不依赖框架包装的任何模块,保持原生的<code>vue</code>开发体验;<code>友好,易升级</code>。</li>\n<li>数据获取提供服务端注入方式,页面视图渲染和数据加工分开处理;<code>逻辑更清晰</code>。</li>\n<li>支持<code>SSR</code>和<code>CSR</code>动态调整,支持<code>SSR</code>缓存,降级。<code>高可用</code>。</li>\n<li>支持其他<code>koa</code>开发框架使用。<code>可扩展</code>。</li>\n<li>支持 MPA,各页面组件可单独构建,<code>可页面级更新</code>。</li>\n</ul>\n<h2 id=\"_3、脚手架快速初始化项目-推荐\" tabindex=\"-1\"> 3、脚手架快速初始化项目[推荐]</h2>\n<blockquote>\n<p>在 cli 中支持快速创建<code>umajs-vue-ssr</code>模板工程。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">$ npm i @umajs/cli -g // 安装cli工具</span></span>\n<span><span style=\"color: #C9D1D9\">$ uma project umajs-vue-demo //通过uma初始化工程,选择vue2.0模板工程</span></span>\n<span><span style=\"color: #C9D1D9\">✔ loading template</span></span>\n<span><span style=\"color: #FF7B72\">?</span><span style=\"color: #C9D1D9\"> please choise a template to create project (Use arrow keys)</span></span>\n<span><span style=\"color: #C9D1D9\"> all,全套模板,包含部分代码示例</span></span>\n<span><span style=\"color: #C9D1D9\"> mini,极简模板,仅有核心代码</span></span>\n<span><span style=\"color: #C9D1D9\"> standard,标准模板,不包含示例代码</span></span>\n<span><span style=\"color: #C9D1D9\"> react,umajs-react-ssr模板,包含示例代码</span></span>\n<span><span style=\"color: #C9D1D9\">❯ vue2.0,umajs-vue-ssr模板,包含示例代码</span></span>\n<span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><p>依赖安装和启动</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #c9d1d9\">cd umajs-vue-demo\nyarn install\nyarn start\n\n</span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br></div></div><h2 id=\"_4、手动安装集成插件\" tabindex=\"-1\"> 4、手动安装集成插件</h2>\n<h3 id=\"插件安装\" tabindex=\"-1\"> 插件安装</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #c9d1d9\"> yarn add @umajs/plugin-vue-ssr --save\n</span></span></code></pre><div><span>1</span><br></div></div><p>打开 <code>package.json</code> 文件并添加 <code>scripts</code> 配置段:</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #c9d1d9\">"scripts": {\n "start":'node app.js',\n "build":"npx ssr build",\n "analyzer": "npx ssr analyzer",\n},\n</span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><ul>\n<li><code>start</code> 启动你的 node 项目</li>\n<li><code>build</code> 运行<code>npx ssr build</code>构建用于生产环境的应用程序,Srejs 为多项目工程目录结构,可通过指定页面标识单独构建或者启动特定页面,命令为:<code>npm run build xxx</code></li>\n<li><code>analyzer</code> 运行<code>npx ssr analyzer</code> 用于分析页面组件打包依赖分析 可通过 <code>npm run analyzer xxx</code> xxx 为页面组件标识,可指定分析某个页面组件打包结果</li>\n</ul>\n<h3 id=\"插件配置\" tabindex=\"-1\"> 插件配置</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\">// plugin.config.ts</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> <{ [key</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">string</span><span style=\"color: #FFA657\">]</span><span style=\"color: #FF7B72\">:</span><span style=\"color: #FFA657\"> TPluginConfig }>{</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">vue: {</span></span>\n<span><span style=\"color: #C9D1D9\"> enable: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> options: {</span></span>\n<span><span style=\"color: #C9D1D9\"> rootDir: </span><span style=\"color: #A5D6FF\">'web'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 客户端页面组件根文件夹</span></span>\n<span><span style=\"color: #C9D1D9\"> rootNode: </span><span style=\"color: #A5D6FF\">'app'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 客户端页面挂载根元素ID</span></span>\n<span><span style=\"color: #C9D1D9\"> ssr: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 全局开启服务端渲染</span></span>\n<span><span style=\"color: #C9D1D9\"> cache: </span><span style=\"color: #79C0FF\">false</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 全局使用服务端渲染缓存 开发环境设置true无效</span></span>\n<span><span style=\"color: #C9D1D9\"> prefixCDN: </span><span style=\"color: #A5D6FF\">'/'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 客户端代码部署CDN前缀</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br></div></div><h3 id=\"目录结构\" tabindex=\"-1\"> 目录结构</h3>\n<p>框架默认配置属性<code>rootDir</code>默认为根目录下<code>web</code>,pages 下是页面组件入口,比如<code>list</code>页面,vue 主入口文件为<code>list/index.js</code>,页面组件为<code>list/App.vue</code></p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #c9d1d9\">└── web\n └── pages\n └── list\n ├── App.vue\n ├── index.js\n</span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br></div></div><h3 id=\"页面组件-app-vue\" tabindex=\"-1\"> 页面组件(App.vue)</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!--vue2.0版本APP.vue必须要设置根元素--></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">id</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"app"</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">h1</span><span style=\"color: #C9D1D9\">>{{ msg }}</</span><span style=\"color: #7EE787\">h1</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">name: </span><span style=\"color: #A5D6FF\">'app'</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">data</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> msg: </span><span style=\"color: #A5D6FF\">'hi vue ssr!'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br></div></div><h3 id=\"页面主入口文件-index-js\" tabindex=\"-1\"> 页面主入口文件(index.js)</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> App </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'./App.vue'</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">App</span><span style=\"color: #FFA657\">, </span><span style=\"color: #8B949E\">// 必须导出App</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">Router</span><span style=\"color: #FFA657\">, </span><span style=\"color: #8B949E\">//如使用vue-router 导出路由配置对象</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">Store</span><span style=\"color: #FFA657\">, </span><span style=\"color: #8B949E\">//如使用vuex 导出store对象</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br></div></div><p><code>Pages</code>下按照文件夹名称定义 vue 页面组件,每一个页面组件必须包含<code>inde.js</code>主入口文件,文件必须导出组件<code>App</code>。如果使用<code>vue-router</code>,则将路由配置导出为<code>Router</code>对象;当使用<code>vuex</code>时,则将初始化配置导出为<code>Store</code>。</p>\n<h2 id=\"_5、插件使用\" tabindex=\"-1\"> 5、插件使用</h2>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { BaseController, Path } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'@umajs/core'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> { Result } </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'../plugins/vue-ssr'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">class</span><span style=\"color: #FFA657\"> Index </span><span style=\"color: #FF7B72\">extends</span><span style=\"color: #FFA657\"> </span><span style=\"color: #79C0FF\">BaseController</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> @</span><span style=\"color: #D2A8FF\">Path</span><span style=\"color: #FFA657\">(</span><span style=\"color: #A5D6FF\">'/'</span><span style=\"color: #FFA657\">)</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">index</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> Result.</span><span style=\"color: #D2A8FF\">vue</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'index'</span><span style=\"color: #C9D1D9\">, { title: </span><span style=\"color: #A5D6FF\">'umajs-vue-ssr'</span><span style=\"color: #C9D1D9\"> })</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br></div></div><h2 id=\"_6、插件-api\" tabindex=\"-1\"> 6、插件 API</h2>\n<blockquote>\n<p>插件扩展了<code>Umajs</code>中提供的统一返回处理<code>Result</code>方法,新增了<code>vue</code>页面组件可在<code>controller</code>自由调用,方式类似传统模板引擎使用方法;也同时将方法挂载到了 koa 中间件中的<code>ctx</code>对象上;当一些公关的页面组件,比如 404、异常提示页面、登录或者需要在中间件中拦截跳转时可以在<code>middleware</code>中调用。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">interface</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">TviewOptions</span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">ssr</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 全局开启服务端渲染</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FFA657\">cache</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">boolean</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #8B949E\">// 全局使用服务端渲染缓存</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span><span style=\"color: #C9D1D9\">Result.</span><span style=\"color: #D2A8FF\">vue</span><span style=\"color: #C9D1D9\">(viewName:string,initProps</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\">object,options</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\">TviewOptions);</span></span>\n<span><span style=\"color: #C9D1D9\">ctx.</span><span style=\"color: #D2A8FF\">vue</span><span style=\"color: #C9D1D9\">(viewName:string,initProps</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\">object,options</span><span style=\"color: #FF7B72\">?:</span><span style=\"color: #C9D1D9\">TviewOptions);</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br></div></div><p><em>如果 options 参数传递为空 则默认会使用全局配置属性,全局配置采用插件集成时传递的 options 参数</em></p>\n<p><strong>注意</strong> <code>cache</code>只在<code>生产环境</code>开启有效。</p>\n<h2 id=\"_7、数据获取\" tabindex=\"-1\"> 7、数据获取</h2>\n<blockquote>\n<p>在<code>Pages</code>页面中,vue 页面组件获取数据有两种形式;我们分为服务端直出数据(Props 和 State)和 vue 组件静态方法<code>asyncData</code>获取两种形式。我们可以通过这两种方式对服务端渲染时首次页面渲染进行数据填充,使得服务端渲染时能返回完整的 DOM 结构,提高用户体验和更利于<code>SEO</code>.</p>\n</blockquote>\n<h3 id=\"服务端直出-props\" tabindex=\"-1\"> 服务端直出 Props</h3>\n<blockquote>\n<p>框架在服务端提供了页面组件的渲染函数<code>Result.vue</code>,在调用函数渲染时我们可以在 initProps 参数中传递初始化的数据对象;这些数据可以在创建 vue 实例时会注册为组件实例的 Props 参数。在页面组件中我们可以将其定义为 Props。 <a href=\"https://cn.vuejs.org/v2/guide/components-props.html\" target=\"_blank\" rel=\"noopener noreferrer\">了解 vue 组件 Props</a></p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">Result.</span><span style=\"color: #D2A8FF\">vue</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'list'</span><span style=\"color: #C9D1D9\">, {</span></span>\n<span><span style=\"color: #C9D1D9\"> title: </span><span style=\"color: #A5D6FF\">'xxx'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> keywords: </span><span style=\"color: #A5D6FF\">'xxx'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> description: </span><span style=\"color: #A5D6FF\">'xxxx'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> say: </span><span style=\"color: #A5D6FF\">'hi!'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br></div></div><p>在页面组件中我们可以直接通过 Props 将服务端直出的数据在 vue 模板中使用。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!--vue2.0版本APP.vue必须要设置根元素--></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">id</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"app"</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">h1</span><span style=\"color: #C9D1D9\">>{{ title }}</</span><span style=\"color: #7EE787\">h1</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">>{{ say }}</</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">name: </span><span style=\"color: #A5D6FF\">'app'</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">props: [</span><span style=\"color: #A5D6FF\">'say'</span><span style=\"color: #C9D1D9\">, </span><span style=\"color: #A5D6FF\">'title'</span><span style=\"color: #C9D1D9\">]</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br></div></div><p>**特别说明:**在<code>initProps</code>参数中,<code>title,keywords,description</code>还会默认被解析为 web 网页头中的 标题,关键字,描述填充。</p>\n<h3 id=\"服务端初直出-state\" tabindex=\"-1\"> 服务端初直出 State</h3>\n<blockquote>\n<p>在 initProps 对象中,框架会默认将 State 属性初始化为 store 实例。从根组件“注入”到每一个子组件中。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">Result.</span><span style=\"color: #D2A8FF\">vue</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'list'</span><span style=\"color: #C9D1D9\">, {</span></span>\n<span><span style=\"color: #C9D1D9\"> title: </span><span style=\"color: #A5D6FF\">'xxx'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> keywords: </span><span style=\"color: #A5D6FF\">'xxx'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> description: </span><span style=\"color: #A5D6FF\">'xxxx'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> state: {</span></span>\n<span><span style=\"color: #C9D1D9\"> say: </span><span style=\"color: #A5D6FF\">'hi!'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\">})</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br></div></div><p>我们可以直接在 <code>Vue</code> 任意组件中直接获得 <code>Vuex</code> 状态。获取方式为<code>this.$store.state</code>。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!--vue2.0版本APP.vue必须要设置根元素--></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">id</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"app"</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">h1</span><span style=\"color: #C9D1D9\">>{{ title }}</</span><span style=\"color: #7EE787\">h1</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">>{{ say }}</</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">name: </span><span style=\"color: #A5D6FF\">'app'</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">props: [</span><span style=\"color: #A5D6FF\">'title'</span><span style=\"color: #C9D1D9\">]</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">data</span><span style=\"color: #C9D1D9\">: () </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> say: </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.$store.state.say,</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br></div></div><p>由于 Vuex 的状态存储是响应式的,从 store 实例中可以在计算属性中返回某个状态。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">name: </span><span style=\"color: #A5D6FF\">'app'</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">props: [</span><span style=\"color: #A5D6FF\">'title'</span><span style=\"color: #C9D1D9\">]</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">computed: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">say</span><span style=\"color: #C9D1D9\">() {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.$store.state.say</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br></div></div><p><strong>更多获取 Vuex 状态的使用方法可查看官方文档<a href=\"https://vuex.vuejs.org/zh/guide/state.html\" target=\"_blank\" rel=\"noopener noreferrer\">Vuex</a></strong></p>\n<h3 id=\"asyncdata-静态方法\" tabindex=\"-1\"> asyncData 静态方法</h3>\n<blockquote>\n<p><code>asyncData</code>是页面组件数据获取的钩子,<code>只能作用于页面</code>。其接收对象参数默认是<code>vuex</code>的<code>store</code>和当前<code>router</code>,通过<code>router</code>可以获取到当前路由的参数等数据,然后调用异步请求获取 http 类型的数据,然后通过<code>store</code>触发状态管理的更新,也可直接改写操作<code>store.state</code>属性。框架会合并到<code>store</code>数据上下文<code>state</code>中。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">name: </span><span style=\"color: #A5D6FF\">'app'</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">data</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> msg: </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.$store.state.msg,</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">async</span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">asyncData</span><span style=\"color: #FFA657\">({ store, route }) </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// store.state.msg = 'about来自asyncData的数据'</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\">// 触发 action 后,会返回 Promise</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> store.</span><span style=\"color: #D2A8FF\">dispatch</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'fetchItem'</span><span style=\"color: #C9D1D9\">, route.params.id)</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br></div></div><p><strong>asyncData</strong>灵感来自官方<a href=\"https://ssr.vuejs.org/zh/guide/data.html#%E6%95%B0%E6%8D%AE%E9%A2%84%E5%8F%96%E5%AD%98%E5%82%A8%E5%AE%B9%E5%99%A8-data-store\" target=\"_blank\" rel=\"noopener noreferrer\">vue-ssr 示例</a>和<a href=\"https://zh.nuxtjs.org/docs/2.x/features/data-fetching#async-data\" target=\"_blank\" rel=\"noopener noreferrer\">nuxtjs</a>。</p>\n<h2 id=\"_8、seo-和-html\" tabindex=\"-1\"> 8、SEO 和 HTML</h2>\n<blockquote>\n<p>在<code>initProps</code>中通过,默认接收<code>title,keywords,description</code>作为页面标题,关键字,网页描述填充字段。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">Result.</span><span style=\"color: #D2A8FF\">vue</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'list'</span><span style=\"color: #C9D1D9\">, { title: </span><span style=\"color: #A5D6FF\">'xxx'</span><span style=\"color: #C9D1D9\">, keywords: </span><span style=\"color: #A5D6FF\">'xxx'</span><span style=\"color: #C9D1D9\">, description: </span><span style=\"color: #A5D6FF\">'xxxx'</span><span style=\"color: #C9D1D9\"> })</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"自定义-html\" tabindex=\"-1\"> 自定义 html</h3>\n<blockquote>\n<p>框架内置<code>HTMLWebpackPlugin</code>插件,开发者在页面组件同级目录下可以覆盖默认 html 模板自定义引入第三方资源和脚本。自定义 html 文件名为页面下的<code>index.html</code>。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #8B949E\"><!-- web/pages/index/index.html --></span></span>\n<span><span style=\"color: #C9D1D9\"><!</span><span style=\"color: #7EE787\">DOCTYPE</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">html</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">html</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">head</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">http-equiv</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"Content-Type"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"text/html; charset=UTF-8"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">charset</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"utf-8"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"viewport"</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width"</span></span>\n<span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"format-detection"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"telephone=no"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"format-detection"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"email=no"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"format-detection"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"address=no;"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"apple-mobile-web-app-capable"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"yes"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">meta</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">name</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"apple-mobile-web-app-status-bar-style"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">content</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"default"</span><span style=\"color: #C9D1D9\"> /></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">title</span><span style=\"color: #C9D1D9\">>vue ssr</</span><span style=\"color: #7EE787\">title</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!-- 引入第三方组件库样式 --></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">head</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">body</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!--vue-ssr-outlet--></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">body</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!-- 引入第三方sdk脚本 --></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">html</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br></div></div><h3 id=\"模板插值\" tabindex=\"-1\"> 模板插值</h3>\n<p>在 html 模板中,还可以使用模板插值。服务端渲染初始化时传递的<code>initProps</code>数据在服务端渲染时会被注入为<code>渲染上下文对象</code>。</p>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">html</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">head</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!-- 使用双花括号(double-mustache)进行 HTML 转义插值(HTML-escaped interpolation) --></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">title</span><span style=\"color: #C9D1D9\">>{{ title }}</</span><span style=\"color: #7EE787\">title</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!-- 使用三花括号(triple-mustache)进行 HTML 不转义插值(non-HTML-escaped interpolation) --></span></span>\n<span><span style=\"color: #C9D1D9\"> {{{ meta }}}</span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">head</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">body</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #8B949E\"><!--vue-ssr-outlet--></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">body</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">html</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br></div></div><h3 id=\"支持全局-html\" tabindex=\"-1\"> 支持全局 HTML</h3>\n<p>为满足业务引入第三方脚本也提供了以下方式自定义 html 模板。</p>\n<ul>\n<li><code>web/pages/xxx/index.html</code>(局部页面生效)</li>\n<li><code>web/index.html</code>(全局生效)</li>\n</ul>\n<p><strong>优先级</strong><code>web/pages/xxx/index.html</code> > <code>web/index.html</code></p>\n<h2 id=\"_9、vuex\" tabindex=\"-1\"> 9、vuex</h2>\n<blockquote>\n<p>当项目比较复杂时,我们可以在页面组件入口文件中导出 Vuex store 对象。框架会自动从根页面组件注入 vue 子组件中,通过$store 访问到实例化后的 store。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> App </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'./App.vue'</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">App</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">Store: {</span></span>\n<span><span style=\"color: #C9D1D9\"> state: {</span></span>\n<span><span style=\"color: #C9D1D9\"> count: </span><span style=\"color: #79C0FF\">100</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> mutations: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">increment</span><span style=\"color: #C9D1D9\">: (</span><span style=\"color: #FFA657\">state</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> state.count</span><span style=\"color: #FF7B72\">++</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">decrement</span><span style=\"color: #C9D1D9\">: (</span><span style=\"color: #FFA657\">state</span><span style=\"color: #C9D1D9\">) </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> state.count</span><span style=\"color: #FF7B72\">--</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br></div></div><p>框架接收到 Store 对象后,会实例化 vuex。并且初始化到 vue 实例中,通过 vue.use 注入到全局。对于初始化的 state 数据,如果在 initProps 中也传入同名的属性,则 initProps.state 将会覆盖主入口文件传入 store.state 中的属性值。</p>\n<h3 id=\"服务端初始化-state\" tabindex=\"-1\"> 服务端初始化 state</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\">Result.</span><span style=\"color: #D2A8FF\">vue</span><span style=\"color: #C9D1D9\">(ctx, </span><span style=\"color: #A5D6FF\">'vuex'</span><span style=\"color: #C9D1D9\">, { state: { count: </span><span style=\"color: #79C0FF\">200</span><span style=\"color: #C9D1D9\"> } })</span></span>\n<span></span></code></pre><div><span>1</span><br></div></div><h3 id=\"页面组件获取状态\" tabindex=\"-1\"> 页面组件获取状态</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">id</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"app"</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">>{{ count }}</</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">button</span><span style=\"color: #C9D1D9\"> @</span><span style=\"color: #79C0FF\">click</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"</span><span style=\"color: #C9D1D9\">increment</span><span style=\"color: #A5D6FF\">"</span><span style=\"color: #C9D1D9\">>+</</span><span style=\"color: #7EE787\">button</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">button</span><span style=\"color: #C9D1D9\"> @</span><span style=\"color: #79C0FF\">click</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"</span><span style=\"color: #C9D1D9\">decrement</span><span style=\"color: #A5D6FF\">"</span><span style=\"color: #C9D1D9\">>-</</span><span style=\"color: #7EE787\">button</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">div</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">name: </span><span style=\"color: #A5D6FF\">'vuex'</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">computed: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">count</span><span style=\"color: #C9D1D9\">() {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #FF7B72\">return</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.$store.state.count</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">methods: {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">increment</span><span style=\"color: #C9D1D9\">() {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.$store.</span><span style=\"color: #D2A8FF\">commit</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'increment'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">decrement</span><span style=\"color: #C9D1D9\">() {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">this</span><span style=\"color: #C9D1D9\">.$store.</span><span style=\"color: #D2A8FF\">commit</span><span style=\"color: #C9D1D9\">(</span><span style=\"color: #A5D6FF\">'decrement'</span><span style=\"color: #C9D1D9\">)</span></span>\n<span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br><span>19</span><br><span>20</span><br><span>21</span><br><span>22</span><br><span>23</span><br><span>24</span><br><span>25</span><br><span>26</span><br><span>27</span><br><span>28</span><br></div></div><p>最后展示到页面上的<code>count</code>初始值为:<code>200</code></p>\n<h2 id=\"_10、vue-router\" tabindex=\"-1\"> 10、vue-router</h2>\n<blockquote>\n<p>当 vue 页面组件需要和 vue-router 结合开发单页面应用时,在入口文件中我们也可以通过 Router 属性导出路由配置。</p>\n</blockquote>\n<ul>\n<li>客户端页面组件入口文件路由配置</li>\n</ul>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> App </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'./App.vue'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> About </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'./about.vue'</span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> Home </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'./home.vue'</span></span>\n<span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">App</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #C9D1D9\">Router: {</span></span>\n<span><span style=\"color: #C9D1D9\"> mode: </span><span style=\"color: #A5D6FF\">'history'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> fallback: </span><span style=\"color: #79C0FF\">false</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> base: </span><span style=\"color: #A5D6FF\">'/index/'</span><span style=\"color: #C9D1D9\">,</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #D2A8FF\">scrollBehavior</span><span style=\"color: #C9D1D9\">: () </span><span style=\"color: #FF7B72\">=></span><span style=\"color: #C9D1D9\"> ({ y: </span><span style=\"color: #79C0FF\">0</span><span style=\"color: #C9D1D9\"> }),</span></span>\n<span><span style=\"color: #C9D1D9\"> routes: [</span></span>\n<span><span style=\"color: #C9D1D9\"> { path: </span><span style=\"color: #A5D6FF\">'/about'</span><span style=\"color: #C9D1D9\">, props: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">, component: About },</span></span>\n<span><span style=\"color: #C9D1D9\"> { path: </span><span style=\"color: #A5D6FF\">'/home'</span><span style=\"color: #C9D1D9\">, props: </span><span style=\"color: #79C0FF\">true</span><span style=\"color: #C9D1D9\">, component: Home },</span></span>\n<span><span style=\"color: #C9D1D9\"> { path: </span><span style=\"color: #A5D6FF\">'/'</span><span style=\"color: #C9D1D9\">, redirect: </span><span style=\"color: #A5D6FF\">'/home'</span><span style=\"color: #C9D1D9\"> },</span></span>\n<span><span style=\"color: #C9D1D9\"> ],</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br><span>18</span><br></div></div><p><strong>注意:服务端渲染模式下不支持使用 import 动态导入组件方式进行路由懒加载</strong></p>\n<ul>\n<li>服务端路由</li>\n</ul>\n<blockquote>\n<p>对于服务端我们需要保持客户端和服务端路由一致,否则会出现子路由页面刷新<code>404</code>现象。</p>\n</blockquote>\n<ul>\n<li>页面路由获取数据</li>\n</ul>\n<blockquote>\n<p>在页面组件中页面数据获取方式和普通页面组件保持一致,我们可以使用服务端渲染 props 直出和 asyncData 钩子函数两种方式获取,具体使用参考<code>数据获取</code>章节。</p>\n</blockquote>\n<h2 id=\"_11、内置-css-支持\" tabindex=\"-1\"> 11、内置 css 支持</h2>\n<blockquote>\n<p>框架内置了<code>vue-style-loader</code>以及 css 预处理器 loader,支持<code>*.vue</code>单个文件组件内的 <code><style></code>提取为单独 css 样式文件。也支持 CSS Modules。以下示例均开箱即用,无需额外配置。</p>\n</blockquote>\n<h3 id=\"scoped-css\" tabindex=\"-1\"> Scoped CSS</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">class</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"scoped"</span><span style=\"color: #C9D1D9\">>style scoped</</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">style</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">scoped</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #79C0FF\">.scoped</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">color</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">red</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">font-size</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">18</span><span style=\"color: #FF7B72\">px</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">style</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br></div></div><h3 id=\"预处理器-less-scss\" tabindex=\"-1\"> 预处理器 less/scss</h3>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">class</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"scoped"</span><span style=\"color: #C9D1D9\">>style scoped</</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">style</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">lang</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"less"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">scoped</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #79C0FF\">.scoped</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">color</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">red</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">font-size</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">18</span><span style=\"color: #FF7B72\">px</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">style</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">style</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">lang</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"scss"</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">scoped</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #79C0FF\">.scoped_scss</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">color</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">red</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">font-size</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">18</span><span style=\"color: #FF7B72\">px</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">style</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br><span>16</span><br><span>17</span><br></div></div><p><em><em>当我们采用</em>.less 或者</em>.scss 文件编写样式时,也可以从 JavaScript 中导入 CSS,例如,import './foo.css'**</p>\n<h2 id=\"_12、css-modules\" tabindex=\"-1\"> 12、CSS Modules</h2>\n<ul>\n<li>使用 style module</li>\n</ul>\n<blockquote>\n<p>在你的 <code><style></code>上添加 module 特性,这个 module 特性指引 Vue Loader 作为名为 $style 的计算属性,向组件注入 CSS Modules 局部对象。然后你就可以在模板中通过一个动态类绑定来使用它了。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\"> :</span><span style=\"color: #79C0FF\">class</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"</span><span style=\"color: #C9D1D9\">$style.red</span><span style=\"color: #A5D6FF\">"</span><span style=\"color: #C9D1D9\">>This should be red</</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">style</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">module</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #79C0FF\">.red</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">color</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">red</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span><span style=\"color: #79C0FF\">.bold</span><span style=\"color: #C9D1D9\"> {</span></span>\n<span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #79C0FF\">font-weight</span><span style=\"color: #C9D1D9\">: </span><span style=\"color: #79C0FF\">bold</span><span style=\"color: #C9D1D9\">;</span></span>\n<span><span style=\"color: #C9D1D9\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">style</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br></div></div><p><strong>详细原理查看官方文档<a href=\"https://vue-loader.vuejs.org/zh/guide/css-modules.html#css-modules\" target=\"_blank\" rel=\"noopener noreferrer\">vue-loader</a></strong></p>\n<ul>\n<li>使用预处理器样</li>\n</ul>\n<blockquote>\n<p>如果你的样式是从 JavaScript 中导入的,那么你只需要将把文件命名为<code>*.module.(less|scss|css)</code>。</p>\n</blockquote>\n<div><pre style=\"background-color: #0d1117\"><code><span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> <</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\"> :</span><span style=\"color: #79C0FF\">class</span><span style=\"color: #C9D1D9\">=</span><span style=\"color: #A5D6FF\">"</span><span style=\"color: #C9D1D9\">styles.module</span><span style=\"color: #A5D6FF\">"</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"> 对于外部样式文件,框架默认支持以文件命名: xxx.module.(less|scss|css)</span></span>\n<span><span style=\"color: #C9D1D9\"> 开启使用css module</span></span>\n<span><span style=\"color: #C9D1D9\"> </</span><span style=\"color: #7EE787\">p</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">template</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span>\n<span><span style=\"color: #C9D1D9\"><</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span><span style=\"color: #FF7B72\">import</span><span style=\"color: #C9D1D9\"> styles </span><span style=\"color: #FF7B72\">from</span><span style=\"color: #C9D1D9\"> </span><span style=\"color: #A5D6FF\">'./index.module.less'</span></span>\n<span><span style=\"color: #FF7B72\">export</span><span style=\"color: #FFA657\"> </span><span style=\"color: #FF7B72\">default</span><span style=\"color: #FFA657\"> {</span></span>\n<span><span style=\"color: #FFA657\"> </span><span style=\"color: #D2A8FF\">data</span><span style=\"color: #FFA657\">() </span><span style=\"color: #C9D1D9\">{</span></span>\n<span><span style=\"color: #C9D1D9\"> styles</span></span>\n<span><span style=\"color: #C9D1D9\"> }</span><span style=\"color: #FFA657\">,</span></span>\n<span><span style=\"color: #FFA657\">}</span></span>\n<span><span style=\"color: #C9D1D9\"></</span><span style=\"color: #7EE787\">script</span><span style=\"color: #C9D1D9\">></span></span>\n<span></span></code></pre><div><span>1</span><br><span>2</span><br><span>3</span><br><span>4</span><br><span>5</span><br><span>6</span><br><span>7</span><br><span>8</span><br><span>9</span><br><span>10</span><br><span>11</span><br><span>12</span><br><span>13</span><br><span>14</span><br><span>15</span><br></div></div><h2 id=\"_13、案例\" tabindex=\"-1\"> 13、案例</h2>\n<ul>\n<li><a href=\"https://github.com/Umajs/umajs-vue-ssr/tree/main/web/pages/css\" target=\"_blank\" rel=\"noopener noreferrer\">css-module</a></li>\n<li><a href=\"https://github.com/Umajs/umajs-vue-ssr/tree/main/web/pages/vuex\" target=\"_blank\" rel=\"noopener noreferrer\">vuex</a></li>\n<li><a href=\"https://github.com/Umajs/umajs-vue-ssr/tree/main/web/pages/router\" target=\"_blank\" rel=\"noopener noreferrer\">vue-router</a></li>\n<li><a href=\"https://github.com/Umajs/umajs-vue-ssr/tree/main/web/pages/element\" target=\"_blank\" rel=\"noopener noreferrer\">elementUI</a></li>\n<li><a href=\"https://github.com/Umajs/umajs-vue-ssr/tree/main/web/pages/andv\" target=\"_blank\" rel=\"noopener noreferrer\">ant-design-vue</a></li>\n</ul>\n<h2 id=\"_14、源码\" tabindex=\"-1\"> 14、源码</h2>\n<ul>\n<li><a href=\"https://github.com/dazjean/srejs\" target=\"_blank\" rel=\"noopener noreferrer\">@srejs/vue</a></li>\n<li><a href=\"https://github.com/Umajs/plugin-vue-ssr\" target=\"_blank\" rel=\"noopener noreferrer\">@umajs/plugin-vue-ssr</a></li>\n</ul>\n<p><strong>如果你觉得有用,请 star 支持下我们~谢谢!</strong></p>\n",
"date_modified": "2023-03-17T10:20:25.170Z",
"authors": [],
"tags": []
}
]
}