用node.js在线备忘录

作者: YM雨蒙 | 来源:发表于2018-01-23 18:20 被阅读58次
项目预览

在搭建网站之前,我们需要搭建一个网站的架子,我选择了Express基于 Node.js 平台,快速、开放、极简的 web 开发框架。

因为是node的项目,所以我们需要初始化项目,安装依赖

npm init -y  // 生成pacjage.json

安装 Express 并将其保存到依赖列表中:(tips: 可以安装nrm切换到taobao镜像)

npm install nrm
npm install express --save

我们先看一下express基本的应用

touch app.js


var express = require('express');  //引用express
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});

但是一个网站不可能是Hello World 这么简单,肯定需要更多的功能,那我们怎么做呢?

Express 应用生成器

  • 应用生成器工具 express 可以快速创建一个应用的骨架。
$ npm install express-generator  //最好安装到本地目录

Express应用生成器文档使用方法

-V, --version // 版本号
-e, --ejs           add ejs engine support (defaults to jade)
    --hbs           add handlebars engine support  // 模板引擎 ejs hbs等
-c, --css <engine>  add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
    --git           add .gitignore  // 默认less ,css编译器
 -f, --force         force on non-empty directory  // 类似空文件夹

我们创建可以使用命令行

$ .node_modules/express-generator/bin/express . -f -e
// 安装依赖
$ cd myapp 
$ npm install
npm start
// 然后在浏览器中打开 http://localhost:3000/ 

目录结构

.
├── app.js
├── bin  // 可执行文件
│   └── www
├── package.json
├── public  // 静态文件
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes  // 路由设置
│   ├── index.js
│   └── users.js
└── views  // 模板语法
    ├── error.ejs
    ├── index.ejs
    └── layout.ejs

那为什么打开localhost:3000会打开一个网站呢?

  1. 我们看一下我们是不是用了 npm start
  2. npm startpackage.json里写的
"scripts": {
    "start": "node ./bin/www",
  },

看一看bin/www写了什么

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');  // require app.js文件
var debug = require('debug')('express-stickynotes:server');
var http = require('http');  // node 模块 http

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');  // 提供给环境的PORT,没有就是3000端口
// 修改是   $ PORT==4000 node bin/www
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.createServer(app);  // 启动服务器

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);  // 监听端口
server.on('error', onError);  // 提示错误信息
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

app.js内容

// 依赖的模块
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');   //转到 router文件夹下的
var api = require('./routes/api');

var app = express();  // 调用express ,网站的逻辑就是由app处理

// view engine setup 设置模板引擎
app.set('views', path.join(__dirname, 'views'));  // views 模板的文件路径
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public  中间件
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());

//加载为静态目录  public
app.use(express.static(path.join(__dirname, 'public')));

//路由router/index 在里面设置内容
// 用户看到的就是经过模板和数据渲染的页面
app.use('/', index);
// app.use('/users', users);
app.use('/api',api)

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

MVC

M -- Module 模型专门和数据库交互
V -- views 视图模板引擎渲染的
C -- control 控制路由跳转的就是控制器 控制页面跳转
对于Express主要有三个概念路由 中间件 模板引擎
  • 中间件 middleware
    • 中间件就是作为一个中间层去做一个数据处理,相当于来了一个请求,交给一个环节处理,然后交给下一个环节,最终得到一个结果,发给前台,得到我们看到的页面和数据
    • 中间件(Middleware) 是一个函数,它可以访问请求对象(request object (req)), 响应对象(response object (res)), 和 web 应用中处于请求-响应循环流程中的中间件,一般被命名为 next 的变量。
  • 路由 route 路由
    • 路由是指如何定义应用的端点(URIs)以及如何响应客户端的请求。
    • 路由是由一个 URI、HTTP 请求(GET、POST等)和若干个句柄组成,它的结构如下: app.METHOD(path, [callback...], callback)appexpress对象的一个实例, METHOD 是一个 HTTP 请求方法path 是服务器上的路径, callback 是当路由匹配时要执行的函
// 应用级
var app = express();

// 没有挂载路径的中间件,应用的每个请求都会执行该中间件
app.use(function (req, res, next) {  // 请求数据  相应数据  下一个挂载点
  console.log('Time:', Date.now());
  next();
});
// 挂载至 /user/:id 的中间件,任何指向 /user/:id 的请求都会执行它
app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});
// 路由和句柄函数(中间件系统),处理指向 /user/:id 的 GET 请求
app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

// 路由级
var app = express();
var router = express.Router();

// 没有挂载路径的中间件,通过该路由的每个请求都会执行该中间件
router.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

