node 学习笔记

71 阅读6分钟

node简介

Node.js是一个Javascript运行环境(runtime) ,发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。

客户端和服务端

服务端渲染:可以被爬虫,客户端异步渲染很难被爬虫

客户端渲染:不利于SEO搜索引擎优化

模块

有三种:

1、具名的核心模块

2、用户自己编写的文件模块,相对路径必须加./,可以省略后缀名

​ 没 有全局作用域,只有模块作用域

​ 外部访问不到内部,内部访问不到外部,

​ 要使用模块中的数据,要在模块中导出

3、第三方模块

​ 第三方模块都必须通过npm来下载

​ 使用的时候就可以require的方式进行加载

​ 不能使任何一个第三方包和核心模块的名字一样

require的作用

1、加载文件模块并执行内部方法,

2、拿到被加载的文件模块的导出接口对象

request请求(node 中的请求)

const request=require("request")

核心模块

文件操作:fs

服务器请求:http

路径操作:path

操作系统:os

读取文件

必须引入 fs 核心模块

异步操作

var fs = require("fs")
// 读文件
// 参1:要读取的文件路径
// 参2:回调函数
//  error
//      失败,返回错误对象
//      成功,返回null
//   data
//      失败,返回错误对象
//      成功,返回读取到的数据

//路径是相对与主目录的,可以省略./
//第二个参数用来转化,可是是我们识别。读出的数据是字符串,可以用JSON
fs.readFile("./nodeStud.md","utf8", (err, data) => {

    if (err) {
        console.log(err);
        console.log("读取文件失败");
        return
    }
    // 浏览器返回16进制数据,toString()进行转化
    console.log(data.toString());
})

// 写文件
// 参1:文件路径
// 参2:文件内容
// 参3:回调函数
//    成功:返回null
//    失败:返回错误对象
fs.writeFile("./testFile.md", "5555", (err) => {
    if (err) {
        console.log(err);
        console.log("写入文件失败");
    }
})

路径操作url模块

必须引入url核心模块

获取路径中的地址和参数

const url=require("url")
const path=url.parse(req.url, true)  //返回一个对象,第一个是路径,第二个参数最好是true,
 // path.name  不含参数的路径
  // path.query  参数, 第二个参数为true,为对象,反之为字符串
  
  url.resolve(参1,参2) /参1 ,基础url ,参2 ,目标url

路径处理Path模块

必须引入path核心模块

path.extname(路径) //路径信息扩展名
path.join("",...)//可以多个路径拼接在一起,生成规范的路径
path.resolve("",...)//会自动拼接系统地址,多个路径拼接在一起,生成规范的路径
__dirname //获取当前执行的目录
__filename //获取当前的文件
path.parse() //解析路径 根路径 ,目录 文件名 ,文件类型

os操作系统信息

必须引入os核心模块

os.cpus()  //操作系统信息
os.totalmem()//内存信息
os.arch() //内存架构 ,x64 

创建服务器

必须引入http核心模块

const http = require("http")
const fs = require("fs")
// 创建一个服务器,可以开多个服务器,但是端口号不能一样
const server = http.createServer()
/*
服务器响应
   request请求事件的回调,有两个参数
   Request 请求对象
      用来回去用户的一些请求信息,例如请求路径
   Response 响应对象
      给客户端发送响应信息
      有一个write()用来给客户发消息,但是必须要有一个end()
      一般用end结束响应,并发送数据

      */
server.on("request", (req, res) => {
    /*
      req.url  请求路径,以/开头 , 通过不同的路径,响应不同的数据
      一般req.url=="/" ,请求的首页
      响应数据只能是字符串,二进制
      res.setHeader("Content-Type", "text/plain;charset=utf-8")
      服务器默认编码uft-8,
      text/plain;charset=utf-8 普通文本
      text/html;charset=utf-8 html 格式的字符串
      访问图片,不需要编码
       image/png, image/jpeg

       */

    fs.readFile("./resourse/xx1.png", (err, data) => {
        if (!err) {
            res.setHeader("Content-Type", "image/png")
            res.end(data)
        } else {
            res.end("错误")
        }
    })


})
// 绑定监听端口
server.listen(3000, () => {
    console.log("服务器启动成功,通过ip:端口号,可以访问");
})

