Node学习笔记

113 阅读9分钟

Node.js的特点

  1. 事件驱动
  2. 非阻塞IO模型(异步)
  3. 轻量和高效

Node的使用

模块的导入导出

  1. require
## require函数用来在一个模块中引入另外一个模块
let cc1 = require('./main.js')
let cc2 = require('home/src/main.js')
let cc3 = require('./main')

## 作用
* 执行导入的模块中的代码
* 返回导入模块中的借口对象
  1. exports
## exports对象用来导出当前模块的公共方法或属性,别的模块通过require函数使用当前模块时得到的就是当前模块的exports对象。
exports.add = function() {
    let i = 0
    console.log(++i)
}
## 导出一个add方法供其他模块使用
## 其实exports类似于ES6中的export的用法,用来导出一个指定名字的对象
  1. module.expots
## module.exports 用来导出一个默认对象,没有指定对象名,常见于修改模块的原始导出对象。
module.exports = function() {
    console.log('hello world!');
}
  1. 模块的初始化
## 一个模块中的js代码仅在模块第一次被使用时执行一次,并且在使用的过程中进行初始化,之后缓存起来便于后续继续使用。
  1. 主模块
## 通过命令行参数传递给NodeJs以启动程序的模块被称为主模块。主模块负责调度组成整个程序的其它模块完成工作。例如通过以下命令启动程序时,main.js就是主模块。
$ node main.js //运行main.js启动程序,main.js称为主模块

npm 常见命令

  • npm -v:查看npm版本
  • npm init:初始化后会出现一个package.json配置文件。可以再后面加上-y,快速跳过问答式界面
  • npm install:会根据项目中的package.json文件自动下载项目所需的全部依赖
  • npm install 包名 --save-dev(npm install 包名 -D):安装的包只用于开发环境,不用于生产环境,会出现在package.json文件中的devDependencies属性中
  • npm install 包名 --save(npm install 包名 -S):安装的包需要发布到生产环境的,会出现在package.json文件中的dependencies属性中
  • npm list:查看当前目录下已安装的node包
  • npm list -g:查看全局已经安装过的node包
  • npm --help:查看npm帮助命令
  • npm update 包名:更新指定包
  • npm uninstall 包名:卸载指定包
  • npm config list:查看配置信息
  • npm 指定命令 --help:查看指定命令的帮助
  • npm info 指定包名:查看远程npm上指定包的所有版本信息
  • npm config set registry registry.npm.taobao.org:修改包下载源,此例修改为了淘宝镜像。
  • npm root:查看当前包的安装路径
  • npm root -g:查看全局包的安装路径
  • npm ls 包名:查看本地安装指定包及版本信息,没有显示empty
  • npm ls 包名 -g:查看全局安装的指定包及版本信息,没有显示empty

fs文件系统模块

文件的读写

  1. 文件读取
## 同步读取操作
var buf = Buffer.alloc(20);
var content = fs.readFileSync('hello.txt', {flag: 'r', encoding: 'utf-8'})
console.log(content)

## 异步读取操作
fs.readFile('hello.txt', {flag: 'r', encoding: 'utf-8'}, (err, data) => {
  if(err) {
    console.log(err)
  }else {
    console.log(data)
  }
})

## 异步读取操作方法优化-封装promise
function fsRead(path) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, { flag: 'r', encoding: 'utf-8' }, (err, data) => {
      if (err) {
        reject(err)
      } else {
        resolve(data)
      }
    })
  })
}

var w1 = fsRead('hello.txt')
w1.then(function(res) {
  console.log(res)
})

async function ReadList() {
  var file2 = await fsRead('hello.txt');
  var file3 = await fsRead(file2 + ".txt");
  var file3Content = await fsRead(file3 + ".txt");
  console.log(file3Content)
}

ReadList()
  1. 文件写入
## 写入文件操作(覆盖)
fs.writeFile('test.txt', '晚饭吃啥?', {flag: 'w', encoding: 'utf-8'}, function (err) {
  if(err) {
    console.log('写入内容出错')
  }else {
    console.log('写入内容成功')
  }
})

