npm init
初始化 生成package.json(项目配置文件)npm install 包名[@版本号]
安装包 -g
全局安装 --save
或-S
安装到生产环境的依赖(记录在package.json里"dependencies") --save-dev
或 -D
安装到开发环境的依赖(记录在package.json里"devDependencies")npm install
简写 npm i
项目移交时不需要拷贝node-modules文件夹,拿到项目文件,执行它,会下载package.json文件里记录所有的项目依赖npm虽然好用,但有它的下载地址是在国外,也就是说,每次使用 npm 下载的时候,都是去国外的服务器上进行下载,那么就会有很多不稳定的因素(慢,丢包等等),我们就可以nrm进行切换镜像的来源。
安装: npm install nrm -g
检测是否安装成功: nrm --version
查看版本号
查看可用的镜像列表:nrm ls
查看 nrm 镜像源地址网速:nrm test
切换镜像源地址 nrm use 源名称
,比如 nrm use taobao
npm i yarn -g
安装使用
yarn init
初始化
yarn add 包名
安装依赖,默认生产环境,相当于yarn add 包名 -S
yarn add 包名 --dev
安装开发环境依赖
yarn global add 包名
安装全局依赖
yarn remove 包名
移除依赖
yarn add
安装项目所有依赖
// 系统模块和下载到node_modules里的依赖引入不需要路径名
var xxx = require('modulexxx')
// 自定义模块引入必须加路径,即使在同一文件夹下也要加'./'
var a = require('./a')
module.exports = {
obj: {a:1},
num: 1,
str: '123',
fn: function(){console.log('你好')}
}
暴露多个接口
exports.obj = {a:123}
exports.num = 3
exports.fn = function(){console.log('123...')}
// 导入接受到的是一个对象
注意当一个文件里面同时写了module.exports=
和exports.xxx=
,导出的是module.exports=
导出的对象啊
const fs = require('fs');
// 目录
// 读取
// fs.readdir('./dir',(err,data)=>{
// if (err){
// console.log('出错了...')
// return
// }
// // 返回的是一个数组,数组里面是文件夹下的所有文件
// console.log(data)
// })
// try {
// var data = fs.readdirSync('./dir2')
// console.log(data)
// } catch (error) {
// console.log(error)
// }
// 创建
// fs.mkdir('./dir2',(err)=>{
// if(err){
// // 已经存在这文件夹会报错
// console.log(err)
// }
// })
// 重命名
// fs.rename('./dir','./dir1',(err)=>{if(err) console.log(err)})
// 删除 只能删除空文件夹
// fs.rmdir('./dir1',(err)=>{
// if(err) console.log(err)
// })
// 文件
// 读取(注意输出的是二进制的数据流)
// fs.readFile('./dir1/a.txt',{encoding:'utf-8'},(err,data)=>{
// if(err) {console.log(err); return}
// // console.log(data.toString())
// console.log(data)
// })
// 写入或创建
// var s = '我是写入的数据'
// fs.writeFile('./dir1/a.txt',s,(err)=>{if(err){ console.log(err); return}})
// 追加数据
// var s1 = '\n我是新追加的数据'
// fs.appendFile('./dir1/a.txt',s1,(err)=>{
// if(err){
// console.log(err)
// return
// }
// })
// 删除文件
// fs.unlink('./dir1/b.css',(err)=>{
// if(err){
// console.log(err)
// return
// }
// })
// 文件所在目录的绝对路径
console.log(__dirname)
// 当前文件的绝对路径
console.log(__filename)
// node运行的文件目录的绝对路径
console.log(process.cwd())
const path = require('path')
// console.log(path)
// console.log(path.extname('./dir/a.txt'))
// 只是单纯的进行拼接
// console.log(path.join('/a','/b','c'))
// console.log(path.join('a','b','c'))
// console.log(path.join(__dirname,'a','b/c'))
// 会从右向左找根盘向右拼接,没根目录,用__dirname的根目录(e:)
// console.log(path.resolve('/a','b','c'))// e:\a\b\c
// console.log(path.resolve('a','/b','c')) //e:\b\c
const url = require("url");
var s = "http://www.conner.com/a/index?query=xx#first"
// 将字符串url地址转换成对象
console.log(url.parse(s))
var urlObj = {
protocol: 'http:',
slashes: true,
auth: null,
host: 'www.conner.com',
port: null,
hostname: 'www.conner.com',
hash: '#first',
search: '?query=xx',
query: 'query=xx',
pathname: '/a/index',
path: '/a/index?query=xx',
href: 'http://www.conner.com/a/index?query=xx#first'
}
// 将对象格式化成url地址字符串
console.log(url.format(urlObj))
// 导入,注意http和https是两个模块
const https = require('https')
const cheerio = require('cheerio')
var imgArr = []
// 可以搞代理,简易爬虫
https.get('https://www.tupianzj.com/meinv/mm/',(res)=>{
res.setEncoding('utf-8')
var rawData=""
// 绑定两个事件
// 获取数据分片处理数据
res.on('data',(chunk)=>{
rawData += chunk
})
// 处理数据结束后在回调函数使用处理过的数据
res.on('end',()=>{
// cheerio是jquery核心功能的一个快速灵活而又简洁的实现,主要是为了用在服务器端需要对DOM进行操作的地方
// rawData是爬取的网页富文本
var $ = cheerio.load(rawData)
$('img').each((i,el)=>{
imgArr.push($(el).attr('src'))
})
console.log(imgArr)
})
}).on('error',(e)=>{
console.log(e.message)
})
初始化npm package.json
npm init -y
安装
npm i express -S
使用
const express = require('express')
// 创建一个服务
const app = express()
// 监听一个端口
app.listen(9527,()=>{console.log("server is running")})
开启服务(执行js文件)
node 文件名.js
app.get('/a',(req,res)=>{
res.send('你好express')
})
app.post('/b',(req,res)=>{
res.send('你好express/b')
})
访问
浏览器地址栏输入localhost:9527
每次重新配置服务,要关掉开的服务再重启,比较麻烦,使用nodemon就可以了
nodemon用来监视node.js应用程序中的任何更改并自动重启服务,非常适合用在开发环境中。
全局安装nodemon
npm i nodemon -g
再开启服务的时候使用nodemon开启
nodemon 文件名.js
中间件其实就是函数,使用时会可以对请求和响应做一些处理
自制中间件
// 说白了,中间件就是函数
var middleWare1 = (req,res,next) => {
// 请求时(写在next上面的)的拦截处理
console.log('我是中间件1')
// 必须要放行,不然请求会一直得不到响应
next()
// 响应时(写在next下面的)的拦截处理
console.log(111)
}
var middleWare2 = (req,res,next) => {
console.log('我是中间件2')
next()
console.log(222)
}
使用
给创建的服务使用
语法: app.use([path,]middleware1)
app.use(middleWare1).use(middleWare2)
app.use('/a',middleWare1,middleWare2)
app.use('/a',middleWare1,middleWare2)
app.get('/a',(req,res)=>{
res.send('apiaaa')
})
发起请求 =>localhost:9527/a
输出=>我是中间件1 \n 我是中间件2 \n 222 \n 111
// get请求直接req.query就可以拿到
app.get('/a',(req,res)=>{
console.log(req.query)
res.send('hello a')
})
npm i body-parser -S
使用中间件后可获取post的请求参数
导入中间件
const bodyParser = require('body-parser')
使用中间件
// 配置好,可以解析x-www-form-urlencoded的参数
app.use(bodyParser.urlencoded({extended:false}))
// 配置好,可以解析json格式的参数
app.use(bodyParser.json())
app.post('/b',(req,res)=>{
// 如果直接使用是undefined没有的,必须使用中间件处理一下
console.log(req.body)
res.send('hello b')
})
就是express的函数,只要下载,导入了express就可以使用
使用
// 注意:express.Router()是大写的R
var router = express.Router()
// 一定要记得使用一下,它是个中间件
app.use(router)
router其实就相当于一个服务,同样可以设置拦截,使用插件
var bodyParser = require('body-parser')
router.use(bodyParser.urlencoded({extended:false}))
router.use(bodyParser.json())
router.get('/a',(req,res)=>{
console.log(req.query)
res.send('api aaaa')
})
router.post('/b',(req,res)=>{
console.log(req.body)
res.send('api bbbb')
})
一个服务器会用到很多接口,都写在index.js文件里不好维护,可以单独提出放在一个文件夹routers里,不同api放不同文件,模块化管理
项目文件夹/routers/home.js
const express = require('express')
const router = express.Router()
router.get('/home',(req,res)=>{
// console.log(req.query)
res.render('home')
})
module.exports = router
服务文件中使用
const express = require('express')
const homeRouter = require('./routers/home')
const newsRouter = require('./routers/news')
const bodyParser = require('body-parser')
var app = express()
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
// 注意别忘了使用它们***
app.use(homeRouter,newsRouter)
app.listen(9527,()=>{
console.log('server is running...')
})
通常网页静态资源放在项目文件的public文件夹下,静态文件images,html,js,css,lib等
const express = require('express')
const app = express()
app.use(express.static('./public'))
app.listen(9527,()=>{
console.log("serve is running...")
})
配置好后就可以通过浏览访问服务器上的静态资源了(如访问 项目文件夹/public/images/a.jpg)
地址/ => public/
浏览器地址栏输入http://localhost:9527/images/a.jpg
后端一手模板一手数据拼好响应给浏览器
模板引擎 主要功能在于 渲染页面(取代了传统了 拼接字符串)
常见的nodejs 模板引擎有哪些
ejs 温和的 非破坏式 (内部写法跟html是一样的只是赋予了html 一些渲染的功能,如循环,条件判断,引入公共模板…)
pug jade 侵入式 (破坏式) 破坏了html 原有的写法
模板引擎 渲染页面的(html写循环,判断…)
ejs模板引擎的是使用
下载依赖
npm i ejs -S
通常将模板文件放在 项目文件夹/views/下
head.ejs文件
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
home.exjs文件
<%- include('head') -%>
<body>
<h1>我是首页h1>
<p><%= msg %>p>
<% for(i in arr) {%>
<li><%= arr[i] %>li>
<%}%>
<% if (!sign) { %>
<p>这个人很懒,啥都没有留下p>
<% } else { %>
<p><%= sign %>p>
<% } %>
<%- richStr %>
body>
html>
常用语法
<%js语句%>
可以解析js语句,条件,循环;是按照每行一一对应的,每行js语句都要包一下
<%=变量%>
可以解析变量
<%-include('xxx')-%>
用来导入公共的模板文件
<%-富文本字符串%>
可以解析标签(通常为了防止注入攻击,模板都不会去主动解析html标签)
服务文件中配置
不需要引入依赖,只需要配置使用的模板引擎名称,和文件路径就行了
app.set("views","./views") // 告诉服务模板文件放在哪个文件夹下
app.set("view engine","ejs")// 告诉服务是哪种模板语法
文件中使用
const express = require('express')
const router = express.Router()
router.use('/home',(req,res)=>{
// 因为已经告诉服务(设置了)文件目录和模板类型
// 响应渲染方法,返回一个解析好的html页面
res.render('home',{
msg: '我是变量',
arr: ["xx","oo","nn","mm","jj","ff"],
richStr: '我是富文本内容'
,
sign: '除了我,还有谁'
})
})
module.exports = router
用来处理上传的文件,并对文件进行一些操作(如设置扩展名)
下载安装
npm i multer -S
文件上传
pro/views/home.ejs
...
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="img" id="">
<input type="submit" value="提交文件">
form>
body>
<body>
<input type="file" id="file">
<img src="" alt="">
<button>提交button>
<script>
var formData = new FormData()
// 定义个容器
// 二进制文件数据流格式转换
$('#file').change(function(){
// 把它扔给img这个变量,single里面的接受的就是它,跟input:file name差不多
formData.append("img",this.files[0])
var fd = new FileReader();
// base64
fd.readAsDataURL(this.files[0]);
// 图片预览功能实现
fd.onload = function () {
console.log(this.result)
$('img').attr("src",this.result)
}
})
// 报错Illegal invocation
// processData
// 类型:Boolean
// 默认值: true。默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串),
// 都会处理转化成一个查询字符串,以配合默认内容类型 "application/x-www-form-urlencoded"。
// 如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。
$('button').click(function(){
$.ajax({
url:'/upload',
type:'POST',
dataType:'json',
data:formData,
processData:false,//把默认数据格式关了
contentType:false,
success: function(res){
console.log(res)
}
})
})
script>
body>
const multer = require('multer')
// 最后路由文件都会挂到index.js上,所以路径·
// var upload = multer({dest: './public/uploads/'})
// single里的参数是上传文件的表单元素的name属性值
var storage = multer.diskStorage({
destination: function (req, file, cb) {
// 最后路由文件都会挂到index.js上,所以路径·
cb(null, './public/uploads')
},
filename: function (req, file, cb) {
console.log(file)
var extName = file.mimetype.split('/').reverse()[0]
cb(null, file.fieldname + '-' + Date.now()+"."+extName)
}
})
var upload = multer({ storage: storage })
module.exports = upload
const express = require('express')
const router = express.Router()
// ***注意路径
const upload = require('../utils/upload')
// single里面的是表单元素的name值
router.post('/upload', upload.single('img'),(req,res)=>{
res.send('hello')
})
module.exports = router
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const homeRouter = require('./routers/home')
const uploadRouter = require('./routers/upload')
app.use(express.static("./public"))
app.use(homeRouter,uploadRouter,bodyParser.urlencoded({extended:false}),bodyParser.json())
app.set('views','./views')
app.set('view engine','ejs')
app.listen(9527,()=>{
console.log("serve is running...")
})
mongod --dbpath db文件夹绝对路径
mongo
show dbs
查看有哪些数据库
use 数据库名
切换使用的数据库
show collections
查看当前数据库下有那些集合,所有的操作都需要切换到目标数据库才能执行
db.createCollection("person")
创建一个集合
db.集合名.drop()
删除集合
集合等价于mysql里的表单,文档等价于mysql里的记录
文档的数据结构和JSON基本一样。
所有存储在集合中的数据都是BSON格式。
BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON。
增删改查
find
方法会检索集合中所有文档结果
db.集合名.find()
{ "_id" : ObjectId("5eeb59318fbe4d2a7d24ef0e"), "name" : "tom", "age" : 18, "gender" : 0 }
{ "_id" : ObjectId("5eeb59458fbe4d2a7d24ef0f"), "name" : "lucy", "age" : 19, "gender" : 1 }
{ "_id" : ObjectId("5eeb59528fbe4d2a7d24ef10"), "name" : "nacy", "age" : 17, "gender" : 1 }
{ "_id" : ObjectId("5eeb59638fbe4d2a7d24ef11"), "name" : "jack", "age" : 18, "gender" : 0 }
返回的结果不美观,可以格式化一下
db.student.find().pretty()
{
"_id" : ObjectId("5eeb59318fbe4d2a7d24ef0e"),
"name" : "tom",
"age" : 18,
"gender" : 0
}
{
"_id" : ObjectId("5eeb59458fbe4d2a7d24ef0f"),
"name" : "lucy",
"age" : 19,
"gender" : 1
}
{
"_id" : ObjectId("5eeb59528fbe4d2a7d24ef10"),
"name" : "nacy",
"age" : 17,
"gender" : 1
}
{
"_id" : ObjectId("5eeb59638fbe4d2a7d24ef11"),
"name" : "jack",
"age" : 18,
"gender" : 0
}
固值查找
db.student.find({name:"lucy"})
等价于where name = 'lucy'
范值查找
{:}
db.student.find({name:"lucy"}).pretty()
等价于 where name = 'lucy'
{:{$lt:}}
db.student.find({age:{$lt:18}}).pretty()
等价于 where age < 18
{:{$lte:}}
db.student.find({age:{$lte:18}}).pretty()
等价于 where age <= 18
{:{$gt:}}
db.student.find({age:{$gt:18}}).pretty()
等价于 where age > 18
{:{$gte:}}
db.student.find({age:{$gte:18}}).pretty()
等价于 where age >= 18
{:{$ne:}}
db.student.find({"age":{$ne:18}}).pretty()
等价于 where age != 50
AND和OR查找
and 寻找年龄>=18且性别为女的
db.student.find({
$and:[{
age: {
$gte: 18
}
},{
gender: 1
}]
})
db.student.find({KaTeX parse error: Expected '}', got 'EOF' at end of input: and:[{age: {gte: 18}},{gender: 1}]})
or 查询年龄为17或者为男性
db.student.find({
$or:[{
age: 17
},{
gender: 0
}]
})
db.student.find({$or:[{age: 17},{gender: 0}]})
结合查询
相当于语句where name = "lucy" OR ( gender = 1 AND age > 18)
db.student.find({
$or:[{
name: "lucy"
},{
$and:[{
gender: 1
},{
age: {
$gt: 18
}
}]
}]
})
db.student.find({KaTeX parse error: Expected '}', got 'EOF' at end of input: …name: "lucy"},{and:[{gender: 1},{age: {$gt: 18}}]}]})
insert()
或save()
方法。db.集合名.insert(document)
比如我们可以插入以下数据
db.wscats.insert({
_id: 100,
title: 'MongoDB Tutorials',
description: 'node_tutorials',
by: 'Oaoafly',
url: 'https://github.com/Wscats/node-tutorial',
tags: ['wscat','MongoDB', 'database', 'NoSQL','node'],
num: 100,
})
可以插入多个,多个是以数组的形式插入的
db.student.insert([{
name:'alius',
age: 36,
gender: 1
},{
name:'plus',
age: 28,
gender: 0
}])
在插入的文档中,如果不指定_id参数,那么mongodb会为此文档分配一个唯一的ObjectId
要插入文档,也可以使用db.post.save(document)
。如果不在文档中指定_id,那么save()
方法将与insert()
方法一样自动分配ID的值。如果指定_id,则将以save()方法的形式替换包含**_id**的文档的全部数据。
save
指定的_id之前没有存在就是插入,有就是替换,而insert
指定_id存在就插入不了报错
db.student.save({_id: 111,name:'yells',age: 23,gender: 1})
update(条件,{$set:{要修改的字段}})
寻找所有age>19的值,并且更新值name为return和age为18
db.student.update({'age': {$gt: 19}}, {$set: {'name': 'return','age': 18}}, { multi: true})
save
根据_id来查找,覆盖修改数据,id为必传key值
_id
为3的文档,默认是删除多条db.student.remove({
'_id':111
})
建议在执行remove()
函数前先执行find()
命令来判断执行的条件是否正确
如果你只想删除第一条找到的记录可以设置justOne为1,如下所示
db.student.remove({...},1)
全部删除
db.student.remove({})
Limit和Skip方法
limit一次取几条数据
skip跳过多少条读取
sort()排序
1升序,-1降序
中文文档 http://www.mongoosejs.net/docs/