模板引擎

art-template

不关心内容,之关系语法

在web中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    xixi
</div>

</body>
<script src="../node_modules/art-template/lib/template-web.js"></script>
<script type="text/template" id="tmep">
    <p>{{name}}</p>
    <p>{{each hoby}} {{$value}}{{/each}}</p>


</script>
<script>

    var rer = template('tmep', {
        name: "afdfa",
        hoby: [
            "daf", "adfa"
        ]
    })
    console.log(rer);
</script>
</html>


在node中

.js

const  template=require("art-template")

const http = require('http')
const server = http.createServer()
const fs = require('fs')
const baseUrl = "./resourse"

server.on("request", (req, res) => {

    var url = "/hello.html"
    if (req.url != '/') {
        url = req.url
    }
    fs.readFile(baseUrl + url, (err, data) => {
        if (!err) {
            // render接受字符串
            var temp=template.render(data.toString(),{
                name: "afdfa",
                hoby: [
                    "daf", "adfa"
                ]
            })

            // res.setHeader("Content-Type", " text/html;charset=utf-8")
            res.end(temp)
        }



    })

})
server.listen(3001, (err) => {
    console.log('服务器启动');
})

.hello.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <p>gafga</p>
    <p>{{name}}</p>
    <p>{{each hoby}} {{$value}}{{/each}}</p>
</div>

</body>

</html>

退出

process.exit(1)

数字1,为退出码,也可以是其他的

在控制台,也可以使用ctrl+c

process.exitCode=1

导入导出

requiremodule.exportsexport

module.exports:公开了指向的对象

**exports:**公开指向的对象的属性,是module.exports的引用

如果一个模块需要导出某一个成员,而非挂载用,module.exports

module.exports进行多个导出时会覆盖

exports.a={}
exports.b=""


module.exports=fun (){}
module.exports=""
//会覆盖

导出多个

module.exports={

}

process

不需要require,自动可以获取

process.env.NODE_ENV //"development"、"production"

输出到命令行

console.log()//打印到命令行console.clear()//清空控制台console.count()//元素计数,会对打印的字符串进行计数console.trace()//打印调用的堆栈踪迹console.time("fun()")//计算函数运行的耗时console.timeEnd("fun()")//计算函数运行的耗时

重定向

通过服务器让客户端重定向

1、状态码设置为

​ 302,临时重定向 ,

​ 301 永久重定向,浏览器会记忆

​ 状态码 res.statusCode=302

2、在响应头通过location告诉客户端往哪里重定向

res. setHeader("Location","/")

优先从缓存中加载

若一个模块已经被重新加载过,当遇到在加载时,不会重新加载,而是重缓存中加载

Apache

const http = require('http')
const server = http.createServer()
const fs = require('fs')

// Apache服务器软件,有一个www默认目录
const baseUrl = "./resourse"
/*
* 1、得到目录列表中的文件名和目录名
*    fs.readdir()
* 2、如何将得到的文件名和目录名替换到html中
*   模板引擎
* */


server.on("request", (req, res) => {
    var url = "/hello.html"
    if (req.url != '/') {
        url = req.url
    }

    fs.readFile(baseUrl + url, (err, data) => {
        if (!err) {
            fs.readdir("./resourse", (err1, file) => {
                var cotent = ''
                file.forEach(item => {
                    cotent += `<h1>${item}</h1>`
                })
                data = data.toString()
                data = data.replace('xixi', cotent)
                res.end(data)
            })

        }



    })

})
server.listen(3001, (err) => {
    console.log('服务器启动');
})

日志打印

const logger = require("morgan") // 日志
// npm i morgan -s
app.use(logger("dev"))

Express

node中的web框架

模板引擎

art-template

npm install --save art-template
npm install --save express-art-template


/*
* 
* express为req相应的对象提供了一个方法:render。
* 但是默认不能使用,需要配置模板引擎,
* res.render('html模板名',{模板数据}),第一参不能写路径,默认去views录查找,
* 修改默认路径,app.set("view",要修改的render函数的默认路径)
* 
* */
//个参数配置的文件后缀名,在view中模板文件必须已.html结尾
app.engine('html', require('express-art-template'));
// 2. 设置项目中默认的模板引擎
app.set('view engine', 'html')
// 3.设置默认模板引擎的存放路径


