文章目录
node.js
在node平台上执行js代码
1.编写js代码,保存文件的扩展名为js
2> 在命令行窗口中,输入命令:node 文件名.js
两个js文件调用
2.js调用1.js,命令窗口执行node 2.js
// 文件1.js
module.exports = {
函数名1:function(){
函数体
return 0;
},
函数名2:function(参数){
函数体2
return 0;
}
}
// 文件2.js
var funcs = require('./1');
funcs.函数名1();
funcs.函数名2(参数);
在nodejs平台上,定义一个funcs的模块,在模块中有2个函数,一个函数使用"*"打印直角三角形图案,另一个函数用于计算从1+2+…+max的和,其中max是函数的形参。并且模块中导出这2个函数。在app.js中导入funcs模块,调用这2个函数。
// 1.js
module.exports = {
printTriangle:function(){
var a = '';
for(var i=0;i<5;i++){
a = '';
for(var j=0;j<i;j++){
a = a+'*';
}
console.log(a);
}
},
cou:function(max){
var i = 1;
var all=0;
for(;i<=max;i++){
all = all+i;
}
return all;
}
}
// 2.js
var funcs = require('./1');
funcs.printTriangle();
console.log(funcs.cou(100));
es6新语法
声明变量:const 声明常量,不能修改
let 声明的变量具有块的,可修改
<body>
<script>
const a=10;
// a++; // 错误,const定义的a的值不能修改
let b=10;
console.log(++b); // 11
for(var i=0;i<10;i++){
let cmt = 10; // 在块中使用let声明的变量具有块的作用,var没有块作用域
cnt++;
}
console.log(cnt); // 不存在,cnt值只存在于for循环中
</script>
</body>
声明函数定义可以使用箭头函数:(形参列表)=>{函数体}
<body>
<script>
var getSum = (max)=>{
var sum=0;
for(var i=01;i<=max;i++){
sum += i;
}
return sum;
}
console.log(getSum(100));
</script>
</body>
简化书写规则:
只有一个形参,小括号可以省略
<body>
<script>
var getSum = max=>{
var sum=0;
for(var i=1;i<=max;i++){
sum += i;
}
return sum;
}
console.log(getSum(100));
</script>
</body>
当函数体中只有一条返回语句,大括号和return关键字可以省略
<body>
<script>
var getResult = x => x*x; // 函数体
console.log(getResult(2));
</script>
</body>
数组排序
<body>
<script>
var nums = [10,40,20,30];
nums.sort(function(a,b){
return (a-b); // 升序排序
//return (b-a); // 降序排序
});
// nums.sort((a,b)=>a-b) // 等于上面函数
console.log(nums);
</script>
</body>
模块
fs模块 文件操作模块
使用文件模块来读取文件的内容
path模块就是路径模块
__dirname
:记录了当前可执行程序所在的路径
path.join(路径的各部分)
:合并成完整路径
读 txt 文件
注意文件坐在位置,我的位置是E:\\code\\JS
,文件名是a.txt
//使用文件模块来读取文件的内容
//导入文件系统模块
const fs = require('fs');
//导入路径模块
const path = require('path');
//err记录了读文件过程中发生的错误,
//data保存读取文件的内容
var fname = 'E:\\code\\JS';
console.log( __dirname);
fs.readFile(path.join(fname,'a.txt'),(err,data)=>{
if(err){
//发生了错误,就打印错误的原因
console.log(err.message);
return;
}
//没有错误,就打印文件的内容
console.log(data.toString());// toString转字符串
});
console.log('程序结束');
写 txt 文件
const fs = require('fs');
var info="good morning";
//writeFile函数就是将内容写入到文件中,覆盖掉文件中原有内容
//第一个参数就是目标文件的文件名(带路径)
//第二个参数就是需要写入文件的内容
//第三个参数就是回调函数
fs.writeFile('./a.txt',info,err=>{
if(err){
console.log(err.message);
return;
}
console.log('写入成功');
});
http 系统模块
静态服务器
http对象的方法
createServer()
:创建服务器
listen(端口号)
:监听端口号,启动服务器
服务器:
on()
:订阅事件处理函数
req对象
:请求对象,封装了请求数据包中的数据
req.url
: 请求的页面的地址
res对象
:响应对象,记录了服务器需要发送给浏览器的数据
res.end([data])
: 如果有data实参,将data数据发送到浏览器中; 结束响应
res.writeHead(状态码,{属性名:属性值 })
:在响应报文的报文头添加属性
res.write(内容)
:向浏览器中输出内容
url系统模块:进行url地址处理
url.parse(地址,true)
:将地址解析成一个对象
pathname
: 字符串格式的具体的地址
query
:就是get方式提交的数据:{数据名1:数据1,数据名2:数据2,…}
在vscode上编写如下代码保存,在该文件目录下输入cmd
进入(该文件目录下的cmd界面)(要退出目前的cmd按Ctrl+C
),输入node 1.js
,再在浏览器输入localhost:8080
进入,出现目标页面
hi,user!!!
//导入http系统模块
const http = require('http');
//调用http对象的方法创建web服务器
var app = http.createServer();
//编写请求处理函数
//req:请求对象,记录浏览器发出请求数据包中的数据
//res:响应对象,记录服务器处理的结果,响应对象中的内容最终要发送给浏览器
app.on('request',function(req,res){
res.write('<h1>hi,user!!!</h1>'); //进入后的界面
res.end();
})
//服务器监听端口
app.listen(8080,function(){
console.log('服务器已经启动,请访问http://localhost:8080 地址');
})
状态码 | 解释 |
---|---|
200 | 成功 |
302 | 重定向 |
404 | 请求资源找不到 |
500 | 服务器端代码出错 |
浏览器向服务器发送数据
get方式:url?数据名1=数据1&数据名2=数据2&...
http://localhost:8080/test.html?uname=Rose&salary=6000
post方式:在请求报文主体中回附带数据,
数据格式:数据名1=数据1&数据名2=数据2&...
{数据名1:数据1,数据名2:数据2,...}
接收浏览器提交的数据
get方式:let {query}=url.parse(req.url,true);
query中就是get方式提交到服务器的数据
post方式:
var data = '';//声明变量用来保存提交的数据,赋初始值为''
//订阅请求对象的data事件和end事件的事件处理函数
req.on('data',(chunk)=>{
//将接收到数据chunk连接到data变量中
data += chunk;
})
req.on('end',(chunk)=>{
//处理接收到的数据
querystring.parse(data);//将接收到的数据转换成为json格式
})
请求服务器端的静态页面
//建立一个服务器:http系统模块
//1 导入http模块
const http = require('http');
// 导入地址处理模块 url
const url = require('url');
// 导入路径处理模块 path
const path = require('path');
// 导入文件和文件夹操作的系统模块 fs
const fs = require('fs');
//2 调用http对象的方法创建服务器
let app = http.createServer();
//3 订阅请求到达事件的处理函数
app.on('request',(req,res)=>{
// 1 获取请求地址中的文件名
const {pathname} = url.parse(req.url);
console.log(pathname);
// 2 拼接页面文件名的绝对路径,屏蔽掉网站图标的请求
if(!pathname.endsWith('.ico')){
var fname = path.join(__dirname,'static',pathname);
// 3 读取文件的内容,发送给浏览器
fs.readFile(fname,(err,data)=>{
//如果读文件过程中发生了错误,发回404响应
if(err){
res.writeHead(404,{
'content-type':'text/html'
});
res.write('error');
res.write(err.message);
res.end();
}else{
res.end(data);
}
})
}else{
res.end('<h1>OK</h1>');
}
})
//4 监听端口号
app.listen(8080,()=>{
console.log('服务器已经在8080端口等待浏览器的请求...');
})
const http=require('http');
const url =require('url');
const path = require('path');
const fs = require('fs');
let app = http.createServer();
app.on('request',(req,res)=>{
let {pathname,query} = url.parse(req.url,true);
if(!pathname.endsWith('.ico')){
if(query){
//如果有提交数据,则在控制台上打印数据
console.log(query);
}
var fname = path.join(__dirname,'static',pathname);
fs.readFile(fname,(err,data)=>{
if(err){
res.writeHead(404,{'content-type':'text/html'});
res.write(err.message);
res.end();
}else{
res.end(data);
}
})
}
});
app.listen(8080,()=>{
console.log('服务器已经启动...')
})
const http=require('http');
const url =require('url');
const path = require('path');
const fs = require('fs');
const querystring = require('querystring');
let app = http.createServer();
app.on('request',(req,res)=>{
let {pathname,query} = url.parse(req.url,true);
if(!pathname.endsWith('.ico')){
//获取post方式提交的数据
var result='';//保存提交数据的变量
//请求对象监听2个事件: data事件,有post方式提交的数据到达服务器
// end 事件,post方式提交的数据已经全部到达
req.on('data',(chunk)=>{
result += chunk;//将本次接收到的数据连接到result变量
});
req.on('end',()=>{
console.log(querystring.parse(result));
})
var fname = path.join(__dirname,'static',pathname);
fs.readFile(fname,(err,data)=>{
if(err){
res.writeHead(404,{'content-type':'text/html'});
res.write(err.message);
res.end();
}else{
res.end(data);
}
})
}
});
app.listen(8080,()=>{
console.log('服务器已经启动...')
})
使用nodejs编写动态网站,实现用户注册功能:
地址为/reg,服务器发回有用户注册表单的页面
地址为/doReg,服务器接收提交的用户数据,发回注册成功的提示信息
先进入该目录下的cmd界面,输入node 1.js
,浏览器浏览localhost:8080/reg
和localhost:8080/doReg
1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/doReg" method="post"><!--action 属性用来指定表单提交数据时所指向的地址-->
<p>Account:<input type="text" name="acc"value=""></p>
<p>Password:<input type="password" name="pwd" value=""></p>
<p><input type="submit" name="login" value="login"></p>
</form>
</body>
</html>
1.js
//web
const http = require('http');
const url = require('url');
const path = require('path')
const fs = require('fs')
const querystring = require('querystring');
let app = http.createServer();
app.on('request',(req,res)=>{
//处理多个请求地址,不同的地址有不同的处理方式
// /reg:打开注册页面,静态页面:1>编写html页面代码 2>读取文件内容发给浏览器
// /doReg:接收注册的账号和密码等等数据,提示注册成功
const{pathname}=url.parse(req.url,true);
switch(pathname){
case '/reg':
let fname = path.join(__dirname,'1.html');
fs.readFile(fname,(err,data)=>{
if(err){
res.end('<h1>ERROR</h1>');
}else{
res.end(data);
}
})
break;
case '/doReg':
var data='';
req.on('data',(chunk)=>{
data += chunk;
});
req.on('end',()=>{
let obj = querystring.parse(data);
console.log(obj);
res.end('<h1>regist success'+obj.acc+'</h1>');
});
break;
}
});
app.listen(8080,()=>{
console.log('已启动');
})
浏览器端请求静态资源,如css,js,jpg图像等,服务器返回相关的资源文件
先进入该目录下的cmd界面,输入node 1.js
,浏览器浏览localhost:8080/1.html
和localhost:8080/a.jpeg
1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/doReg" method="post"><!--action 属性用来指定表单提交数据时所指向的地址-->
<p>Account:<input type="text" name="acc"value=""></p>
<p>Password:<input type="password" name="pwd" value=""></p>
<p><input type="submit" name="login" value="login"></p>
</form>
</body>
</html>
1.js
const http = require('http');
const url = require('url');
const path = require('path')
const fs = require('fs')
const querystring = require('querystring');
let app = http.createServer();
app.on('request',(req,res)=>{
const{pathname}=url.parse(req.url,true);
switch(pathname){
case '/1.html':
let fname = path.join(__dirname,'1.html');
fs.readFile(fname,(err,data)=>{
if(err){
res.end('<h1>ERROR</h1>');
}else{
res.end(data);
}
})
break;
case '/a.jpeg':
let fname1 = path.join(__dirname,'a.jpeg');
fs.readFile(fname1,(err,data)=>{
if(err){
res.end('<h1>ERROR</h1>');
}else{
res.end(data);
}
})
break;
}
});
app.listen(8080,()=>{
console.log('已启动');
})
Express
下载安装exprtss-generator:用于生成npm install express-generator -g
生成的代码结构
app.js
:入口
public
文件夹:静态资源文件夹,保存html页面文件,css文件,js文件,图片文件等资源文件
views
文件夹:模块文件夹,保存模块文件
routes
文件夹:路由文件夹,保存路由文件f
创建项目
npm i art-template -S
npm i express-art-template -S
npm i body-parser -S
npm i session -S
1.创建项目文件夹
2.进入项目文件夹,创建配置文件package.json:npm init -y
3.使用框架系统:express
4.安装依赖的中间件:npm install
5.启动项目:npm start
注::后的代码都是在该项目文件内的cmd里输入
在项目中使用模板引擎输出带有动态数据的页面
express-art-template
在目标文件下输入npm i -S art-template
和npm i -S express-art-template
执行
启动开发工具,打开项目,打开app.js,在app.js
中配置模板引擎
// 导入art-tempate模板引擎
const template = require('art-template');
// 告诉express框架模板文件所在的位置
app.set('views', path.join(__dirname, 'views'));
// 告诉express框架模板的默认后缀是什么
app.set('view engine', 'art');
// 当渲染后缀为art的模板时 所使用的模板引擎是什么
app.engine('art', require('express-art-template'));
模板语法
{{变量名}} :在页面中输出变量的值
{{if(条件表达式)}}…{{/if}}:按条件输出
{{each 变量}}…{{/each}}:遍历变量中的各个元素进行循环
$value就是遍历的一个元素 $index:遍历出来的元素的下标
1> 在views文件夹下编写模板文件:*.art
2>在路由文件中渲染模板文件:res.render(模板文件名,{数据名:数据})
制作商品管理功能:商品列表、新增商品、删除商品,模块
1> 设计路由:routes/goods.js:处理商品模块的全部路由,也就是说,请求商品的任何功能由goods.js中的代码来进行处理
2>具体功能的设计:
/:商品列表, 逻辑:找到所有的商品数据;将商品数据渲染到模板文件
商品数据放在全局变量,
/delete/100:商品删除,逻辑:获取要删除商品的编号,是请求地址中的id值
params,删除商品数据,重定向到列表页面
res.redirect(‘地址’) :重定向到指定地址
新增商品:
进入新增商品的页面:点击“新增”按钮或者超链接,进入页面
页面跳转,地址设置,选择渲染模板文件()
处理新商品数据:路由的处理代码的逻辑,
1>接收post方式提交的数据 :中间件 body-parser
1.1> 安装 npm i body-parser -S
1.2> 导入
const bodyParser =require(‘body-parser’);
配置使用
// 解析 application/json
app.use(bodyParser.json());
// 解析 application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended:true}));
到req.body属性中获取数据就ok了
2> 创建新商品对象
3> 将新商品对象数据保存
==========================================================
修改商品:进入修改页面(包含表单),处理修改后的商品数据
==========================================================
用户登录功能:
进入登录页面
验证输入的用户和密码,显示验证的结果:成功了,进入商品列表页面,失败了,重新登录
路由设计: /login: 进入登录页面
1> 模板文件:views/login.art
2> 添加进入登录页面的路由
/doLogin:处理登录用户数据
添加处理登录数据的路由,逻辑:
接收数据
查找(在模拟数据中查找)
在项目中有些页面是需要登录成功后才可以进入的。
比如:商品新增页面需要登录用户才可进入
在进入新增商品页面代码中添加逻辑:检查是否是登录用户,不是的话,跳转到登录页面强制用户登录。
服务器端的状态管理技术:
1> 服务器端工作在HTTP协议上,所以天生就是无状态的
2> 有的场景中需要状态:比如:购物车,
3> 状态管理的技术:Cookie :在浏览器端开文件记录浏览器自己的数据;减轻了服务器的负担;用户可以在浏览器端修改数据;数据安全性比较差;
Session:在服务器端的内存中记录浏览器端的数据;数据安全性得到保障;增加了服务器的负担
Express框架下使用cookie-parser中间件进行cookie编程
1> 下载安装:npm i cookie-parser -S
2> 配置使用cookie-parser进行cookie编程
3> 向cookie中读写数据
在同一个网站的多个页面中可以通过cookie共享数据
Express使用express-session中间件进行session状态管理
1>下载安装 npm i express-session -S
2> 在app.js中配置使用expression-session
app.use(session({
secret: ‘keyboard cat’,
resave: true, saveUninitialized: true
}));
3> 在session中读写数据
req.session.数据名称
req.session.数据名称=值
session会话变量:在一次会话中有效
===============================================================课堂练习:
在express框架下,编写学生管理的功能:学生的增删改查。
合并新增和修改
设计路由:
/edit/:id :进入修改页面
/doEdit: 处理提交的修改数据
修改
进入修改页面(包含输入数据的表单)
逻辑:根据id找到需要修改的数据;渲染模板文件,传递找到的需要修改的数据;处理修改后的数据
扩展的考虑:新增和修改多数的是一样,有少量的区别
能不能合并?合并
/change/:id :进入新增和修改表单页面的地址
/save :处理新增和修改数据的地址
如果是数据库保存数据:没有id就是新增
判断模拟数据中有没有商品,有是修改
请求
请求 | 用途 | 注 |
---|---|---|
get请求 | 显示数据 | 浏览器浏览 |
post | 增加数据 | postman浏览 |
put | 主要用于修改用户 | postman浏览 |
delete | 主要用于删除用户 | postman浏览 |
注:post、put、delete在浏览器中浏览不出来,要在postman软件中浏览 |
配置路由
get请求
可在浏览器中浏览
const express = require('express')
const app=express()
// localhost:3000
app.get("/",(req,res)=>{
res.send('你好 express')
});
// localhost:3000/article
app.get("/article",(req,res)=>{
res.send('新闻页面')
});
// localhost:3000/login
app.get("/login",(req,res)=>{
res.send('登入')
});
// localhost:3000/register
app.get("/register",(req,res)=>{
res.send('注册页面')
});
app.listen(3000,()=>{
console.log('已启动');
});
post请求
浏览器无法浏览,需在postman软件浏览
// localhost:3000/doLogin
app.get("/doLogin",(req,res)=>{
console.log('执行登录');
res.send('执行登录');
});
put请求
浏览器无法浏览,需在postman软件浏览
// localhost:3000/editUser
app.put("/editUser",(req,res)=>{
console.log('修改用户');
res.send('修改用户');
});
delete请求
浏览器无法浏览,需在postman软件浏览
// localhost:3000/delete
app.delete("/delete",(req,res)=>{
console.log('删除用户');
res.send('删除用户');
});
二级路由
// http://localhost:3000/admin/user
app.get("/admin/user",(req,res)=>{
res.send('admin user');
});
动态路由
配置路由也要注意顺序,下方的/article/add路由会被上方的/article/:id路由拦截,
//http://localhost:3000/article/xxx xxx为任意字母
app.get("/article/:id",(req,res)=>{ //这个路由已经包括了下方的/article/add路由
var id = req.params['id'];
res.send('动态路由'+id); // 动态路由xxx
});
// 要匹配到这个,需要把这个移动到上面的之前
app.get("/article/add",(req,res)=>{ // 匹配到了上面的/article/:id,该/article/add不会匹配
res.send('article add'); // 动态路由xxx
});
更好两个路由顺序可以访问/article/add路由,代码如下
app.get("/article/add",(req,res)=>{
res.send('article add'); // article add
});
app.get("/article/:id",(req,res)=>{
var id = req.params['id'];
res.send('动态路由'+id); // 动态路由xxx
});
get 传值
// localhost:3000/product?id=123&cid=123
app.get("/product",(req,res)=>{
let query = req.query; // 获取传值
console.log(query); // {id:'123',cid:'123'}
res.send('product '+query.id); // product 123
});
const express = require('express')
const app=express()
// get请求,浏览器浏览localhost:3000
// 配置路由
app.get("/",(req,res)=>{
res.send('你好 express')
});
// get请求,浏览器浏览localhost:3000/article
app.get("/article",(req,res)=>{
res.send('新闻页面')
});
app.get("/login",(req,res)=>{
res.send('登入')
});
app.get("/register",(req,res)=>{
res.send('注册页面')
});
app.post("/doLogin",(req,res)=>{ // post
console.log('执行登入');
res.send('执行页面');
});
app.put("/editUser",(req,res)=>{ // put
console.log('修改用户');
res.send('修改用户');
});
app.delete("/delete",(req,res)=>{ // delete
console.log('删除用户');
res.send('删除用户');
});
// 二级路由
app.get("/admin/user",(req,res)=>{
res.send('admin user');
});
// 动态路由 配置路由也要注意顺序
app.get("/article/:id",(req,res)=>{ //http://localhost:3000/article/xxx xxx为任意字母,这个路由已经包括了下方的/article/add路由
var id = req.params['id'];
res.send('动态路由'+id); // 动态路由xxx
});
// 要匹配到这个,需要把这个移动到上面的之前
app.get("/article/add",(req,res)=>{ // 匹配到了上面的/article/:id,该/article/add不会匹配
res.send('article add'); // 动态路由xxx
});
// get 传值 http://localhost:3000/product?id=123&cid=123
app.get("/product",(req,res)=>{
let query = req.query; // 获取传值
console.log(query); // {id:'123',cid:'123'}
res.send('product '+query.id); // product 123
});
app.listen(3000,()=>{
console.log('已启动');
});
mongoDB数据库
事务:做一个业务操作,有n个步骤,是一个整体:所有的步骤要么全部成功,要么全部失败。
账户表:账号 余额
记录表:账号 操作日期 操作类型
存款操作:
1.在记录表上新增一条存款记录
2.修改账户表对应账号的余额
文件型数据库:
优点:读写数据的效果比较高
缺点:不能很好的处理事件性较强的数据
安装MongoDB,下载community社区版,下载compass(图形化管理工具)
mongodb.com/try/download/community
启动mongodb数据库:
mongodb数据库也是以服务的形式存在于windows操作系统中
法一:win+R进入cmd,输入net start mongodb
法二:打开我的电脑,右击此电脑,选择管理,弹出计算机管理对话框,点击服务和应用程序下的服务,选择MongoDB server,右击后选择菜单中的启动
MongoDB中间件
nodejs平台上提供的访问MongoDB的API
访问数据库步骤:
创建案例代码:
1.创建文件夹,从项目文件中进入cmd,
2.使用express-generator脚手架生成项目代码框架
3.安装中间件:
npm install
//安装配置文件中的依赖安装依赖的中间件
npm i mongoose -S
// 安装mongoose中间件
4.在项目中新建文件夹—model,
1.连接数据库
let mongoose = require(‘mongoose’);
mongoose.connect(‘连接字符串’,参数);
连接字符串:协议://主机/数据库名mongodb://localhost:27017//dbname
异步方法在es6的语法中:异步方法名(实参).then(成功执行回调函数):异步方法名(实参).catch(失败执行回调函数);