华南理工大学无线电爱好者协会软件小组大前端-万物皆可JS程序员

AdonisJS 入门篇

2017-03-03  本文已影响1896人  唐紫依

参考资料

前言

本篇文章仅对 AdonisJS 框架作简要介绍及简单语法提及,详细语法跟配置请参考官方文档。本篇的目的在于看完之后能够大体了解 AdonisJS 的架构,并实现简单的功能。

零、简单介绍及安装

1.Introduce

2.Install

node 版本 npm 版本
npm i -g adonis-cli           // 全局安装 adois
adonis new awesome-project    // 当前目录下创建新工程
cd awesome-project    
// 然后你需要把 .env-example 文件改名为 .env
npm run serve:dev    // 启动 project

3.Directory structure

文件夹结构图

一、应用生命周期

1.Http Server

// bootstrap/app.js
const provider = []
const aceProviders = []
const aliases = []
const commads = []
// bootstrap/http.js

// 引用 node_modules 提供的 providers
const app = require('./app')
const fold = require('adonis-fold')
const path = require('path')
const packageFile = path.join(__dirname, '../package.json')
require('./extend')
// 注册
module.exports = function (callback) {
    ...
}
// 可以在此配置
{
    "autoload": {
        "App": "./app"
    }
}

2.Http Request

二、MVC 设计模式

本部分仅对 MVC 模式作简要介绍,后续将进一步介绍 View 和 Controller。

1.概述

MVC 设计模式示意图

2.Model

3.Controller

4.View

三、Rounting

本节简单介绍路由,以及常用的几个语法

const Route = use('Route')    // 类似 include,跟 require 不同

Route.get('/', function * (request, response) {
    yield response.sendView('home')    // 这里使用 ES6 generator 语法达到异步请求数据的效果
})
Route.get('users/:id', function * (request, response) {
    const id = request.param('id')
    response.send('Profile for user with id ${id}')
})
Route.group('version1', function () {
    Route.get('users', function * (request, response) {  // 路由是 /api/v1/users
        // ...
    })
}).prefix('api/v1').middleware('auth')    // 该路由群都会加上 api/v1 的前缀,并经过用户登录中间件的检验
Route
    .get('users/:id', '与否.show')
    .as('profile') 

四、Controller

本节主要作控制器的简要介绍,以及 request 和 response 的常用语法使用。最后简单说说中间件。

1.概述

// 引入依赖文件
const path = require('path')

// 定义控制器
class UsersController {

  // 依赖注入
  static get inject () {
    return ['App/Model/User']   
  }

  // 以参数形式接收依赖注入
  constructor (User) { 
    this.User = User 
  }
  
  // 自定义数据处理方法
  static _processUserInfo() {
    // ...
  }
  
  // 异步调用的方法
  * index () {
    const users = yield this.User.all()
    // 传递数据给视图渲染
    yield response.sendView('users',{
        userName,
        userInfo
    })
  }

}

module.exports = UserController

2.request

2.1 简单示例

// 路由闭包中调用 request ,response
const Route = use('Route')

Route.get('post', function * (request, response) {
  const body = request.all()
   
  // cherry picking fields
  const body = request.only('title', 'description', 'categories')
})
// 控制器中调用 request, response
class IndexController {
  * index(requset, response) {
    // ...
  }
}

2.2 常用的 request 方法

const data = request.all()
// example.html?id=1&name=John 
// <input name="gender" value="male" />
// => {"id":1, "name": "John", "gender": "male" }
const data = request.only('name', 'email', 'age')
/* returns
{
  'name': '..',
  'email':'..',
  'age':'..'
}
*/
const name = request.input('name')
const subscribe = request.input('subscribe', 'yes')
// url - http://foo.com/users?orderBy=desc&limit=10
request.url()
// returns - http://foo.com/users
// url - http://foo.com/users?orderBy=desc&limit=10
request.param('orderBy')
// returns - desc

// 返回所有的查询字符串
request.params()
<form method="POST" action="/users">
  <div class="row">
    <h2> User 1 </h2>
    <input type="email" name="email[]" />
    <input type="password" name="password[]" />
  </div>

  <div class="row">
    <h2> User 2 </h2>
    <input type="email" name="email[]" />
    <input type="password" name="password[]" />
  </div>

  <button type="submit"> Create Users </button>