res.render("index.html")

ejs

默认后缀名 index.ejs (在views文件夹下建立index.ejs ,和index.html结构相似)

app.set("views",__dirname+"/views1")  /修改保存路径

修改模板引擎的后缀 ejs ->html

app.js

var ejs=require('ejs')

app.engine("html",ejs,__express)

app.set("view engin","html")
npm i ejs --save    

app.set("view engine" ,"ejs")

//默认加载模板引擎的文件夹views
//输出对象
res.render("index",{})
//输出html



index.ejs

//数据渲染
<div><%=title%></div>

//html 
<div><%-title%></div>

//条件判断
<%if(){%> <span></span>	<%}%>

<%if(){%>
<span></span>
<%}else{%>
<span></span>
<%}%>

//for循环
<%for(){%>
<span></span>
<%}%>

//引入公共ejs
<%- include("footer.ejs") %>

get请求

const  express=require('express')
// 创建服务器  类似http.createServer()
 const app=express()

const fs=require('fs')
// 公开指定目录,可以通过/pub /xxx访问pub下的资源
app.use('/pub/',express.static("./pub/"))

//配置静态目录,使外部可以访问static文件夹下 (同上)
app.use(express.static("static"))

// 当服务器收到get请求时,执行的回调,可以使用req.query来获取查询字符串
app.get("/",(req,res)=>{
  // 重定向
    res.redirect("/")
    res.send("hello 、。")
})
app.get("/具体路径",(req,res)=>{
    res.send("hello")
})



// 监听事件
app.listen(3000,()=>{
    console.log("服务器启动");
})

post请求

const  express=require('express')
// 创建服务器  类似http.createServer()
 const app=express()
// post请求解析的中间件
const  bodyParse=require('body-parser')
const fs=require('fs')
// 公开指定目录,可以通过/pub /xxx访问pub下的资源
app.use('/pub/',express.static("./pub/"))


/*
* 当服务器收到post请求时,执行的回调,可以用中间件
* npm i body-parser --save
一定要在路由之后
*
* */
// 配置中间件
// parse  application/x-www-form-urlencoded
//true 或者false 将会影响post请求的body 数据格式

app.use(bodyParse.urlencoded({extended:false}))
// parse  application/json
app.use(bodyParse.json())

app.post("",()=>{
    // req.body获取post请求数据
})
// 监听事件
app.listen(3000,()=>{
    console.log("服务器启动");
})

路由

app.js

const route=require("./router/routerExpress")
app.use(route)

router.js


// express提供的路由
const express=require("express")

const router=express.Router()

module.exports=router

动态路由

app.get("/new/:id",(req,res)=>{
    // 获取new后的路径
    // req.params["id"]
    console.log(req.params["id"]);
})

中间件

应用级中间件(用于权限判断)


app.use((req,res,next)=>{
    // res.send
    next() //是否继续执行
})


路由中间件(用的少)

app.get("/new/:id",(req,res,next)=>{
    // 获取new后的路径
    // req.params["id"]
    console.log(req.params["id"]);
    next()
})

错误处理中间件(放在最后)

app.use((req,res,next)=>{
 
  res.status(404).send("404")
  
    next() //是否继续执行
})

内置中间件


app.use(express.static("static"))

cookie

npm i cookie-parser --save

const cookieParser=require("cookie-parser")

app.use(cookieParser())

//使用  maxAge 过期时间 (毫秒) 

res.cookie("name":'zzz',{maxAge:5000,httpOnly:true})

//获取

req.cookies.name

参数

maxAge :5000//过期时间

httpOnly:true ,//true 只能后台使用, false ,前台可用

secure:true,//true加密

signed:true,//签名,加密
//要配置的时候加入参数

expires:Data,//具体时间

path:String,//cookie访问目录,正常不用(只能某一个页面也用)
//path:"/login"

//多个二级域名访问cookie  aaa.xxx.com  bbb.xxx.com
domain:String,//  domain:".xxx.com"

加密

//要在配置中间件的时候加入加密的参数
app.use(cookieParser("xxxx"))

//设置
res.cookie("name":'zzz',{maxAge:5000,signed:true})

