如果你能把所有代码写进一个文件,并且能很好的管理、协调、多人开发。那么可以跳过这期(请务必带我飞)。

我们接着完善上期的代码,给代码分家。

node并没有启动入口,更没有固定的项目结构,文件配置。这些全部要靠自己动手,靠约定,正所谓约定由于配置。因为作者书读的少,只会MVC结构,姑且按照MVC结构来分。

建立如下目录。

  • /bin/ : 项目的启动文件,也可以放其他乱七八糟的脚本。如果你有多种环境或者多个入口,这样分就很有必要的
  • /configure/ : 配置文件,上图中根据生产环境和开发环境配置了两个文件夹,分别是development和production
  • /lib/ : js源代码,app.js文件也在这里
  • /logs/ : 日志文件
  • /node_modules/ : 通过npm包管理中间件都在这,包括session,模板,日志等中间件,你自己安装的中间件也在这
  • /public/ : 暴露的文件夹,从名字就可以看出,图面前端js脚本和css会在这里
  • /src/ : 其他语言的文件,如果是coffeescript的项目,编译前的文件会放在这里,编译后的文件在lib里,这里我们暂时用不到
  • /test/ : 单元测试
  • /views/ : 模板文件
  • /app.js : 约定俗成的项目入口
  • /package.json : 配置你项目依赖的包,使用npm命令 npm install -d 会自动安装里面记录的中间件,非常方便。由于nodejs的中间件不完全是脚本组成的,也会包含C写的编译文件,各环境下不尽相同,所以通过npm,本地下载编译是非常重要的

下面我们来填充文件

lib/app.js

 var express = require('express');
var app = express(); module.exports = app;

bin/start.js

 var app = require('../lib/app');

 var port = 3000;
var server = app.listen(port, function () {
console.log('http server listening on port %s', server.address().port);
});

这里bin/start.js充当程序的启动文件。通过node bin/start.js启动项目。现在访问http://127.0.0.1:3000/能看到Cannot GET /的字样就说明成功了。

我们来写第一个路由

controllers/homeController.js

 var action = {
get: function (req, res, next) {
return res.send('ok');
} }; module.exports = action;

routes/homeRoute.js

1 var express = require('express');
2 var controller = require('../controllers/homeController');
3 var router = express.Router();
4
5 router.get('/', controller.get);
6
7 module.exports = router;

routes/index.js

 var homeRoute = require('./homeRoute');
module.exports = function (app) {
app.use(homeRoute);
}

routes/app.js

 var path = require('path');
var express = require('express');
var route = require('./routes');
var bodyParser = require('body-parser');
var app = express(); app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true })); route(app); module.exports = app;

现在第一个路由已经配置好了,访问 http://127.0.0.1:3000/ 就能看到ok的提示。

接下来我们添加一个能交互的页面。

首先我们需要一个模板引擎,使用npm安装

E:\project\heron-lesson\demo3>npm install ejs --save

修改app.js文件

 var path = require('path');
var express = require('express');
var route = require('./routes');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.set('views', path.join(__dirname, '../views'));
app.set('view engine', 'ejs');
app.engine('ejs', require('ejs').renderFile);
route(app); // 路由文件分开 module.exports = app;

由于我们还没讲到数据库,那么先缓存几个数据吧

controllers/listController.js

 var data = [
{name: '张三', age: 20},
{name: '李四', age: 22}
];

继续填充路由

 var action = {
index: {
get: function (req, res, next) {
return res.render('list/index', {data: data});
}
}
}; module.exports = action;

routes/listRoute.js

 var express = require('express');
var controller = require('../controllers/listController');
var router = express.Router(); router.get('/index', controller.index.get); module.exports = router;

routes/index.js,我们这里用了个小技巧给list路由加上了目录/list

 var homeRoute = require('./homeRoute');
var listRoute = require('./listRoute');
module.exports = function (app) {
app.use(homeRoute);
app.use('/list', listRoute);
}

views/list/index.ejs

 <!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>List</title>
