在平常的项目中,有时候仍是不可避免的会维护一些jq官网项目等。面对此类需求,不少仍是之前的老套路,前端写页面交给后端去套数据。很烦有木有~~而改动以后还得交给后端再次修改,时间和沟通都是个麻烦。同时开发中,写静态页面也很麻烦,不能复用,不能使用如今的工具,心累有木有~~固然了,解决办法不少javascript
而本文介绍一下node的egg.js框架配合模板引擎来快速开发项目的模式。上手简单快速,一我的搞定先后端。PS:又能够学习新知识来,我好(草)开(泥)心(马),奥利给~~~css
# 初始化
cnpm init egg --type=simple
# 安装依赖
cnpm i
# 启动服务
npm run dev
复制代码
简单看下生成的文件目录(ps:个别文件是没有的,后期本身添加的)html
先介绍一下egg中app下的这些文件的基本做用,有个大概的概念:前端
定义路由,首先要打开app/router.js文件,在里面进行定义,例如:vue
'use strict';
module.exports = app => {
const { router, controller } = app;
// 定义首页的路由
// 即当直接访问域名的时候,将请求映射到controller.home.home中进行进一步的处理
router.get('/', controller.home.home);
// 定义关于咱们的路由
router.get('/about', controller.home.about);
// 定义新闻详情的路由
router.get('/details/:id', controller.home.details);
};
复制代码
此处的路由能够理解为就是咱们访问的域名后面的具体的路径地址。例如xxx.com/about中的/about
java
controller.xx.xx是指当咱们访问了这个路由的时候,服务将当前路由映射到这个控制器中。具体的控制器做用,下面会详细介绍。node
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async home() {
const { ctx } = this;
await ctx.render('index.njk')
}
}
module.exports = HomeController
// 或者你也能够简化一下写法
module.exports = class extends require('egg').Controller {
// ...
}
复制代码
下面演示一个调用service的例子:jquery
// app/controller/home.js
'use strict';
module.exports = class extends require('egg').Controller {
async details() {
const { ctx } = this;
try {
// 调用service的home模块中的details服务
// 获得数据后,塞给静态模板使用
const data = await ctx.service.home.details(ctx.params.id)
// 渲染一个模板
await ctx.render('details.njk', data)
} catch (error) {
ctx.body = '新闻获取出错'
}
}
}
复制代码
service服务主要是用来作什么的呢?上面在controller中也提到了,主要用来获取数据,拿到数据以后也能够格式化再返回给controller使用。webpack
下面演示一个service调用某些接口服务获得数据并返回给controller使用:ios
// 首先须要在app/下新建service文件夹
// 而后在service下新建home.js,最终为app/service/home.js
'use strict';
module.exports = class extends require('egg').Service {
// 根据文章id获取文章数据
// 此处的id是controll调用service服务时传递的id
async details(id) {
try {
const url = `https:xxxx.com/api/${id}`
const { data } = await this.ctx.curl(url, { dataType: 'json' })
if (data.data && data.code === 200) {
// 此处也能够对数据进行处理后再返回
// 返回数据
return data.data
}
throw '数据获取失败'
} catch (error) {
throw error
}
}
}
复制代码
home.js
,是由于咱们controller
中使用的是ctx.service.home
service.home
中的home
就是service
文件的文件名称this.ctx.curl
方法请求其余接口的数据。相似于使用axios
获取数据的操做。定义好了基本的路由、控制器和service以后,就剩下模板了。首先模板,多是前端小伙伴写的静态页面给到咱们的(ps:这个前端充气小伙伴或许就是咱们本身!哦呸,不是充气的)
好了,言归正传!Egg中有关于模板渲染的文档,能够看一下。Egg自己内置了egg-view做为模板的解决方案,其中View支持插件egg-view-nunjucks,本文也是经过该插件进行的模板开发。
# 首先安装
cnpm i egg-view-nunjucks --save
# 而后在根目录下的config/plugin.js中使用插件
'use strict';
module.exports = {
nunjucks: {
enable: true,
package: 'egg-view-nunjucks',
}
};
# 完成了插件的安装和引入,咱们还须要配置插件的参数
# 根目录下的config/config.default.js中
module.exports = appInfo => {
// 其余代码
// ...
// 配置咱们的插件参数
config.view = {
// 定义映射的文件后缀名
// 此处咱们定义为.njk,那么咱们的模板都须要以.njk结束,
// 这样该类型的文件才会被咱们的模板插件进行处理
mapping: {
'.njk': 'nunjucks',
}
}
// 其余代码
// ...
}
复制代码
.njk
也是能够的,这个是自定义的,只要知足你的模板文件的后缀名和你定义的同样就行,这样才会被插件处理。egg-view-nunjucks
封装的是nunjucks
,nunjucks
推荐叫.njk
egg-view-nunjucks文档 nunjucks文档
有了模板引擎,咱们嵌套数据等就会方便不少了。下面来简单看下一个模板的文件夹:
下面咱们简单看下base.njk
这个模板,作了什么事情:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{% block title %}title默认内容{% endblock %}</title>
<meta name="keywords" content="{% block keywords %}keywords默认内容{% endblock %}">
<meta name="description" content="{% block description %}description默认内容{% endblock %}">
<link rel="stylesheet" type="text/css" href="../../public/css/base.css">
{% block head %}{% endblock %}
</head>
<body>
<!-- 主体内容部分 -->
{% block content %}{% endblock %}
<script src="../../public/js/jquery.js"></script>
<!-- script部分 -->
{% block script %}{% endblock %}
</body>
</html>
复制代码
block
块,这样就能够在页面中替换掉这块的内容。有些相似于vue的slot
插槽。// 定义block块
{% block title %}默认内容{% endblock %}
复制代码
名称 | 说明 |
---|---|
head块 | 用于在head内最底部插入一些代码。例如,公共模板引入了公共css,可是每一个页面还有可能单独引入css,全局只有一个css文件的除外 |
content块 | 用于放置每一个页面的主体部分 |
script块 | 用于放置每一个页面须要单独引入的js文件 |
定义好了基本的模板和块,下面咱们看下页面中如何使用:
{% extends "./base/base.njk" %}
{% block title %}这是一个新的title{% endblock %}
{% block description %}这是一个新的description{% endblock %}
{% block keywords %}壹沓科技,加入壹沓,联系咱们{% endblock %}
{% set navActive = "about" %}
{% block head %}
<link rel="stylesheet" href="../public/css/swiper.min.css">
{% endblock %}
{% block content %}
<div class="page-wrapper">
<!-- 导入公共的nav模板 -->
{% include './base/nav.njk' %}
<!-- 背景图 -->
<section class="banner-wrapper">
<img src="../public/img/icon/about-banner.jpg" alt="背景LOGO">
<span>{{ userName }}</span>
</section>
<!-- 渲染html模板演示 -->
<div>{{content | safe}}</div>
<!-- 导入公共的底部模板 -->
{% include './base/foot.njk' %}
</div>
{% endblock %}
{% block script %}
<script src="../public/js/swiper.min.js"></script>
<script src="../public/js/about.js"></script>
{% endblock %}
复制代码
// 相对路径便可
{% extends "./base/base.njk" %}
复制代码
// 例如,设置该页面的title
// 若是不设置,就会使用基础模板中默认的
{% block title %}这是一个新的title{% endblock %}
复制代码
// 定义了一个navActive变量
// 后面会讲解一个常见的场景
{% set navActive = "about" %}
复制代码
// 变量的使用,和vue的{{}}插值同样
// 好比这个userName是咱们从controller中调用service获取的数据对象中的一个属性,
// 而后把对象传递给了模板,
// 那么在模板中能够直接取对象中的属性进行渲染
// 注意,传递给模板的是一个对象,例如{userName: 'jack'},可是咱们使用的时候直接取userName
{{userName}}
// 一样的,咱们在模板内定义的变量也能够直接使用的
// 渲染html,好比很常见的富文本
// 相似vue的过滤器,这个safe是内置的,
// 过滤器也能够自定义,具体的查看文档吧
{{content | safe}}
复制代码
// 导入咱们的nav模板
{% include './base/nav.njk' %}
复制代码
<!-- 导航头部 -->
<nav class="nav-wrapper">
<ul class="menu-content">
<li>
<a href="/news" class="{{ 'active' if navActive == 'news' else '' }}">动态资讯</a>
</li>
<li>
<a href="/about" class="{{ 'active' if navActive == 'about' else '' }}">关于咱们</a>
</li>
</ul>
</nav>
复制代码
能够看到,咱们对class名
进行了一个if判断,判断当变量navActive
是某些值的时候给他增长一个active
类名,不然就是各空的class名
。这里仔细注意一下写法便可。 那么咱们怎么定义变量呢?此时再回到上面定义变量的部分介绍,咱们已经在页面中定义了一个变量navActive
,因此咱们只须要每一个页面定义一个navActive
且值为咱们须要的便可了。
router.js
中定义的路由便可,而不是写的模板地址。// a标签跳转
<a href="/news"></a>
// js调整也是同样,使用router.js定义的路由
window.location.href="/news"
复制代码
百尺竿头、日进一步 我是大家的老朋友愣锤~ 喜欢的小伙伴欢迎关注点赞,一块儿分享交流更多的前端好玩技术!