//获取
req.signedCookies.name

session

npm i express-session --save

const session =require("express-session")

mongodb

注:

无法安装服务

 sc delete MongoDB 
 
 mongod --dbpath=E:\MongoDB\data\db  --logpath=E:\MongoDB\log\MongoDB.log --install --serviceName "MongoDB"
 
  net start MongoDB
  
  展示启动成功
 

安装时候不要安装conpass(可视化工具) ,要增加path (打开bin,)路径要携带bin

常用命令

cls 清屏

mongo       连接数据库
db             查看当前数据库
show dbs       所以数据库
use 数据库名   切换数据库(创建数据库)
show collections 当前数据库下的表
db.user.insert({})(user为数据表(集合))
db.user.insert({"id":2,"price":400,"num":200})

db.user.find() //查看表中内容  (user为数据表(集合))
db.dropDatabase()//删除数据库
db.user.drop() //删除集合 (user为集合)

空数据库不展示

查找

db.user.find({"name":"hha}) //找name为hh的数据
db.user.find({"age":{$gt:22}})  //查找age大于22的记录
db.user.find({"age":{$lt:22}})  //查找age小于22的记录
db.user.find({"age":{$lte:22}})  //查找age<=22的记录
db.user.find({"age":{$gte:22}})  //查找age>=22的记录
db.user.find({"name": /mon/})  //查找name中包含mon的
db.user.find({"name": /^mon/})  //查找name中以mon的开头
db.user.find({"name": /mon$/})  //查找name中以mon的结尾
db.user.find({},{'name':1}) //只显示name 
db.user.find({},{'name':1,age:1}) //只显示name 和age
db.user.find().sort({'age':1})  //根据age升序
db.user.find().sort({'age':-1}) //根据age 降序
db.user.find().limit(5) //查找前5条
db.user.find().skip(10) //查询10之后的
db.user.find().count() //总共多少条
db.user.find().skip((pageSize-1)*pageNum).limit(pageSize) //分页 pagesize pageNum
db.user.find({$or:[{"age":"22},{"age":23}]}) //找age等于22或者23的

修改

注:

不加$set为完整替换

//改修 name=hah 的性别为男 1:/查询条件   参2:要修改的数据    参3:是否多条同时修改
db.user.updata({"name":"hah"},{$set:{"sex:"","name":xixi},{"multi:true})

删除

//参1 :要删除的条件  参2:是这删除一条
db.user.remove({"age":12},{justOne:true})
//删除age 12 或者13
db.user.remove({$or:[{"age":12},{"age":13}]})

设置索引

db.user.getIndexes() //获取当前的索引
//设置索引,user:表 name:字段  1.升序,-1降序
db.user.ensureIndex({"name":1})
db.user.dropIndex({"name":1}) //删除

//复合索引,查询条件中必须包含到复合索引  参2:索引名字
db.user.ensureIndex({"name":1},{"age":"22"}) 


唯一索引
db.user.ensureIndex({"userID":1},{"unique":true})

创建管理员

1.创建

use admin 

db.createUser({
   user:'admin',
   pwd:'123456',
   roles:[{'role':'root','db':'admin'}]
})

2.修改配置

D:\myWork\tools\tools\mongooses\bin\mongod.cfg

前面有#说明没有其作用 ,不能用记事本 ,webstrom打开 ,可以hbuild ,notpdd
security:
 authorization: enabled

3.重启数据库

windows +r
services.msc

4.用超级管理员连接数据库

// 方式一
mongo
use admin
db.auth('admin', '123456')

// 方式二
mongo admin -u admin -p 123456

5.添加单个数据库用户

use test  // 跳转到需要添加用户的数据库
db.createUser({
  user: 'fooadmin',  // 用户名
  pwd: '123456',  // 密码
  roles:[{
    role: 'readWrite',  // 角色
    db: 'test'  // 数据库名
  }]
})

常见命令

show users  // 查看当前库下的用户

db.dropUser('testadmin')  // 删除用户

db.updateUser('admin', {pwd: '654321'})  // 修改用户密码

db.auth('admin', '654321')  // 密码认证

MongoDB 数据库默认角色

数据库用户角色:read、readWrite
数据库管理角色:dbAdmin、dbOwner、userAdmin
集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager
备份恢复角色:backup、restore
所有数据库角色: readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、
dbAdminAnyDatabase
超级用户角色:root

作者:地平线0530
链接:https://www.jianshu.com/p/237a0c5ad9fa
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

聚合管道

聚合管道可以对集合中的文档进行变化和组合

实际项目中:表的关联查询,数据统计

//常见的操作

  $project    增加,删除,重命名字段

  $match     条件匹配。满足条件的文档进入下一阶段

  $limit        限制结果的数量

  $skip         跳过文档的数量

  $sort        条件排序

  $group     条件组合结果

  $lookup    可以引入其他集合的数据(关联查询)
  db.user.aggregate([
    {
        $lookup: {
           from: "user_item",//和谁关联
            localField:"id", //要关联的字段
            foreignField:"id",//要关联的字段
            as:"user",//放到哪里
        }
    }
])
db.user.aggregate([
    {
        $project: {name: 1, id: 1}
    },
    {
        $match: {}
    }

])

mongoose基本使用

const mongoose=require("mongoose")
// 链接数据库,数据库可以不存在,在创建第一条数据时自动创建
mongoose.connect("mongodb://localhost/test",{useMongoClient:true})

mongoose.Promise=global.Promise

// 创建一个模型,第一个参数大写,为数据库的名称,会自动生成小写复数的形式,第二参数,架构的数据格式,返回模型构造函数
var Cat=mongoose.model("Cat",{name:String})


var  kitty=new Cat({

  name:{
    type:String,
    required:true,//是否必填
    default0,默认是0
    enum:[0,1],//只能是0或者1
  }
})

kitty.save(()=>{

})

kitty.save(()=>{

})

Cat.remove({},(err,ret)=>{

}),//参1:条件
还有其他的

Cat.findByIdAndUpdate("",{},(err,ret)=>{

}),//参1 :根据要找的参数,参2:要改的东西,回调
还有其他的

Cat.find({},(err,data)=>{

})//第一个是查询条件,可以不写

Cat.findOne({},(err,data)=>{

})//第一个参数是查询条件,可以不写

MongoBooster

数据库格式化软件

Schema

使用Schema创建约束,为了使表中无脏数据

node操作数据库

// 引入数据库
const {MongoClient} = require('mongodb')
// 数据库地址
const url = "mongodb://localhost:27017";
// 要连接的数据库(集合)
const dbName = "user"

// 实例化
const client = new MongoClient(url, { useUnifiedTopology: true })

client.connect((err) => {
    if (err) {
        console.log(err);
        return
    }
    console.log("数据库链接成功");
    let db=client.db(dbName)

  // 查找数据 user 表

    db.collection("user").find().toArray((err, data) => {

        if (err) {
            console.log("查找失败");
        } else {
            console.log(data);

            // 操作完一定要关闭
            client.close();
        }
    })

    // 增加数据
    db.collection("user").insertOne({"name": "di", "id": 5, "age": 25, "code": 89}, (err, result) => {
        if (err) {
            console.log("增加失败");
            console.log(err);
        } else {
            console.log("增加成功");
            console.log(resove);
            // 操作完一定要关闭
            client.close();
        }
    })


    // 更新数据
    db.collection("user").updateOne({"name": "di"}, {$set: {"age": 85}}, (err, result) => {
        if (err) {
            console.log("更新失败");
            console.log(err);
        } else {
            console.log("更新成功");
            console.log(resove);
            // 操作完一定要关闭
            client.close();
        }
    })
     // 删除 一条
    db.collection("user").deleteOne({"name": "di"}, (err) => {
        if (err) {
            console.log("删除失败");
            console.log(err);
        } else {
            console.log("删除成功");

            // 操作完一定要关闭
            client.close();
        }
    })
    // 删除 多条
    db.collection("user").deleteMany({"name": "di"}, (err) => {
        if (err) {
            console.log("删除失败");
            console.log(err);
        } else {
            console.log("删除成功");

            // 操作完一定要关闭
            client.close();
        }
    })
})

实例化

MongoClient.connect(url,{ useUnifiedTopology: true }, (err, client) => {
    if (err) {
        console.log(err);
        return
    }
   let db = client.db(dbName)
})