</head>
<body>
<ul>
<% data.forEach(function (item) { %>
<li>姓名:<%= item.name %>,年龄:<%= item.age %></li> <% }) %>
</ul> </body>
</html>

现在访问http://127.0.0.1:3000/list/index ,就能看到两行数据了。注意,如果你输出的中文有问题,请更改你的代码文件,保存为utf-8。

姓名:张三,年龄:20
姓名:李四,年龄:22

我们再添加一个搜索功能

修改页面 /views/list/index.ejs

 <!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>List</title>
</head>
<body>
<form action="" method="post">
搜索:<input type="text" name="q"/> <input type="submit"/>
</form>
<ul>
<% data.forEach(function (item) { %>
<li>姓名:<%= item.name %>,年龄:<%= item.age %></li> <% }) %>
</ul> </body>
</html>

同上controllers、routes都得改

controllers/listController.js

 var data = [
{name: '张三', age: },
{name: '李四', age: }
]; var action = {
index: {
get: function (req, res, next) {
return res.render('list/index', {data: data});
},
post: function (req, res, next) {
var list = [];
data.forEach(function (item) {
if (item.name === req.body.q)
list.push(item);
});
return res.render('list/index', {data: list});
}
}
}; module.exports = action;

routes/listRoute.js

 var express = require('express');
var controller = require('../controllers/listController');
var router = express.Router(); router.get('/index', controller.index.get)
.post('/index', controller.index.post); module.exports = router;

刷新页面。

就可以根据name字段来完全搜素了。


彩蛋:

每次都要修改routes里的多个文件来路由,是不是太麻烦了呢。

D:\project\heron-lesson\demo3>npm install heron-mvc

安装heron-mvc。github: https://github.com/iheron/heron-mvc

修改lib/app.js

 var path = require('path');
var express = require('express');
var route = require('./routes');
var bodyParser = require('body-parser');
var app = express();
var mvc = require('heron-mvc'); app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.set('views', path.join(__dirname, '../views'));
app.set('view engine', 'ejs');
app.engine('ejs', require('ejs').renderFile); mvc.route.load({
routeDir: path.join(__dirname, './routes'),
controllerDir: path.join(__dirname, './controllers')
}, function (data) {
app.use("/" + data.route, data.router); // 优先加载路由
}, function (data) {
app[data.method]("/" + data.controller + "/" + data.action, data.func); // 没有路由直接加载控制器 会根据控制器的前缀和action名称 生成两级目录
}); module.exports = app;

现在是见证奇迹的时候了。不用再改routes 来处理路由了,甚至可以删除这个了。

该插件会根据controller的前缀和action的名称来自动生成两级目录。如果你要手动控制路由,也会优先加载路由配置。

该项目下载地址:demo3

下载后需通过npm install -d 来安装依赖

下一期如果内容过多会考虑录成视频。大家如果有什么想看的可以给我留言。