</form>
request.only('email', 'password', )
/* returns 
{
  email: ['bar@foo.com', 'baz@foo.com'],
  password: ['secret', 'secret1']
}
*/
request.collect('email', 'password')
/* returns
[
  {
    email: 'bar@foo.com',
    password: 'secret'
  },
  {
    email: 'baz@foo.com',
    password: 'secret1'
  }
]
*/

3.response

// Render Views
Route
  .get('/', function *() {
    yield response.sendView('welcome')    // resources/views/welcome.njk
})
// JSON Response
Route
  .get('user', function * () {
    const user = yield User.all()    // fetch users
    response.json(users)
})
response.location('/signup')
// or
response.location('back')

4.middleware

'use strict'

const geoip = use('geoip-lite')  // npm module

class CountryDetector {
  
  * handle (request, response, next) {
    const ip = request.ip()
    request.country = geoip.lookup(ip).country
    yield next    // 如果想要把 req, res 传递给下个中间件或者路由行为,注意使用 yield next 
  }
}

五、View

本节简要介绍 View 层以及 View 层常见的使用。

1.概述

// Route
const Route = use('Route')
Route.get('/greet/:user', 'UserController.greet')

// Controller
class UserController {
  * greet (request, response) {
     const user = request.param('user')  // user: "John"
     yield response.sendView('greet', {user})
  }
}
// View
<h2>Hello {{ user }}</h2>    // <h2>John</h2>

2.常见使用

{% if hungry %}
  I am hungry
{% else %}
  I am good
{% endif %}
{{ username | capitalize }}
// username = 'john' => output = John
{% for book in books %}
  book
{% endfor %}
// resources/views/master.njk
<html>
  <body>

    <header class="header">
      {% block header %}
        Common Header
      {% endblock %}
    </header>

    <section class="sidebar">
      {% block sidebar %}
        Common Sidebar
      {% endblock %}
    </section>

    <section class="content">
      {% block content %}{% endblock %}
    </section>

  </body>
</html>
// resources/views/home.njk
{% extends 'master' %}

{% block content %}
  Here comes the content of the home page.
{% endblock %}
<html>
  <body>

    <header class="header">
      Common Header
    </header>

    <section class="sidebar">
      Common Sidebar
    </section>

    <section class="content">
      Here comes the content of the home page.
    </section>

  </body>
</html>
// resources/views/chat/message.njk
<div class="chat__message">
  <h2> {{ message.from }} </h2>
  <p> {{ message.body }} </p>
</div>
// resources/views/chat/index.njk
{% for message in messages %}
  {% include 'message' %}
{% endfor %}
// resource/views/macros/button.njk
{% macro button(value, style='default') %}
  <button type="button" class="btn btn-{{style}}"> {{ value }} </button>
{% endmacro %}
// resources/views/home.njk
{% from 'macros.button' import button %}
{{ button('Create User', 'primary') }}

3.自定义全局变量和过滤器

// 定义全局变量
Http.onStart = function () {
  const View = use('View')
  View.global('time', function () {
    return new Date().getTime()
  })
}
// 定义过滤器
const View = use('Adonis/Src/View')
const accounting = use('accounting') // npm module

View.filter('currency', function (amount, symbol) {
  return accounting.formatMoney(amount, {symbol})
})

// 使用过滤器
{{ 1000 | currency('$') }}

{# returns $1,000.00 #}

六、IoC Container & Service Providers

const Ioc = require('adonis-fold').Ioc
const bugsnag = require('bugsnag')

Ioc.bind('Adonis/Src/Bugsnag', function (app) { 

  const Config = app.use('Adonis/Src/Config') 
  const bugSnagConfig = Config.get('services.bugsnag') 

  bugsnag.register(bugSnagConfig.apiKey, bugSnagConfig.options) 
  return bugsnag 

})
const ServiceProvider = require('adonis-fold').ServiceProvider

class BugSnagProvider extends ServiceProvider {

  * register () { 
    this.app.bind('Adonis/Addons/BugSnag', (app) => {
      const BugSnag = require('./BugSnag')
      const Config = app.use('Adonis/Src/Config')
      return new BugSnag(Config)
    })
  }

  * boot () { 
    // Everything is registered do some hard work
  }

}

注:本篇对 model 部分的简单略过。相关配置,Ace 开发工具等请参考官方文档。

上一篇 下一篇

猜你喜欢

热点阅读