node.js

143 阅读10分钟

客户端(PC+移动端+小程序) + 服务器端(Node.js) + 数据库(mongoDB)

概述:

做的功能绝对不是特效!做的事和服务器端其他语言是一致(和数据库进行交互,成为了一个前端到数据库的中间桥梁)

目的

  1. 使用代码搭建一个服务器&文件系统(服务器文件可以放在任何位置,但是不在你的电脑里,你可以根据网址来访问到我的东西)
  2. Node.js如何沟通前端和数据库
  3. 全栈:图书管理系统(HTML+CSS+JS+Node+Mongo)

如何运行

1、交互模式 - 临时测试
	打开cmd输入:node回车,就可以开始敲你的"js"代码

2、脚本/文件模式 - 正式开发中
	1、先创建xx.js,里面书写自己的代码
	2、打开cmd输入:node 文件的绝对路径

3、编辑器越来越强大了:安装插件,前提:至少两个方式能够成功,才可以安装插件
	vscode - code runner:对着文件出右键,第一个选项就是code runner,或者 右上角有一个开始按钮
            

模块(module)

  1. 模块化开发:如果以一个网站来说,我们可以按功能分为很多模块:商家模块、商品模块、促销模块、用户模块、产品模块...
  2. 分工合作:将每个模块交给对应的人,完成,最后再由【主模块】进行引入
  3. 每一个模块都有一个操作,可以用于公开/暴露自己的成员
exportsNode.js自带的一个预定义变量,可以直接使用,是一个对象,放在此对象里面的东西,就是允许公开的东西
				语法:
					1exports.属性名=属性值;
					2module.exports={
						属性名:属性值,
						...
					      }

					错误导出法:
						exports={
							name:"袍哥",
							age:18,
							hobby:"学习"
						}

2、每一个模块(主模块)都有一个操作,可以用于导入/引入其他模块
				requireNode.js自带的一个预定义变量,可以直接使用,是一个函数,函数中需要书写出引入模块的路径
				语法:var x=require("./文件名")

1.Global模块

不需要引入,可以直接使用

提供了:
1、五个预定义变量,可以直接使用
  1、__filename - 获取当前文件完整的绝对路径
  2、*__dirname - 获取当前文件绝对路径,不包含文件的名字,何时:vscode某的同学可能不支持node.js上书写相对路径,只能写绝对路径 - 等我们学习了文件系统
  3、*exports - 空对象,可以用于公开暴露自己的成员
  4、*require - 函数,可以用于导入其他模块
  5、***module - 指代当前模块本身,甚至包含着以上4个操作
  
2、定时器(周期性、一次性、瞬间定时器):定时器不是当初的js,只不过用法和当初一摸一样
3console也不是当初的console,只不过用法和当初一摸一样

querystring模块:
  • 解析查询字符串,使其变成一个对象,可以获取到前端传到后端的消息
需要引入:var qs = require('querystring');
  作用:解析url查询字符串部分的功能
  var obj=qs.parse("查询字符串");
  想要获得前端传来的每一个部分:obj.键名;
  垃圾:如果前端传来的是一个完整的url网址,他就解析不了了!

URL模块--小重点
需要引入:var url = require('url');
作用:提供了解析url各个部分的功能
	var objUrl=url.parse("网址",true);支持第二参数,是一个布尔值,默认为false,一旦设置为true,自动使用querystring模块的parse方法去解析查询字符串部分
	真正的重点:
	    1、查询字符串:objUrl.query.键名; - 前端form表单提交传到后端的东西
	    2、路由/文件相对路径/请求地址:objUrl.pathname - 判断路由的不同,去读取不同的HTML发送给我们的用户看


4、Buffer模块:
缓冲区,可以将数据变成一个16进制的数字,你可以理解为是Node.js中的一种新的数据类型,但是我们绝对不会手动使用,因为我们一眼看不懂
但是后面的一些API可能会导致我们被动都到Buffer,但是你也别怕,因为Node.js中大部分的API,是支持Buffer
5.fs模块----大重点
需要引入:var fs = require('fs');
   *异步读取文件:fs.readFile("文件路径",(err,buf)=>{
	  buf->读取到的内容
			})

    异步写入文件:fs.writeFile("文件路径","新内容"/buf,()=>{
	  console.log("写入完毕后,要做什么,必须放在这里面");
		})//会替换掉原来的东西
						
    异步追加文件:fs.appendFile("文件路径","新内容"/buf,()=>{
	 console.log("写入完毕后,要做什么,必须放在这里面");
		})//会替换掉原来的东西