Node填坑教程——整理文件的更多相关文章

  1. Node填坑教程——前言

    Node是什么? Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用程序,编写能够处理数万条同时连接到一个(只有一个)物 ...

  2. Node填坑教程——HelloWorld

    环境安装(极简): Node需要的环境可以说及其简单,也可以说及其复杂.为什么这么说呢? 如果里只需要运行环境那么到Node官网下载一个包就行了.里面自带npm管理工具,这是包管理工具,以后会频繁的使 ...

  3. Node填坑教程——简易http服务器

    我们这一期做一个简易的http服务器. 先建一个文件夹,就算是一个空的项目了.然后新建app.js和package.json文件. 这样一个简易项目的基本文件就建好了. 通过命令行工具,在项目路径下输 ...

  4. Node填坑教程——过滤器

    所谓“过滤器”,只是一个概念,可以理解是一个路由,也可以理解为一个中间件.原理非常简单,就是利用匹配规则,让其有限匹配在正常的路由前面处理就行了. 比如有如下路由 app.get('/', funct ...

  5. Node填坑教程——常用库

    作为函数式编程来说,流程控制和函数库是必不可少的(应该吧). 下面我们介绍两个常用的库. lodash:完整的api请参阅,https://lodash.com/docs.这里我们只演示几个简单的例子 ...

  6. Android项目开发填坑记-so文件引发的攻坚战

    故事的最初 我负责的项目A要求有播放在线视频的功能,当时从别人的聊天记录的一瞥中发现百度有相关的SDK,当时找到的是Baidu-T5Player-SDK-Android-1.4s,项目中Demo的so ...

  7. ReactNative 从环境和第一个demo说起,填坑教程

    一.React-Native MacOS必备环境配置: 1.安装homebrew(这东西可以理解为命令行的app商店) /usr/bin/ruby -e "$(curl -fsSL http ...

  8. backbone新手填坑教程资源

    backbone 入门第二版 http://www.kancloud.cn/kancloud/backbonejs-learning-note/49379 backbone 入门讲解 http://w ...

  9. Vue3+Typescript+Node.js实现微信端公众号H5支付(JSAPI v3)教程--各种填坑

    ----微信支付文档,不得不说,挺乱!(吐槽截止) 功能背景 微信公众号中,点击菜单或者扫码,打开公众号中的H5页面,进行支付. 一.技术栈 前端:Vue:3.0.0,typescript:3.9.3 ...

随机推荐

  1. (大数据工程师学习路径)第四步 SQL基础课程----SQL介绍及mysql的安装

    一.数据库和SQL介绍 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,它的产生距今已有六十多年.随着信息技术和市场的发展,数据库变得无处不在:它在电子商务.银行系统等众多领域都 ...

  2. krpano漫游加方向性3D声音(这篇文章已被移到krpano中国网站 krpano360.com)

    需求:      在场景转换视角时.会出现不同方位的声音以及对应的音量变化,也即是将声音视作hotspot.当视角转到该声音热点时,也随之听到声音.官方样例:点击打开链接 本文已经搬迁到下述网址.请点 ...

  3. 微设计(www.weidesigner.com)介绍系列文章(三)

    微设计(www.weidesigner.com)是一个专门针对微信公众账号提供营销推广服务而打造的第三方平台. 3.1 优惠券 优惠券是用于微信上与顾客互动的一种营销方式,不仅能够展现自己的产品,更能 ...

  4. java线程API学习 线程池ThreadPoolExecutor(转)

    线程池ThreadPoolExecutor继承自ExecutorService.是jdk1.5加入的新特性,将提交执行的任务在内部线程池中的可用线程中执行. 构造函数 ThreadPoolExecut ...

  5. thinkphp学习笔记8—命名空间

    原文:thinkphp学习笔记8-命名空间 新版本(3.2)中采用命名空间的方式定义和加载类库文件,解决多个模块之间的冲突问题,并实现了更加高效的自动加载机制. 需要给类库定义所在的命名空间,命名空间 ...

  6. java一般使用基础

    1.这是一个通用 仿制药javaA型安全机制来保护. 它是通过变量的类型,如果,实现变量类型限制,从而保证了程序编译变量类型的安全性在一定程度上.反之.如果没有泛型,这些只存在于程序,如果猿的大脑,这 ...

  7. Gitserver几家互联网代理安装方法未能解决。

    1.gem安装下面的错误 root@ubuntu:/home/git/gitlab# sudo gem install bundler --no-ri --no-rdoc ERROR:  Could ...

  8. PYTHON单元测试

    PYTHON开发入门与实战11-单元测试 1. 单元测试 本章节我们来讲讲django工程中如何实现单元测试,单元测试如何编写以及在可持续项目中单元测试的重要性. 下面是单元测试的定义: 单元测试是开 ...

  9. SpringMVC传参

    @Controller @RequestMapping("/user") public UserController extends BaseController{ @InitBi ...

  10. CSS定位与层叠

    position:static(静态定位)     当position属性定义为static时,可以将元素定义为静态位置,所谓静态位置就是各个元素在HTML文档流中应有的位置 podisition定位 ...