## 文件追加内容
let fs = require('fs');
fs.writeFile('test.txt', '红烧狮子头\n', {flag: 'a', encoding: 'utf-8'}, function (err) {
  if(err) {
    console.log('写入内容出错')
  }else {
    console.log('写入内容成功')
  }
})

## 异步写入操作方法优化-封装promise
function writefs(path, content) {
  return new Promise((resolve, reject) => {
    fs.writeFile(path, content, { flag: 'a', encoding: 'utf-8' }, function (err) {
      if (err) {
        reject(err)
      } else {
        resolve(err)
      }
    })
  })
} 

async function writeList() {
  await writefs('test.txt', '1今天吃烧烤\n');
  await writefs('test.txt', '2今天吃烧烤\n');
  await writefs('test.txt', '3今天吃烧烤\n');
  await writefs('test.txt', '4今天吃烧烤\n');
}

writeList();
  1. 删除文件
let fs = require('fs');
fs.unlink('test.txt', function() {
  console.log('成功删除!')
})

Buffer的使用

//1、数组不能进行二进制数据的操作
//2、js数组不像java、python等语言效率高
//3、buffer内存空间开辟出固定大小得内存

  1. 将字符串转成buffer对象
var str = 'helloworld'
let buf = Buffer.from(str)
console.log(buf)
  1. 输出buffer内容
console.log(buf.toString())
  1. 开辟一个空的buffer(缓存区)
let buf1 = Buffer.alloc(10)
buf1[0] = 10
console.log(buf1)

//不安全-未清空内存区
let buf2 = Buffer.allocUnsafe(10)
console.log(buf2)

目录的读取

  1. 读取指定路径的文件目录
fs.readdir('../03fs', function(err, files) {
  if(err) {
    console.log(err)
  }else {
    console.log(files)
  }
})
  1. 删除目录
fs.rmdir('abc', function() {
  console.log('删除成功')
})

Stream文件流的使用

  1. 写入流
let fs = require('fs');

//1创建写入流
// --语法:fs.createWriteStream(文件路径,【可选的配置操作】)
let ws = fs.createWriteStream("hello.txt", { flags: 'w', encoding: 'utf-8' });
console.log(ws);

//监听文件打开事件
ws.on('open', function () {
  console.log('文件打开')
})
//监听准备事件
ws.on('ready', function () {
  console.log('文件写入已准备状态')
})
//监听文件关闭事件
ws.on('close', function () {
  console.log('文件写入完成,关闭')
})

//文件流式写入
ws.write("helloworld!", function (err) {
  if (err) {
    console.log(err);
  }else {
    console.log('内容流入完成')
  }
});
//文件写入完成
ws.end(function() {
  console.log('文件写入关闭')
});
  1. 读取流
let fs = require('fs');
const { randomBytes } = require('crypto');

//创建读取流,语法:fs.createReadStream(路径,【可以选的配置项】)
let rs = fs.createReadStream('hello.txt', {flags: 'r', encoding: 'utf-8'})
console.log(rs);

rs.on('oprn', function() {
  console.log('读取的文件打开')
})

rs.on('close', function() {
  console.log('读取流结束')
})
// 每一批数据的流入完成
rs.on('data', function(chunk) {
  console.log('单批数据流入:' + chunk.length)
  console.log(chunk)
})
  1. 管道流
let fs = require('fs');
const { randomBytes } = require('crypto');

//创建读取流,语法:fs.createReadStream(路径,【可以选的配置项】)
let rs = fs.createReadStream('hello.txt', {flags: 'r', encoding: 'utf-8'})
let ws = fs.createWriteStream('a.txt', {flags: 'w', encoding: 'utf-8'})
console.log(rs);

rs.on('open', function() {
  console.log('读取的文件打开')
})

rs.on('close', function() {
  console.log('读取流结束')
})

rs.pipe(ws);

readline模块的使用

输入输出

let readline = require('readline');

//导入readline包
//实例化接口对象

var rl = readline.createInterface({
  output: process.stdout,
  input: process.stdin
})

//设置rl,提问时间
rl.question('今晚吃啥?', function (answer) {
  console.log("答复:", answer);
  rl.close();
})

rl.on('close', function () {
  process.exit(0);
})

node事件-events模块

  1. 使用on定义事件并触发
let events = require('events')
let fs = require('fs')