// 一个中间件栈,显示任何指向 /user/:id 的 HTTP 请求的信息
router.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

// 可以对照 app.js看看里面的路由做一下对比,然后看routers/index文件看一下路由

但是静态文件该怎么处理呢?配置webpack

// app.js

//加载为静态目录  public
app.use(express.static(path.join(__dirname, 'public')));
MVC模式目录结构
  • 目录可以按功能划分
  • 目录也可以按应用划分

因为我仅仅用webpack配置前端,所以我把webpack.config.js放在了src文件中学习webpack

使用webpack

1. 本地安装,不建议全局安装
npm install --save-dev webpack
npm install --save-dev webpack@<version>  //特定版本

2. 设置npm script
"scripts": {
    "start": "webpack --config webpack.config.js"
}
  • 入口起点(entry point)指示webpack 应该使用哪个模块,来作为构建其内部依赖图的开始
  • output 属性告诉webpack在哪里输出它所创建的 bundles,以及如何命名这些文件
  • loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。
  • 插件(plugins)插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。
/**
 * Created by yym on 2017/11/24.
 */
var webpack = require('webpack')  // 引用webpack
var path = require('path')  // node 内置path

module.exports = {
    entry: path.join(__dirname, "js/app/index.js"),  // 入口文件,相对于webpack.config.js的位置
    output: {  // 出口文件
        filename: "index.js",  // 文件名字
        path: path.join(__dirname,"../public/js")  // 出口位置
    },
    module: {
        rules:[{  //一些规则
            test : /\.less$/,
            use: ["style-loader", "css-loader", "less-loader"]
        }]
    },
    resolve: {  // 解析
        alias: {  // 创建 import 或 require 的别名,来确保模块引入变得更简单。例如,一些位于 src/ 文件夹下的常用模块
            jquery: path.join(__dirname,"js/lib/jquery.min.js"),
            mod: path.join(__dirname,"js/mod"),
            less: path.join(__dirname,"less")
        }
    },
    plugins: [  //插件
        new webpack.ProvidePlugin({  // 自动加载模块,而不必到处 import 或 require 
            $: "jquery"
        })
    ]
}

为了自动监测webpack变动,我们可以从npm下载onchange

npm install --save onchange

"scripts": {
    "watch": "onchange src/**/*.js src/**/*.less -- npm run webpack"
  },

基本上写代码前的配置工作做到这里,后面如果有需要修改的地方,再慢慢修改


前端的备忘录,当我对这些进行删除,移动等操作时,我希望有提醒,写一个提醒组件

//提醒组件
require("less/toast.less");
function toast(message, time){
    //信息
    this.message = message;
    //延迟时间
    this.dismissTime = time||1000;
    this.createNode();
    this.showToast();
}
toast.prototype = {
    //创建节点
    createNode: function(){
        var html = "<div class = 'toast'>" + this.message + "</div>";
        this.$toast = $(html);
        $('body').append(this.$toast);
    },
    //展示节点
    showToast: function(){
        var _this = this;  // this指向变掉了
        this.$toast.fadeIn(400, function(){
            setTimeout(function(){
                _this.$toast.fadeOut(400, function(){
                    _this.$toast.remove();
                })
            }, _this.dismissTime)
        });
    }
}
function Toast(message, time){
    return new toast(message, time);
}
//暴露接口
window.Toast = Toast
module.exports.Toast = Toast;

还有几个组件的写法可以看代码
github地址src


下面就是备忘录的增删改查的处理,我们可以看一下路由

/*
* 路由设置 和后台约定接口

 1. 获取所有的notes : /api/notes GET  数据req:{}  响应:res:{status:0,data:[{},{}]}  {status:1,errorMsg:'失败的'原因} 
 2. 创建一个note: POST /api/notes/add  数据req{note: 'Hello'}  响应res :{status:0} 
 3. 修改一个note: POST /api/notes/edit  数据req{note: "new note", id:"100}  
 4. 删除一个note: POST /api/notes/delete  数据 req{id:100} 
* 
* */
  1. 我们看一下app.js里面的路由设置
// app.js
// 二级路由
var index = require('./routes/index');
var api = require('./routes/api');

//路由router/index
app.use('/', index);
// app.use('/users', users);
app.use('/api',api)
// index.js
// 如果是get请求,我们可以通过 req.query获得请求信息
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  console.log(req.query)
  res.render('index', { title: 'Express' });
});

module.exports = router;

需要使用数据库来存储我们的数据,我用的是sequelize

sequelize使用文档