强调:只有异步才能更完美的发挥Node.js的特点(快)
6.http模块---超级重点:搭建服务器
  • 引入了http(搭建服务器)、url(区分开路由和请求消息)、fs(读取文件响应给用户看)
var http=require("http");
var url=require("url");
var fs=require("fs");
  • 创建服务器应用
var app=http.createServer();
  • 为其绑定监听端口
app.listen(80);
  • 为其绑定请求事件:
http:请求 - 响应模式,必须要有一个请求,才有一个响应
app.on("request",(req,res)=>{
	req:request(请求)对象,他有一个属性叫做req.url,看了一获取到前端传到后端的路由和请求消息,但是路由和请求消息是融为一体的,不方便我们获取某个部分,所以我们引入了url,进行解析,分开两部分
	var objUrl=url.parse(req.url,true);
	保存路由
	var router=objUrl.pathname;
	if(router=="/" || router=="/index.html"){//判断路由的不同,读取不同的页面给用户看
		//res:response(响应)对象,他有一个方法:res.end(响应的内容) - 可以响应给前端想要的东西
		fs.readFile("./public/html/index.html",(err,buf)=>{
			res.end(buf);//res.end只能用一次
		})
	}
})

math---字符串的API
var rs=str.match(reg);和indexOf几乎一致,但是支持正则,我们不关心为多少,只关心为不为null

  • 强调:一切的src和href都是一个请求都是一个路由,这个请求就需要后端来解析,根据不同的请求响应不同的内容

模块(每个.js文件)的分类

  1. 官方模块:不需要下载,再安装Node.js环境的时候就已经自带了,但是有的模块需要引入:require("模块名");
  2. 第三方模块
  3. 自定义模块:自己书写的xx.js:require("./模块名");
为什么有的模块引入要./有的又不用加./
自定义模块:分为2大类
	1、文件模块:创建xx.js去公开需要公开的内容,主模块要引入,必须写为require("./模块名");

	2、目录模块:3种用法
		1、比如创建m1的文件夹,在其中创建index.js的文件,去公开需要公开的内容,主模块要引入,必须写为require("./m1");

		2、比如创建m2的文件夹,在其中创建xx.js的文件,,去公开需要公开的内容,主模块要引入,必须写为require("./m2");
必须再创建一个package.json的配置文件,写入:{"main":"xx.js"}

		3、创建一个文件夹必须名为:node_modules,再在其中创建出m3文件夹,在其中创建index.js的文件,去公开需要公开的内容,主模块要引入,必须写为require("m3");

其实真实开发中,我们程序员用的最多的是文件模块,目录模块的第三种方式其实根本不是给人用的(第三方模块下载后会自动创建此文件夹)

如何下载第三方模块
npm工具:Node Package ManagerNode.js的模块/包管理器,专门用于管理第三方模块的,作用:下载、更新、删除、维护包之间的依赖关系
	打开网址:npm官网https://www.npmjs.com/
	搜索你需要用到的模块:尽量用带有完全符合标签的那个包,或者是 第一个包:
		1、打开cmd:检查npm是否安装成功:npm -v
		2、在你的项目之中,再打开cmd
		3、下载:npm i 包名
		4、更新:npm up 包名
		5、删除:npm un 包名

mongo

  • 是基于json的数据库,json就是JavaScript Object Notation
  • 1.安装&启动
1、解压我提供的mongodb-win32-x86_64-2008plus-ssl-3.6.11.zip文件
	2、打开bin文件夹,里面有:mongo.exe(客户端) 和 mongod.exe(服务器端)
	3、如何启动:
		在bin文件夹中打开cmd:输入:.\mongod.exe --dbpath=你想要保存的绝对文件夹路径; - 服务器开启成功,而且那个文件夹就保存着你以后要存储的所有的数据
		不要关闭mongo服务器的cmd
		再打开一个cmd:输入:.\mongo.exe - 在上一个命令行可以查看我们是否链接成功 - 客户端开启成功

