Node.js简介
1、javascript可以在浏览器执行的原因:
javascript可以在浏览器中执行时因为有javascript引擎支持,不同浏览器有不同的解析引擎:chrome时V8,safri是JSCore,IE是Chakra。
2、javascript可以操作DOM和BOM的原因:
浏览器存在DOM API,BOM API,Ajax API。javascript可以调用这些API。
3、javascript运行时环境:(正常运行所需要的环境)
运行引擎,内置web API
4、javascript能否进行后端开发:
常用的后端开发语言(java,python,php),javascript控制web行为,是前端开发语言,但借助node.js使其成为java一样的后端开发语言。因为javascript需要前端引擎如V8,所以只能在浏览器中运行,但又node之后出现了后端引擎,也可以运行javascript进行后端开发。
5、node.js是基于V8引擎的Javascript运行时环境。
node的存在,时javascript脱离浏览器任然可以运行,也是其作为后端开发语言的必要条件。使js除了在浏览器中运行为,也可以在node环境中运行。即js在前端为前端开发,在node中为后端开发。【浏览器时js的前端运行环境,nodejs时js’的后端运行环境】
6、node.js运行时环境:
nodeJs环境具备chorme的V8引擎和内置API,js代码调用API并放在V8中执行。但不具备DOM,BOM、Ajax和web内置API,因为这些是浏览器特有的属性。node中只具有js引擎(负责运行js代码)和node内置API(负责进行后端开发)。
7、nodeJS可以做什么:
node具有很强的横向扩展性,许多基于node的API使js开发更加容易。
Express框架,可快速构建web应用;
Electtron框架购机爱你跨平台的桌面应用
restify框架可快速构建API接口项目
读写和操作数据库,创建命令行辅助前端开发。
Node.js环境安装
node以js语言为基础,运行jsdiamagnetic需要安装node环境,官网下载,并安装,配置环境变量。在window终端输入node -v出现版本号即为安装成功。
Node.js执行js代码
node +js文件命名
Node.js内置API
和前端js调用webAPI一样(documen)node也有内置API,使其不仅仅限于前端开发。
1、fs模块(nodejs用来操作文件的模块,满足用户对文件操作的需求)
fs.readFile() 读取指定文件的内容
fs.writeFile() 向指定文件中写入内容
导入fs模块:const fs=require('fs');
语法:
fs.readFile(path[,options],callback);path是资源路径,第二个是读取的字符编码,第三个是回调函数拿取读取结果。
node .\1使用readFile方法读取文档内容.js 命令执行
//导入fs模块
const fs=require('fs');
//调用fs.readFile函数读取文件
fs.readFile('./测试.txt','utf8',function(err,dataStr){
//打印失败的结果
console.log(err);
console.log("-------");
//打印成功的结果
console.log(dataStr);
})
结果:
null
-------
1121odcnc冲动是魔鬼
如果读取成功err的值是null,dataStr是读取的内容;读取失败err是失败的对象,dataStr是undefined
fs.writeFile写入文件
fs.writeFile(file,data[option],callback);file是带路径的文件,data是要写入的内容,callback
回调函数。
//写入成功err是null,如果不存在文件就新建一个文件。
//写入失败err是错误信息,
2、path模块:(path模块是nodejs官方提供的处理路径的模块,它提供了一系列的方法和属性,用来满足用户对路径的处理需求。)
path.join()将多个路径拼接成一个完整的字符串
path.basename()从路径字符串中将路径解析出来
path.extname() 从路径中回取文件扩展名
同理也要导入:
const path=require('path')
3、http模块
http模块是node提供的用来创建web服务器的模块通过http.createServer()方法将一台电脑变成一台web服务器,对外提供web资源服务,使电脑不需要安装第三方软件而用node提供的API即可对外提供web服务和flask有点类似。也需要导入http模块。
node创建web服务器:
1、导入模块;
const http=require('http');
2、http.createServer创建web服务器;
const server=http.createServer();
3、为web服务器绑定request事件,监听客户端请求;
server.on('request',(req,res)=>{
console.log("request is setted !");
})
4、启动服务器。
server.listen(80,()=>{
console.log("server is running");
})
//补充
req,res使请求和响应,和携带数据用于前后端交互。
req提供了:req.url;req.method等方法;res提供res.end方法传递数据并结束本次请求,完成一次交互。响应时的中文乱码问题,设置响应头。
res.setHeader('Content-Type','text/html;charset=utf-8');
3.1、http路由
如何输入不同的地址响应不同的内容你呢?http模块通过编程式路由管理监管。
在为web绑定监听事件时:
1、获取请求url地址;
2、设置默认响应内容;
3、判断用户的请求地址;
4、设置响应头解决编码问题
5、res.end响应相关内容
//主要又request监听来编写逻辑
server.on('request',(req,res)=>{
var url=req.url;
if(url==="/" || url==='/index.html'){
content='<h1>首页</h1>'
}
else if(url==="/one.html"){
content='<h1>one</h1>'
}
else{
content='<h1>Hello.word</h1>'
}
res.setHeader("Content-Type","text/html;charset=utf-8");
res.end(content);
}) //文件前面要有/不然出错。
3.2、http模块部署静态资源,后端渲染
__dirname时获取当前虚拟路径。
//读文件模块
const fs=require('fs');
//path路径模块
const path=require('path');
//web服务器模块
const http=require('http');
const server=http.createServer();
server.on('request',(req,res)=>{
// //获取请求的url
var url=req.url;
//console.log(url);
// //组装完整url
var index=path.join(__dirname,url);
//console.log(index);
// //读取文件内容
fs.readFile(index,'utf8',(err,dataStr)=>{
if(err) return res.end("NOT FOUND");
res.setHeader("Content-Type","text/html;charset=utf-8"); //这里要设置响应数据类型围殴html不然读取的式文件
res.end(dataStr);
})
})
server.listen(80,()=>{
console.log("server is running");
})
模块化
编程的模块化式遵守固定的规则,把一个大文件差分成独立的互相依赖的多个小文件。
好处:1、提高了代码的复用性,每个模块实现一个功能,可以公用。
2、提高了代码的可维护性;
3、实现按需加载,减少冗余度
模块化规范:
在模块化过程,即对模块拆分与组合时,需要遵守的规则。例如:
如何声明一个模块,使其他模块可以公用;如何导入可公用的模块。
node的模块化
node模块分类:1、内置模块(fs,path,http等);2、自定义模块(用户创建的js文件)3、第三方模块(框架)
模块加载
require方法加载模块会执行模块的代码。(加载时何以省略js后缀)
加载内置模块只需提供名字,加载自定义模块提供路径和名称;加载第三方模块需下载并导入。(一般使用模块管理器webpack来管理)
node的模块作用域
函数,变量只能在当前模块使用,这种访问限制叫模块作用域。也就是说变量和函数只能在本模块访问,即使通过require导入也不能访问。
one.js:
const name='xiaoxu';
function show(){
console.log("myname is"+name);
}
two.js:
const func=require('./one.js');
console.log(func.name);
func.show() //两个都不能访问,有作用域限制,都是空对象{},{}。这样的好处时放置全局变量的污染。
那么如何如何从外部访问模块内的对象或方法呢?module对象!!!
每个js都用一个module对象,存储了当前模块的信息,打印如下:
console.log(module);
Module {
id: '<repl>',
path: '.',
exports: {},
parent: undefined,
filename: null,
loaded: false,
children: [],
paths: [
'C:\\Program Files\\nodejs\\repl\\node_modules',
'C:\\Program Files\\nodejs\\node_modules',
'C:\\Program Files\\node_modules',
'C:\\node_modules',
'C:\\Users\\54295\\.node_modules',
'C:\\Users\\54295\\.node_libraries',
'C:\\Program Files\\nodejs\\lib\\node'
]
}
module对象中的exports管理了对外暴露的对象或方法,将对象或方法封装为一个对象赋给exports就能再外部访问了。
也就是说每个js由module管理,其中的exports对象主要负责管理向外暴露的对象,若想让某变量或函数向外暴露须在exports中注册。
自定义模块使用module.exports将成员共享出去,供外界使用。
外界用require方法导入时得到的就是module.exports对象,其中存储了众多共享对象,默认为空{}。
值得注意的时module.exports={}的优先级要高于module.exports.name(这种方法挂在的就没有了)
由于module.exports对象单词写起来比较复杂,为例简化向外共享成员的代码,node提供了exports对象指向module.exports。也就是module的exports子js中可以直接使用了。
最终结果也还是以module.exports为准。
而且require导入模块时得到的永远是以module.exports指向的对象为准。
exports——>【】<——module.exports(主)
node的语法规范CommonJS:
CommonJS规定了每个模块内部,module代表当前模块;module的exports对象记录对外接口;加载模块用require方法且加载的module.exports。
npm(node package manager)包管理器
1、node的第三方模块也叫包;由于node的内置模块仅仅提供一些底层的API,开发效率低,使用包并使用其提供的API极大的提高了开发效率。(相当于框架和底层API的关系),就像python的第三方库一样提供供更加丰富的功能。
2、包的下载途径:https://www.npmjs.com/ 用于搜索包
https://registry.npmjs.org/ 用于下载需要的包
开发包的公司提供了一款包管理工具npm(node package manager)且随node.js的安装自动安装。npm -v查看版本 node -v查看node版本。安装第三方模块的命令 npm install 名称,第一次安装会创建node_modules的文件夹存储所已安装的包,package-lock.json管理包的路径等一些重要的信息,require时会根据这里的信息查找包。和Maven类似,不需要我们引入导入,配置路径等 。
npm install 名称@版本号 安装指定版本,重新安装会覆盖。
npm自动管理各种包,不需要程序员修改。
另外项目的更目录中还要有一个package.json的配置文件,用来对项目进行管理,记录项目的信息,如该项目使用了那些第三方包在dependencies中和package-lock.json不同后者时记录第三方包的路径信息用于查找包信息。
初始化node项目
安装的命令 npm init -y 注意项目名称只能时中文。且有了该文件夹后通过 npm install 自动安装所有需要的依赖第三方包(dependecies记录的包),非常棒 npm uninstall 卸载包
git多人协作开发时要忽略node_modules文件夹。其他人直接联网下载即可。不用上传。
如果某些包只在开发阶段使用,上线后不会使用,就将第三方包放在devDependencies中,命令
npm install 包名 -D & npm install 包名 –save-dev
npm的国内镜像,镜像时文件存储的一种形式,一个磁盘上的数据在另一个磁盘存在完全跟=相同的副本即为镜像
切换包下载地址:
//产看包下载地址: npm config get registry
//切换国内镜像地址:npm config set registry=https://registry.npm.taobao.org/
nrm 为更加方便切换下载源,安装nrm的工具利用nrm工具可以快速切换和查看下载源,命令:
// 安装nrm工具 npm install nrm -g
// 查看可用镜像源 nrm ls
// 切换镜像源 nrm use taobao
//也可以全局安装cnpm工具包从国内镜像下载 npm install cnpm -g
包的分类
- 项目包:安装在项目的node_modules中的包;
- 全局包:安装在本地的node_modules中的工具包,要使用那些工具命令就安装全局包,只需要安装一次即可
npm install 包名 -g
npm uninstall 包名 -g
包结构:
一个包必须必须符合以下要求:
一个包必须以单独的目录存在
一个包必须要包含package.json配置文件
package.json中必须包含name,verrsion,main这三个属性,分别代表包名,版本号,包的入口。
自定义包:
新建目录作为报的单独目录
在目录中新建:
- package.json (包管理配置文件)
- index.js (包入口文件)
- README.md (说明文档)
package.json:
{
"name":"util_one",
"version": "1.0.0",
"main": "index.js", //包的入口
"description": "格式化事件的小工具",
"keywords": ["timeFormat","time"],
"license": "ISC"
}
index.js:
//包入口文件
function dataFormat(dataStr){
const date=new Date();
const year=date.getFullYear();
const month=date.getMonth()+1;
const day=date.getDate();
const hour=date.getHours();
const minute=date.getMinutes();
const second=date.getSeconds();
return year+"-"+"-"+month+"-"+day+" "+hour+":"+minute+":"+second
}
module.exports={
dataFormat
}
README.md:时markdown写的解释文档
测试自定义包
test.js:
const df=require('./10-1module规范-自定义包') //导入时需要直接导入js文件直接导入单文件包目录即可,一方面package.json记录了包目录信息会自动查找js文件,也符合模块化规范
const date=df.dataFormat(new Date());
console.log(date);
/*结果
PS D:\NodeJS\Utill-1> node .\10-module规范.js
2022--1-25 11:9:34
*/
直接导入单文件包目录即可,会依次 package.json—>index.js—->上级目录—->package.json—>index.js—-
同类型不同功能的js可新建src目录将index.js的不同方法拆分到src中的js文件中并向外暴露,在index.js导入即可。
发布规范化包:
对包模块化后可以发布到npm官网;1、注册npm账号,2、在包所在的目录新建终端,并用npm login登录(前提是不可以使用镜像地址,使用npm官方下载地址,nrm检查)3、使用npm publish (在包的根目录下)发布前登陆官网查询,名称不能雷同,发布后可登录查看。
包的加载机制:
前面已经说过require加载包会执行依次,那么如果重复加载呢?包会优先从缓存中加载,当重复加载后,从缓存中加载,不会再次执行。
内置模块的加载优先级最高。
模块加载自定义模块必须以./ …/开头分别表示当前目录,和上一级目录。不然node会将其当作内置模块或第三方模块。
加载模块是入宫省略了扩展名,node会依次按以下顺序加载文件:
1、确切的文件名
2、补全.js扩展进行加载
3、补全.json扩展进行加载
4、补全.node扩展进行加载
node后端开发
express模块
express是基于node.js平台的快速,开放,极简的web开发框架。
express框架和node的http模块相似,专门用来创建web服务器的。
express本质是一个第三方包,用来快速创建web服务器。相对于内置模块http更加方便。
安装 npm install express@4.17.1
创建web服务器
//导入express模块
const express=require('express');
//创建web服务器
const app=express() //这里是无参构造方法,创建express实例
//启动服务器和http模块相似
app.listen(80,()=>{
console.log("express server is running !");
})
//监听get请求 .get()方法
app.get('请求地址',function(req,res){ /* 处理函数*/ }) //参数以是请求地址 参数二是处理函数
get方法获取地址的参数:
req.query
req.params获取动态参数,参数用 :参数 做占位符 (/user/:id)
req.body 请求体获取数据,必须要配置解析数据的中间才可以获取
//监听post请求 .post()方法
app.post('请求地址',function(req,res){ /* 处理函数*/ }) //参数以是请求地址 参数二是处理函数
//响应内容
app.send();
express托管静态资源
express提供了static方法创建静态资源服务器,将某个文件对外开放。且指定静态资源文件按后该目录不会出现在url地址中。
托管后外部就可以访问这些静态资源了。
app.use(express.static('public'))
需要托管多个目录只需对此调用方法即可,访问时会依次按顺序查找所需文件。
如果需要区分的话只需要添加一个参数即可
app.use('/public',express.static('public'))
此时public文件名就会加到url中了也便于区分。
nodemon node的调试环境 debug模式
自动监听项目文件的变动,修改代码后会自动重启项目,极大的方便了开发和调试。这是工具包,使用全局安装 npm install nodemon -g
之前是使用 node index.js启动项目
安装nodemon后 适应 nodemon app.js 启动项目动态调试。保存后生效 ctrl +s。
express的路由
路由是指请求与服务之间的映射关系。
express路由由三个部分组成,分别是请求类型,请求url地址,处理函数。
get,post的基础
模块化路由
为了方便对路由进行管理,一般不讲路由直接挂载到web服务器上而挂载到web服务器的单独的路由管理模块Router
1、创建路由模块js文件
2、调用路由管理模块express.Router()实例化路由管理对象
3、在路由管理对象上挂载路由
4、使用use方法注册路由模块,挂载到web服务器上
var express=require('express');
var router=express.Router(); //这里只是调用了express的router方法相当于匿名内部类
router.get('/user',function(req,res){ })
router.post('/user',function(req,res){ })
module.exports=router
测试模块
const userRouter=require('./router.js');
//将路由挂载到当前服务器上 才能正常访问
app.user(userRouter);
//修改路由地址再添加一个参数即可app.user('api',userRouter); userRouter访问时加一个/api的路径
//use方法是注册全局间的,将暴露的模块在当前注册到当前对象上。
中间件
回调函数,对请求进行预处理。是一个函数。如:
app.get('/user',function(req,res)=>{next()})
function就是中间件用于对请求进行预处理。
注意:
中间件函数必须包含next参数,而路由处理函数只包含req,res。
next函数实现多个中间件的连续调用,转发到下一个中间件或路由
客户端发起的任何请求到达服务器都会触发额中间件角坐全局中间件。
use方法注册全局中间件。
错误中间件
app.use(function(err,req,res,next){ }) 用于获取全局错误
局部中间不用use注册时局部,直接加到get,post方法中
app.get(’/user’,中间件,function(req,res){…})
const 中间件=function(req,res,next){ … next()}
多个局部中间件直接当作参数添加即可
要在路有前定义中间件,next方法后不再写逻辑
中间件的作用:多个中间件之间共享同一份req,res,再不同中间件对这两个对象那个添加自定义属性或方法,供后续中间件或路由使用。中间件会按照先后顺序依次执行。
express内置中间件:
- express.static 管理静态资源
解析数据类型的类似javaweb的fastjson工具包的作用 - express.json 解析json数据
- express.urlencoded 解析URL-encoded格式的请求数据
post从请求体获取数据时配置数据解析中间,
app.use(express.json());
…console.log(req.body)…
前端发送的数据都可通过json发送,后端只解析json类型就可以了。
前后端传递数据的解析
// An highlighted block
var foo = 'bar';
app.use(express.urlencode());
..
//前端发送form表单的数据的解析中间件。
//后端的数据解析node提供内置querystring模块,提供了parse方法将字符串转化为对象。
必须要注册这些解析数据的中间件,不然由于数据类型不符合会造成数据发送或接收不成功!
cors解决nodejs的跨域问题
在谈跨域的解决方法前,首先了解什么是跨域,为什么会产生跨域。
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。而产生跨域问题是由于浏览器的同源策略限制。同源策略是浏览器最核心也是最基本的安全功能,如果缺少了同源策略,则浏览器的功能可能会出现紊乱。跨域问题后台发送的数据会被浏览器拦截。
浏览器是通过document.domain属性来检查两个页面是否相同的,因此只要通过设置相同的document.domain,两个页面就可以共享cookie
jsonp方法 只支持get不推荐
cors方法
CORS:全称”跨域资源共享” 推荐
由于类似于java的静态页面和后台后运行再tomcat中,三个条件都相同,所以没有出现,node中:
本地端口:http://127.0.0.1:5500/index.html
express端口 http://127.0.0.1:80
出现了端口不一致。前后端分离,前后端分离的开发容易出现跨域问题
发送Ajax请求出现该错误(端口不一样):
Access to XMLHttpRequest at 'http://localhost/user' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
解决方案:
1、安装exprss的cors中间件 npm install cors
2、导入中间件 require导入
3、再所有路由之前注册cors中间件, use方法
res.setHeader('Access-Control-Allow-Origin','*'); //允许任何域的请求
node操作数据库
1、安装并配置mysql环境
略
2、node安装第三方模块,连接到数据库
npm install mysql
//1、导入mysql模块
const mysql=require('mysql');
//建立数据库连接
const db=mysql.createPool({
host:'127.0.0.1', //数据库id(本机ip)
user:'root', //数据库用户名
password:'password', //数据库密码
database:'db1' //连接的数据库
})
//2、测试连接成功
db.query('SELECT 1',(err,result)=>{ //该语句没有任何作用主要时测试是否连接成功
if(err) return console.log(err.message);
console.log(result);
}) //结果:[ RowDataPacket { '1': 1 } ]
//3、通过sql语句操作数据库
//查询query方法第一个参数时sql语句,第二个参数时回溯函数: query的sql参数要以数组的格式传入
db.query('sql语句',(err,result)=>{
if(err) return console.log(err.massage)
console.log(result);
})
//insert
var sql='insert into tb_user (username,password) values(?,?)'; //占位有多为时以数组传入数据
var value={name:'xiaoming',password:123456};
db.query(sql,[value.name,value.password],(err,results)=>{ //这里的参数只能时results不可随意更改
if(err) return console.log(err.massage);
if(results.affectedRows ===1){
console.log("ok");
}
})
//update和delete都相同只需要修改sql语句就行了,传参都是一样的
Session与Cookie
session与cookie是会话跟踪技术,session负责保持服务器端的状态,cookie负责保持客户端的状态。
1、安装express-session
npm install epress-session
2、全局注册session中间件
app.use(session({
secret:'keyboard cat', //可以为任意字符串
resave:false,
saveUninitialized:true
}));
3、使用session保持服务器端状态
req.session访问和使用session对象
app.get('/name',(req,res)=>{
req.session.name=req.query;
res.send(req.session.name);
}) //数据以对象的形式存储再session中{"name":"1"} 直接.名称创建和获取对象即可
app.get('/more',(req,res)=>{
req.session.more=req.query;
res.send(req.session.more+req.session.more.age);
})
/*
http://localhost/more?name=xuwenhui&age=22
[object Object]22
*/
//注销
session: req.session.destory()
JWT技术
session需要配合cookie使用分离开发时存在端口问题,cookie不支持跨域访问,因此涉及跨域问题推荐jwt机制。
创建web后端接口
node项目这是黑马程序员的教程的后端接口案例。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/156323.html