// 开始
$ npm install --save sequelize
$ npm install --save sqlite3
// 连接
const path = require('path')
const Sequelize = require('sequelize');
const sequelize = new Sequelize(undefined, undefined, undefined, {
  host: 'localhost',
  dialect: 'sqlite',
  // SQLite only 位置
  storage: path.join(__dirname,'../database/database.sqlite'),
});
// 测试连接
sequelize
  .authenticate()
  .then(() => {
    console.log('Connection has been established successfully.');
  })
  .catch(err => {
    console.error('Unable to connect to the database:', err);
  });
//定义模型
/*
模型就是一个表,表里面是数据结构

对应条目:
1 hello  12345  3435366   id text Time
 */
const Note = sequelize.define('note', {
  text: {
    type: Sequelize.STRING
  },
});


// force: true 如果表已经存在,将会丢弃表
// {raw:true} 得到真实的数据
// where :{id:2} 查询某一个
Note.sync().then(function(){
    //创建数据
    Note.create({text:'Hello World'})
}).then(function(){
    //查找数据
    Note.findAll({raw:true}).then(function(notes) {
      console.log(notes)
    })
});

看看路由怎么写

// api.js

var express = require('express');
var router = express.Router();
var Note = require('../model/note.js').Note
/* GET users listing. */
router.get('/notes', function(req, res, next) {
  
  Note.findAll({raw:true}).then(function(notes){
    console.log(notes)
    res.send({status:0,data:notes})
  })
  
});
//增加创建
router.post('/notes/add',function(req,res,next){
    var note = req.body.note  // post请求的信息
    Note.create({text:note}).then(function(note) {
        res.send({status:0})
    }).catch(function(){
        res.send({status:1,errMessage:'数据库出错'})
    })
})

//修改,更新 update 或者 save
router.post('/notes/edit',function(req,res,next){
    Note.update({text: req.body.note},{where: {id: req.body.id}}).then(function(){
        console.log(arguments)
        res.send({status:0})
    }).catch(function(){
        res.send({status:1,errMessage:'数据库出错'})
    })
})

//删除
router.post('/notes/delete',function (req,res,next) {
    Note.destroy({where:{id:req.body.id}}).then(function(){
        res.send({status:0})
    }).catch(function(){
        res.send({status:1,errMessage:'数据库出错'})
    })
})

module.exports = router;
项目到这里创建 删除 保存 更新等功能已经可以用了,可以自己修改自己喜欢的样式,自己添加功能

使用第三方github做登录/注册

github settings
Developer settings
设置
创建好了 成功

上面部分内容讲了一点,没有具体讲,有问题可以看代码

github项目地址
欢迎star,给个小星星

还需完善,还能做什么???

  • 修改UI
  • 添加聊天功能
  • 添加弹幕功能
  • 清除所有note的功能
  • 给note增加提醒的功能
    • chrome插件的Notification
  • iOS Android等移动端应用

相关文章

  • 用node.js在线备忘录

    在搭建网站之前,我们需要搭建一个网站的架子,我选择了Express基于 Node.js 平台,快速、开放、极简的 ...

  • 自动抓取微信数据程序实现详细步骤-包括阅读数和点赞数

    在线工具:微信文章转PDF2018.1.29 程序原理 准备工作 1. 安装Node.js 去Node.js 官网...

  • 技术支持与服务

    懒猫备忘录 是一个语音备忘录,方便记住琐碎的事情。下载地址 无线听书 (懒猫听书)在线听书,走路都可以在玄幻的世界...

  • Node.js 在线QQ

    聊天室聊天是典型的实时、多用户应用。在当时IRC通过许多专有和开放的协议运行在不标准的端口上,现在在Node.js...

  • 私有GitBook服务部署说明

    20170125 创建说明 使用Gitbook生成在线文档的流程: 本机安装Node.js环境; 安装GitBoo...

  • 12_Node.js Web 开发

    下面开始用 Node.js 进行 Web 开发。 我是通过《Node.js开发指南》这本书来学习 Node.js ...

  • 0.写在最前头

    用ThinkJS之前,如果你不太懂Node.js,建议先从Node.js开始学起。

  • 搭建Web服务器-Node.js

    Node.js介绍 Node.js 是一种新兴的服务器语言,用 Javascript开发服务器。 Node.js ...

  • weex入门之开门篇

    weex简介 playground应用下载weex代码在线编辑工具 环境配置 node.js官网下载Sublime...

  • 用指头画的

    手机备忘录上用指头画画的有木有???

网友评论

    本文标题:用node.js在线备忘录

    本文链接:https://www.haomeiwen.com/subject/hgdlaxtx.html