2、mongo的语法:都是在客户端cmd输入
1、数据库的操作
		1、查询所有数据库:show dbs
		2、创建/切换数据库:没有就创建,有了就切换:use 数据库名称
		3、查看当前选中的数据库:db
		4、创建数据表:db.createCollection("表名") - 无限,一定要先创建数据表后,我们才能查看到自己创建的数据库
		5、删除数据库:db.dropDatabase(); - 一旦删除不能恢复,不推荐,因为要坐牢
2、数据表的操作
		1、创建数据表:db.createCollection("表名",{size:5242880,capped:true,max:5000}) - 最大存储空间为5mb,最多存储500个,意味着这个数据表做了限制,不推荐
		2、查看目前所有的数据表:db.getCollectionNames();
		3、删除数据表:db.表名.drop();

3、*****数据的操作
		1、增:db.表名.save({键值对,...}) - 一次只能插入一条数据
			db.表名.save([{},{},{},....]) - 一次插入多条数据
			举例:db.user.save([{name:"付楠",age:18,pwd:"666666",email:"fn@qq.com",vip:"0"},{name:"袍哥",age:19,pwd:"999999",email:"pg@qq.com",vip:"1"}])

		2、删:db.表名.remove({}) - 不推荐,删除数据库中所有的数据
		             db.表名.remove({name:"任小波"}) - 会删除数据库中name:"任小波"的所有数据

		3、改:db.表名.update({条件},{$set:{新内容}});
			举例:db.表名.update({name:"任小波"},{$set:{pwd:"123123"}});

4、*查:db.表名.find(); - 找所有
	 db.表名.find({pwd:"666666"}); - 找到所有的密码为666666的数据
         db.表名.find({},{name:1,pwd:1}) - 找到所有的数据,但是只返回name和pwd
         db.表名.find().sort({age:1}) - 按照age升序排列,-1为降序排列
	 db.表名.find({age:{$gte:18}}) - 拿到所有age大于等于18的数据
	 db.表名.find({name:/正则/}) - 甚至可以用正则(模糊查询)
         db.表名.find().skip(5).limit(5) - 跳过前5条,再拿5条,理解为5-10条数据(第几个分页条显示第几条数据-第几条数据)
         db.表名.find().count() - 获取到此表有多少条数据(做出分页条)

安装mongoDBCompass软件:图形化界面,直观、好看、方便 - 仅仅只用于给我们方便查看

Node.js操作mongoDB:

1、安装第三方模块:mongoose

2、使用步骤:
	1、引入:const mongoose = require('mongoose');
	2、连接数据库:mongoose.connect("mongodb://127.0.0.1/数据库名称");
	3、创建出一个新的数据表的同时,设置数据类型的控制,防止用户乱输
			const UserSchema=mongoose.Schema({
				age: Number,
				pwd: String,
				email: String,
				vip: String,
				name: String,
			})
			//		模型名    类型限制     
			var User=mongoose.model("User",UserSchema,"数据表名");
	4、增:
			var x=new User({//仅仅只是创建出了一个x对象,并没有放入到数据库之中
				age: "20",
				pwd: "123123",
				email: "dy@qq.com",
				vip: "0",
				name: "dy",
			})

			x.save((err)=>{
				console.log("新增成功后要干什么");
			})

	5、删:
			User.remove/deleteOne/deleteMany({条件},(err)=>{// - 作者不推荐remove在mongoose之中使用
				console.log("删除成功后要干什么");
			})

	6、改:
			User.update/updateOne/updateMany({条件},{新内容},(err)=>{// - 作者不推荐update在mongoose之中使用
				console.log("修改成功后要干什么");
			})

	7、查:
			User.find({条件},(err,result)=>{
				result就是你的查找到的结果
			})
  • 目前:前端能传到后端的技术,只有一个:form表单,action属性可以随便自定义一个路由名称,后端解析此路由就可以通过objUrl.query.键名得到想要的部分