Eggjs筆記:路由get傳值、動態路由、靜態資源訪問、ejs模板引擎、數據模型Service、方法擴展

路由get傳值

官網API:https://eggjs.org/zh-cn/basics/router.html

1 )query的方式

路由

router.get('/news', controller.news.index);

news控制器

  async index() {
    const { ctx } = this;
    ctx.render('news');

    // 獲取get傳值 ?age=10
    console.log('query: ' + ctx.query.age);
  }

2 ) params的方式

路由

router.get('/newslist/:id', controller.news.list);

news控制器

  async list() {
    const { ctx } = this;
    ctx.body = 'hi, news list';

    // 獲取get傳值
    console.log('params: ' + ctx.params.id);
  }

動態路由

  • 官網API: https://eggjs.org/zh-cn/basics/controller.html

egg-view-ejs 的使用

  • github: https://github.com/eggjs/egg-view-ejs
  • 配置
    • config/plugin.js
    module.exports = {
        ejs: {
            enable: true,
            package: 'egg-view-ejs',
        },
    };
    
    • config/config.default.js
    // 配置ejs 建議版本
    config.view = {
        mapping: {
            '.html': 'ejs'
        }
    };
    
  • controller中使用
    // 定義渲染數據
    const msg = 'ejs';
    const list = [ '111', '222', '333' ];
    
    await ctx.render('news', {
      msg,
      list,
    }); // 注意這裏和koa一樣,異步渲染
    
  • view中編寫html, 如news.html
    <h3>這是一個新聞 == <%=msg%></h3>
    
    <ul>
        <% for(var i=0; i < list.length; i++) { %>
            <li><%=list[i]%></li>
        <%}%>
    </ul>
    

靜態資源的訪問

<img width="200" src="/public/images/2.jpg" />

數據模型 Model(service)

抽離數據,此處演示,不從數據庫讀取

services.news

'use strict';

const Service = require('egg').Service;

class NewsService extends Service {
  async getList() {
    // 定義渲染數據
    const list = [ '111', '222', '333' ];

    return list;
  }
}

module.exports = NewsService;

在controller中應用

async index() {
    const { ctx } = this;
    // ctx.body = 'hi, news';

    // 定義渲染數據
    const msg = 'hello ejs';
    const list = await this.service.news.getList();

    await ctx.render('news', {
        msg,
        list,
    }); // 注意這裏和koa一樣,異步渲染
}
  • 根據官網中關於Controller,在this屬性上的東西, 具體使用很方便

    此外 egg.Controller,會有下面幾個屬性掛在 this 上

    this.ctx: 當前請求的上下文 Context 對象的實例,通過它我們可以拿到框架封裝好的處理當前請求的各種便捷屬性和方法。
    this.app: 當前應用 Application 對象的實例,通過它我們可以拿到框架提供的全局對象和方法。
    this.service:應用定義的 Service,通過它我們可以訪問到抽象出的業務層,等價於 this.ctx.service 。
    this.config:應用運行時的配置項。
    this.logger:logger 對象,上面有四個方法(debug,info,warn,error),分別代表打印四個不同級別的日誌,使用方法和效果與 context logger 中介紹的一樣,但是通過這個 logger 對象記錄的日誌,在日誌前面會加上打印該日誌的文件路徑,以便快速定位日誌打印位置。

  • 我們的服務service可以在控制器中調用,也可以在service中相互調用,模塊劃分,非常方便

  • 但是服務不能調用控制器,控制器也不能相互調用

  • 服務的命名規則:

    • Service 文件必須放在 app/service 目錄,可以支持多級目錄,訪問的時候可以通過目錄名級聯訪問
      app/service/biz/user.js => ctx.service.biz.user (推薦寫法)
      app/service/sync_user.js => ctx.service.syncUser
      app/service/HackerNews.js => ctx.service.hackerNews
      
    • 一個 Service 文件只能包含一個類, 這個類需要通過 module.exports 的方式返回。
    • Service 需要通過 Class 的方式定義,父類必須是 egg.Service。
    • Service 不是單例,是 請求級別 的對象,框架在每次請求中首次訪問 ctx.service.xx 時延遲實例化,所以 Service 中可以通過 this.ctx 獲取到當前請求的上下文

方法擴展

  • https://eggjs.org/zh-cn/basics/extend.html

  • 框架提供了多種擴展點擴展自身的功能:

    • Application
    • Context
    • Request
    • Response
    • Helper
    • 在開發中,我們既可以使用已有的擴展 API 來方便開發,也可以對以上對象進行自定義擴展,進一步加強框架的功能

以下對Application,Context,Request,Helper進行測試,在目錄app/extend下新建四個文件:application.js、context.js、helper.js、request.js

1 ) Application

application.js編碼

'use strict';
/*
* 外部通過 this.app.foo() 來調用
*/

module.exports = {
  foo() {
    // this 就是 app 對象,在其中可以調用 app 上的其他方法,或訪問屬性
    // console.log(this);
    return this.config.api;
  },
};

2 ) Context

context.js編碼

'use strict';
/*
* 外部通過 this.ctx.foo() 來調用
*/

module.exports = {
  getHost() {
    // this 就是 app 對象,在其中可以調用 app 上的其他方法,或訪問屬性
    // console.log(this);
    return this.request.host;
  },
};

3 ) Request

'use strict';
/*
* 外部通過  來調用
*/

module.exports = {
  // 時間戳轉換時間
  foo() {
    // console.log(this); // 這裏是request對象
    return 'req host: ' + this.header.host;
  },
};

4 ) helper.js

'use strict';
/*
* 外部通過 this.helper.formatTime() 來調用
*/
// 擴展裏面引入第三方模塊
const sd = require('silly-datetime');

module.exports = {
  // 時間戳轉換時間
  formatTime(param) {
    // 這裏是10位的日期,*1000
    return sd.format(param * 1000, 'YYYY MM DD HH:mm');
  },
  // 獲取信息
  getHelperData() {
    return 'I"m helper data!';
  },
};

5 ) 最終調用測試,在app/controller/home.js中

async index() {
    const { ctx } = this;
    await ctx.render('index');

    // 測試調用extend裏面擴展的application
    console.log(this.app.foo());
    // 測試調用extend裏面擴展的context
    console.log(this.ctx.getHost());
    // 測試調用extend裏面擴展的helper方法 egg框架把helper掛載到了context下面
    console.log(this.ctx.helper.getHelperData());
    // 測試調用extend裏面擴展的request方法
    console.log(this.ctx.request.foo());
  }

特別的,在模板文件 view/news.html中,對時間的處理helper.formatTime,但是這種客戶端處理時間戳的方式可能會有很難解決的兼容問題

<ul>
    <% for(var i=0; i < list.length; i++) { %>
        <li>
            <a href="/newscontent?aid=<%=list[i].aid%>"><%=list[i].title%></a> <span>---<%=helper.formatTime(list[i].dateline)%></span>
        </li>
    <%}%>
</ul>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章