let e = new events.EventEmitter()

e.on('helloSuccess', function(eventMsg) {
  console.log('1吃夜宵')
})
e.on('helloSuccess', function(eventMsg) {
  console.log('2唱k')
})
e.on('helloSuccess', function(eventMsg) {
  console.log('3打王者')
})
e.on('helloSuccess', function(eventMsg) {
  console.log('4打dota')
})

fs.readFile('hello.txt', {flag: 'r', encoding: 'utf-8'}, function(err, data) {
  if(err) {
    console.log(err)
  }else {
    e.emit('helloSuccess', data);
  }
})

路径模块和系统模块

  1. 路径模块的使用-path模块
let path = require('path')
let fs = require('fs')

// console.log(path)

// let strPath = "http://www.xinhuanet.com//2019-11/23/c_1125266028.htm"
let strPath = "http://www.newsimg.cn/xjp20171103/images/xjp_banner.jpg"

//获取路径信息的扩展名
let info = path.extname(strPath);
// console.log(info);

let arr = ['/sxt', 'qianduan', 'zhongji']
let info1 = path.resolve(...arr)
// console.log(info1)

//获取当前执行目录的完整路径
// console.log(__dirname)
let info2 = path.join(__dirname,'sxt', 'qianduan', 'zhongji');
// console.log(info2)


//
let str = 'http://www.sxt.com/07PATH/xinwen/guonei.html'
//解析出请求目录
let arrParse = str.split('/')
// console.log(arrParse)
let arrTemp = arrParse.slice(-2)
// console.log(arrTemp)

let filePath = path.join(__dirname,...arrTemp)
console.log(filePath)
fs.readFile(filePath, {encoding: 'utf-8'}, function(err, data) {
  if(err) {
    console.log(err)
  } else {
    console.log(data)
  }
})
  1. 系统模块的使用-os模块
let os = require('os')
// console.log(os)

//查看cpu信息
console.log(os.cpus())
//查看整个内存大小
console.log(os.totalmem())
//查看内存架构
console.log(os.arch())

//查看剩余内存量
console.log(os.freemem());

数据爬取-url模块

const { readFile } = require("fs");

let url = require('url')
// console.log(url)

let httpUrl = "https://sale.vmall.com/hwmate.html?cid=10602"
let urlObj = url.parse(httpUrl)
// console.log(urlObj)

let targetUrl = "http://www.taobao.com/"
httpUrl = "./sxt/qianduan/laochen.html"

let newUrl = url.resolve(targetUrl, httpUrl)
console.log(newUrl)

axios模块

let axios = require('axios')

// console.log(axios)
// let httpUrl = "https://www.dytt8.net/index.htm"
// let httpUrl = "https://api.apiopen.top/getJoke?page=1&count=10&type=image"
let httpUrl = "https://www.1905.com/vod/list/n_1_t_1/o3p1.html"

//获取其实页面的所有分类地址
async function getClassUrl(httpUrl) {
  let res = await axios.get(httpUrl)

  let reg = /<span class="search-index-L">栏目(.*?)<div class="grid-12x">/igs
  //解析html内容
  let result = reg.exec(res.data)[1]

  // console.log(res)
  let reg1 = /<a href="(.*?)".*?>(.*?)<\/a>/igs
  let arrClass = []
  var temp;

  while (temp = reg1.exec(result)) {
    let obj = {
      className: temp[2],
      url: temp[1]
    }
    arrClass.push(obj)
    getMovies(temp[1])
  }
  // console.log(arrClass)
}

//通过分类,获取页面中的电影链接
async function getMovies(url) {
  let res = await axios.get(url);
  // console.log(res.data)
  let reg = /<a class="pic-pack-outer" target="_blank" href="(.*?)".*?>/
  var temp;
  let arrList = [];
  while (temp = reg.exec(res.data)) {
    console.log(temp);
    //改进,可以改为迭代器,提升性能
    arrList.push(temp[1])
  }
  console.log(arrList);
}

// axios.get(httpUrl).then(function (res) {
//   console.log(res)
// })

getClassUrl(httpUrl)

服务器部署到公网(花生壳)

node操作数据库

1.下载mysql插件
npm install mysql

2.创建数据库链接对象
let options = {
  host: 'localhost',
  // port: '3306',//可选,默认是3306
  user: 'root',
  password: 'root',
  database: 'mall'
}
//创建与数据库的连接的对象
let con = mysql.createConnection(options);

3.建立连接
con.connect((err) => {
  //如果建立连接失败
  if (err) {
    console.log(err)
  } else {
    console.log("连接成功")
  }
});

4.执行sql语句
let strSql = "select * from user";
con.query(strSql, (err, results, fields) => {
  console.log(err);
  console.log(results)
  console.log(fields)
})

express框架的使用

express项目的创建

  1. 下载express插件
npm install express --save
  1. 创建一个名为myapp的Express应用,并使用ejs模板引擎
express --view=ejs app
  1. express生成器快速生成项目
express moviesapp -e

express路由的使用

1.字符串的路由模式

app.get('/', (req, res) => {
  res.send('这是首页')
})

2类字符串的正则模式

//例如:匹配2个路径abcd或者acd
app.get('/ab?cd', (req, res) => {
  res.send('这是abcd/acd')
})
//例如路径:/ab+cd /abcd /abbcd /abbbbcd
//例如路径:/ab*cd,必须以ab开头,cd结尾,中间可以有任意的东西

3正则的匹配模式

app.get(/\/a\d{10,}/, (req, res) => {
  res.send('新闻页面')
})

4动态路由

app.get('/news/:cataoryid/a:newsid',
  (req, res, next) => {
    req.params.customHost = '127.0.0.1'
    next()
  },
  (req, res, next) => {
    res.send('新闻id页面:\n' + JSON.stringify(req.params))
  })

使用ejs模板

  1. 添加ejs模板配置

  2. ejs文件语法

<!DOCTYPE html>
<html>
	<head>
    	<meta charset="utf-8>
        <title></title>
    </head>
  	<body>
    	<% for(var i=0;i<10;i++){ %>
        	<%= i %>
        <% } %>
        <!-- 获取变量 -->
        <div class="datas">
        	<p>获取变量:</p>
            <%- title %>
            <%= title %>
        </div>
     </body>
 </html>
 # <% xxx %>:里面写入的是js语法
 # <%= xxx %>:里面是服务端发送给ejs模板转义后的变量,输出为原html
 # <%- xxx %>:里面也是服务器端发送给ejs模板后的变量,不过他会把html输出来
 # <%_ xxx _%>:删除内容前和后的空格符
 # <%#:注释标签,不执行、不输出内容
 # -%>:删除紧随其后的换行符

中间件(拦截器)

  1. 执行过程
  • 浏览器发送请求
  • express接受请求
  • 中间处理的过程(中间件)
  • 路由函数处理渲染(req,res)
  • res.render渲染
  1. 示例(可以截获请求,不执行next则中断后续操作)
//添加中间件
app.use(function(req, res, next) {
  console.log('访问任何页面,此函数都会被调用!')
  next()
})
  1. 路由中间件
let router1 = express.Router();
router1.get('/', (req, res) => {
  res.send('商城首页')
})
router1.get('/list', (req, res) => {
  res.send('商城产品列表页')
})
//实例化路由模块,此路由模块相当于一个小的app实例
app.use('/mall', router1)

cookie的使用

sesssion的使用

multer中间件的使用(上传文件的实现)

医院管理系统

前台

  1. 首页
  2. 医院介绍
  3. 新闻中心
  4. 预约挂号

后台

  1. 用户管理,添加删除修改用户资料
  2. 权限管理,用户有哪些的权限,有些页面只有某部分特殊用户可以访问。
  3. 登陆注册
  4. 新闻信息管理
  5. 新闻分类管理
  6. 医生管理
  7. 患者管理
  8. 挂号管理
  9. 药品管理
  10. 财务统计

权限管理

权限管理需要的数据表

  1. 用户表
  2. 角色表
  3. 权限表

举例: 张三用户是一个管理员,那么管理员就有(编辑用户,编辑新闻,编辑挂号,查看统计数据)

设置权限表

  1. 添加/删除/需改权限
  2. 字段:
    • 权限编码,id
    • 编辑用户权限,权限名称
    • /damin/users/userlist,访问路径