1.Node.js官网地址:https://nodejs.org/en/
中文网站:http://nodejs.cn/api/
2.Node是一个构建Chrome V8引擎之上的一个Javascript 运行环境
是
一个运行环境
,作用是让js拥有开发服务端的功能3…Node中的NPM
是世界上最大的开源库生态系统(类似于github)
1.确认电脑是否安装Node环境
打开终端,输入 node -v
,如果能看到版本号则说明当前电脑已经安装Node环境,如果提示Node不是内部或外部命令
,则表示未安装
一旦安装了node,则会自动一并安装`npm[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f3tyT12I-1599793552966)(C:/Users/86188/AppData/Roaming/Typora/typora-user-images/1599028279378.png)]
/*
学习目标: 了解let与const声明变量特点
ES6学习技巧:对比法
学习路线:
1. 介绍ES5声明变量var特点
* a. 有变量提升--->编译器会将var声明提升到当前作业与最顶端
* b. 没有块级作用域 (块级作用域:大括号里面的变量都是局部的)
2. 介绍ES6声明变量let与const特点
* a. 没有变量提升 : 一定要先声明后使用
* b. 有块级作用域 : 只要是大括号里面声明的变量,都是局部
3. 介绍let与const区别
* a. let :变量。 可以重新赋值
* b. const :常量。 不可以重新赋值,只能在声明的时候唯一赋值一次
*/
/* 1.介绍ES5声明变量var特点 */
// 1.1 有变量提升
// var num; 编译器会将var声明提升到当前作用域最顶端
console.log(num);
var num = 10;
// 1.2 没有块级作用域 (块级作用域:大括号里面的变量都是局部的)
if(1){
// var在大括号里面声明的还是全局的
var num = 20;
}
console.log(num);
/* 2.介绍ES6声明变量let与const特点 */
// 2.1 没有变量提升
// console.log(num1);
// let num1 = 10;
// 2.2 有块级作用域
if(1){
let num2 = 20;
console.log(num2);
}
// console.log(num2);
/* 3.介绍let与const区别 */
// 3.1 let :变量(可以重新赋值) 和var一样
let a = 10;
console.log(a);
a = 100;
console.log(a);
// 3.2 const : 常量(不可重新赋值) 只能声明的时候赋值一次
const b = 800;
console.log(b);
/*
1.学习目标: 对象的解构赋值
解构赋值 : 变量赋值的简写形式
2.对比法学习
2.1 取出对象的属性 赋值给 变量
let {name,age,sex} = obj;
2.2 取出变量的值 赋值给 对象的属性
let obj = {name,age,sex}
2.3 解构赋值语法默认值
let {name,age=18,sex} = obj;
*/
/* 1. 取出对象的属性 赋值给 变量 */
//1.1 复习 以前ES5写法
let obj = {
name:'张三',
age:20,
sex:'男'
};
// let name = obj.name
// let age = obj.age
// let sex = obj.sex
console.log(name,age,sex);
// 1.1 复习 一起ES6写法
let obj1 = {
name:'张三',
age:20,
sex:'男'
};
// let name = obj.name
// let age = obj.age
// let sex = obj.sex
let {
age,name,sex} = obj1
console.log(name,age,sex);
/* 2.2 取出变量的值 赋值给 对象的属性 */
let name = '李四';
let age = 22;
let sex = '女';
// ES5 写法
let obj2 = {
name:name,
age:age,
sex:sex
}
console.log(obj2);
// ES6 写法
let obj = {
name, // === name:name
age,
sex,
satHi:function(){
console.log(11111);},
eat(){
// === eat:function(){}
console.log(22222);
}
}
console.log(obj2);
//3 解构赋值语法默认值
let obj3 = {
name:'王五',
sex:'男',
age:0
};
// let name = obj.name;
// let sex = obj.sex;
/*
(1)声明变量 let age
(2)检查obj有没有属性要age,有则赋值。没有则赋默认值
if(obj.age != undefined) {
age = obj.age
} else {
age = 18
}
*/
let {
name,sex,age} = obj3;
console.log(name,sex,age);
/* 数组解构赋值 */
let arr = [10,20,30]
/* 解构数组 */
// let n1 = arr[0]
// let n2 = arr[1]
// let n3 = arr[2]
// let n4 = arr[3]
let [n1,n2,n3,n4=100] =arr;
console.log(n1,n2,n3,n4);
/*
学习目标 :函数的结构赋值与函数默认参数
学习路线 :
1.复习函数传参本质: 实参给形参
2.函数解构赋值
3.函数默认参数
*/
// 1. 复习函数传参本质:实参给形参赋值
// ES5接收参数:let obj = {name:'张三',age:20}
// ES6接收参数:let{name,age,sex="男"} = {name:'张三',age:20}
// function fn ({name,age,sex="男"}){
// //ES5 :
// // console.log(obj);
// // let name = obj.name;
// // let age = obj.age;
// console.log(name,age,sex);
// }
// let preson = { name:'张三',age:20};
// fn(preson);
// 2.函数默认参数
function fn1(a=10,b=20){
// ES5 : 逻辑或短路
// a = a || 10;
// b = b || 20;
console.log(a,b);
}
fn1(100,200);
fn1();
fn1(5)
/*
1. 学习目标:箭头函数
*就是function函数的间歇形式
*(1)将function替换成箭头
*(2)将形参小括号移到箭头的=>的左边
* let fn = () => {}
2. 学习目标
2.1 一般用法
2.2 其他用法
* a. 如果函数只有一个形参,则可以省略形参小括号
* b. 如果函数只有一行,则可以省略函数体的大括号(此时必须要省略return
*/
// 1. ES5声明函数:function
// 无参无返回
let fn = ()=>{
console.log('5555');
}
fn();
// 有参有返回
let fn1 = (a,b)=>{
return a+b;
}
let res = fn1(10,20);
console.log(res);
// 2.其他用法
// 2.1 如果函数只有一个形参,则可以省略小括号
let fn2 = a=>{
return a*2};
let res2 = fn2(100);
console.log(res2);
// 2.2 如果函数体只有一行代码,则可以省略大括号(此时必须省略return)
let fn3 = a =>a*2;
let res3 =fn3(500);
console.log(res3);
/*
学习目标: 模板字符串
学习技巧: 对比法
1. 复习ES5学习的字符串特点:一切以 单引号 '' 或 双引号 "" 引起了的内容
1.1 不能字符串里面取变量的值:需要使用连接符
1.2 不能识别字符串格式 : 需要使用转义符
2. ES6新增 模板字符串:一切以反引号引起来的内容 ` `
2.1 可以去变量的值: ${变量名}
1.2 可以识别字符串格式
*/
// 1.复习ES5学习的字符串特点
// 1.1 不能在字符串中去变量的值 :只能使用字符串连接符 +
// 1.2 不能识别字符串本身格式 : 需要使用转义符
let name ="保健";
let str1 = '我爱\n'
+ name;
console.log(str1);
//2.ES6新增 模板字符串:一切以反引号引起来的内容 ` `
// 2.1 可以去变量的值:${变量名}
// 2.2 支持字符串格式
let name2 = '学生';
let str2 = `我爱
${
name2}`;
console.log(str2);
/*
1.拓展运算符(展开运算符) : ...
2.作用 :变量对象一种简写形式(类似于for-in循环)
3.应用场景:
a. 连接数组
b. 求最大/最小值
c. 一行代码实现数组去重
*/
// 1. 基本用法
let car = {
pinpai:'特斯拉',
price:888888
};
let hourse = {
address : '深圳湾一号'
}
let person = {
name: '维克多',
age:26,
...car,
...hourse
}
console.log(person);
// 2.应用场景
// 2.1 连接数组
let arr1 = [10,20,30]
let arr2 = [40,50,60]
// 之前:concat
let arr3 = arr1.concat(arr2); //连接arr1 和 arr2
arr3.push(70,80,90); //连接之后,继续添加元素
console.log(arr3);
// ES6展开运算符
let arr4 = [...arr1,...arr2,70,80,90];
console.log(arr4);
// 2.2 求数组最大值/最小值
let arr = [23,45,11,23,45,88,66,11,88,66];
// 之前:擂台思想、 Math.max.apply()
let max = Math.max.apply(Math,arr);
console.log(max);
// ES6展开运算符
let min = Math.min(...arr);
console.log(min);
/*
1.新增数据类型(集合): Set
* 与数组几乎一致,惟一的区别是不支持重复元素(相当于是无法存储重复元素)
*/
// 声明Set : new Set(数组)
let set = new Set([10,20,30,66,77,30,20,77,10])
console.log(set);
// set一般不会单独使用,只是为了去掉重复数组元素。将set转成数组
let arr =[...set];
console.log(arr);
// 应用场景:数组去重
let arr1 = [21,54,67,88,54,21,67];
// 最简单的一行代码实现数组去重
let newArr = [...new Set(arr1)];
console.log(newArr);
1.前端框架使用流程
*导包 (下载) :得到一个对象,存储框架中的API
*拥抱 : 调用对象方法
2.后端nodejs模块使用流程
*导包 :得到一个对象,存储框架中的API
*用包 :调用对象方法
fs.readFile('./data/c.txt','utf-8',(err,data)=>{
if(err){
console.log(err);
// 抛出异常,throw的作用就是让node程勋终止运行,方便调试
throw err;
}else{
console.log(data);
}
})
console.log('111');
//1. 导入模块
const fs = require('fs');
//2. 使用模块
/**
* @description: 写入文件
* @param {string} path : 文件路径
* @param {string} data : 要写入的数据
* @param {string} option : 文件编码 自动根据数据识别,一般不用传
* @param {function} callback : 写入回调 (err)=>{ err:错误信息 }
* @return:
*/
fs.writeFile('./data/b.txt','临渊羡鱼不如退而结网',err=>{
if( err ){
throw err;
}else{
console.log('写入成功');
}
});
/* 学习目标: 同步与异步区别
1. 编译器执行代码流程
1.1 从上往下解析代码
1.2 判断代码是同步还是异步
同步 :立即执行
异步 :不执行,放入一个事件队列池 (EventLoop)
1.3 当页面所有的同步执行完毕之后,才会执行事件队列池中的代码
2. 同步与异步区别
2.1 API不同 :异步有回调函数,同步一般没有
* 前端有两个API是异步 : 定时器 和 ajax
2.2 执行顺序不同 : 同步有序且优先执行, 异步是无序执行
2.3 性能不同 : 异步性能高(不阻塞线程),同步阻塞线程
*/
// nodejs中所有的api默认都是异步的,如果希望拥抱就会后面加上Sync即可
/*异步特点
1. 有回调函数
2. 无序执行
3. 不阻塞线程 : 性能高
*/
fs.readFile('./data/c.txt','utf8',(err,data)=>{
console.log('11111');
})
/* 同步特点
1. 没有回调
2. 有序
3. 阻塞线程:性能低
*/
let data = fs.readFileSync('./data/c.txt','utf8');
console.log('7');
//1.导入文件模块
const fs = require('fs');
//2.读取文件
/*a.注意点: node中的相对路径: ./ 不是相对于当前文件所在路径,而是相对于执行node命名的文件夹路径
在服务端开发中,一般不要使用相对路径,而使用绝对路径
b.解决方案:在nodejs中,每一个js文件都有两个全局属性,它可以帮助我们获取到文件的绝对路径
__filename:当前js文件所在目录的绝对路径
__dirname:当前js文件的绝对路径
*/
console.log(_dirname);
console.log(_filename);
/* 2.如果想要获取当前文件夹下其他文件绝对路径,可以使用 __dirname属性来拼接 */
var path = __dirname + '/aaa.txt';
console.log(path);
fs.readFile(path,'utf-8',(err,data)=>{
if(err){
console.log(err);
//抛出异常,throw的作用就是让node程序终止运行,方便调试
throw err;
}else{
console.log(data);
};
});
/*
1. 前端相对路径 ./ 与nodejs后端 相对路径 ./ 区别
1.1 前端相对路径 ./ : 相对于当前文件 所在的文件夹 (固定的)
1.2 nodejs相对路径 ./ : 相对于 执行node命令 所在的文件夹 (不固定)
2. nodejs中文件路径一般不适应相对路径,使用绝对路径
* 在node中,每一个js文件都有两个默认的全局变量
* __dirname :当前js文件所在的文件夹绝对路径
* __filename : 当前js文件本身的绝对路径
3. path模块作用: 拼接文件路径
作用和自己拼接差不多,但是容错率更高
* 自动识别当前操作系统的磁盘分隔符,会自动添加
* 接错功能 :如果磁盘疯符写错了,path模块会自动纠正
*/
//1.导入模块
//(1)参数: 模块路径 (2)返回值: 对象 , 存储模块所有的api
const fs = require('fs');
//2.使用模块
fs.readFile( aPath ,'utf-8',function(err,data){
if(err)throw err;
console.log(data);
});
//1.导入模块
const http = require('http');
//2.创建服务器
let server = http.createServer((req,res)=>{
//req : 请求对象。 负责获取客户端的请求信息 res : 响应对象。 负责响应客户端数据的
console.log(req.url);
//了解即可: url中的中文会被进行urlencode转码
console.log(decodeURI(req.url));
});
//3.开启服务器
server.listen(3000,()=>{
console.log('服务器开启成功');
});
/* nodejs搭建静态资源服务器
1. 浏览器中所有的外部资源路径,都会变成网络请求
*/
// 1. 导入模块
const http = request('http');
const fs = require('fs');
const path = require('path');
//2.创建服务器
let server = http.createServer((req,res)=>{
// (1)请求:req
console.log(req.url);
// (2)处理
if (req.url == '/') {
// 读取html文件响应返回
fs.readFile(path.join(__dirname,'www','index.html'),'utf8',(err,data)=>{
if(err) throw err;
// (3)响应:res
res.end(data);
});
}else if (req.url == '/resource/css/index.css'){
fs.readFile( path.join(__dirname,'www','resource','css','index.css'),(err,data)=>{
if(err) throw err;
//(3)响应:res
res.end(data);
});
}else if( req.url == '/resource/images/01.gif'){
fs.readFile( path.join(__dirname,'www','resource','images','01.gif'),(err,data)=>{
if(err) throw err;
//(3)响应:res
res.end(data);
});
}else if( req.url == '/resource/images/01.jpg'){
fs.readFile( path.join(__dirname,'www','resource','images','01.jpg'),(err,data)=>{
if(err) throw err;
//(3)响应:res
res.end(data);
});
}else if( req.url == '/resource/video.mp4'){
fs.readFile( path.join(__dirname,'www','resource','video.mp4'),(err,data)=>{
if(err) throw err;
//(3)响应:res
res.end(data);
});
}else{
//错误路径
res.end('404 not found');
}
});
//3.开启服务器
server.listen(3000,()=>{
console.log('服务器开启成功');
});
/* nodejs搭建静态资源服务器
1. 浏览器中的所有外部资源路径,都会变成网络请求
2. 一般静态资源(css文件,图片,音视频)使用 url路径拼接的方式来处理
*/
//1.导入模块
const http = require('http');
const fs = require('fs');
const path = require('path');
//2.创建服务器
let server = http.createServer((req,res)=>{
// (1)请求:red
console.log(req.url);
// (2)处理
if( req.url == '/' ){
//读取html文件响应返回
fs.readFile( path.join(__dirname,'www','index.html'),(err,data)=>{
if(err) throw err;
//(3)响应:res
res.end(data);
});
}else if( req.url.indexOf('/resource') == 0 ){
fs.readFile( path.join(__dirname,'www',req.url),(err,data)=>{
if(err) throw err;
//(3)响应:res
res.end(data);
});
}else{
//错误路径
res.end('404 not found');
}
});
//3.开启服务器
server.listen(3000,()=>{
console.log('服务器开启成功');
});
/*
学习目标:nodejs接受get请求参数
1. 前端发送get请求:直接在url后面拼接 url?key1=value&key2=val2
2. nodejs接受get请求参数
2.1 导入url模块
2.2 调用parse()方法解析参数: url.parse( req.url,true)
2.3 获取解析好的query属性: get参数
*/
//1.导入模块
const http = require('http');
const url = require('url');
//2.创建服务器
let server = http.createServer((req,res)=>{
// (1)get请求采纳数直接在url后面拼接
console.log(req.url);
// (2)get参数解析原理是 字符串切割
// 第一个参数:要切割的url字符串
// 第二个参数:布尔类型 默认false:query不处理 true:query处理成对象
let obj = url.parse(req.url,true);
console.log(obj);
let {
query} = obj;
let query = obj.query
console.log(query);
// 响应返回参数:告诉客户端解析成功 (js对象需要转json对象才可以响应返回)
res.end(JSON.stringify(query));
});
//3.开启服务器
server.listen(3000,()=>{
console.log('服务器开启成功');
});
/*
学习目标:nodejs接受post请求参数
1. 前端发送post
1.1 需要设置请求头
1.2 请求头中发送: xhr.send(key=value)
2. nodejs接受post参数
2.1 给red注册data事件 (接收数据包)
2.2 给red注册end事件 (数据包接受完毕)
2.3 在end方法中使用querystring模块解析body
*/
// 1. 导入模块
//1.导入模块
const http = require('http');
// 解析get请求参数
const url = require('url');
// 解析post请求参数
const querystring = require('querystring');
//2.创建服务器
let server = http.createServer((req,res)=>{
console.log(req.url);
/* (1)给req注册data事件
客户点每发送一个数据包,这个事件就会车发一次 (触发多次)
*/
let postData = '';
req.on('data',function (chunk){
postData += chunk;
})
/* (2)给req注册end事件
客户端每一次post所有的数据包发送完毕会执行一次
*/
req.on('end',function (){
/* (3)处置post参数:使用querystring模块切割 请求体 */
console.log(postData);
let body = querystring.parse(postData);
console.log(body);
// 响应给客户端
res.end(JSON.stringify(body))
})
});
//3.开启服务器
server.listen(3000,()=>{
console.log('服务器开启成功');
});
get与post区别
jquery的插件
一样,由于jquery库自身的功能无法满足开发需求,所以通过插件来拓展功能/*学习目标: express响应客户端数据
(1)响应普通文本 : res.send('字符串')
(2)响应json对象 : res.send( js对象 )
(3)响应html文件 : res.sendFile( 文件绝对路径 )
(1)express框架本质不是修改原生代码,而是在原生的基础上添加方法 (给req和res原型添加成员)
(2)在express中你可以使用一切node原生语法
*/
//1.导入模块----相当于http
const express = require('express');
//2.创建服务器
let app = express();
//3.路由(接口文档) : 一个请求对应一个函数
app.get('/',(req,res)=>{
//响应普通文本
//原生node语法
// res.end('这是首页');
//express语法
res.send('这是首页');
});
app.get('/login',(req,res)=>{
//响应json : 底层会自动将js对象转成json格式字符串
res.send({
name:'班长',
age:40
});
});
app.get('/list',(req,res)=>{
//响应html文件: 文件绝对路径
res.sendFile( `${
__dirname}/list.html`);
});
app.use((req,res)=>{
//自定义404处理结果
res.end('404');
})
//4.开启服务器
app.listen(3000,()=>{
console.log('服务器开启成功');
});
//1.导入模块
const express = require('express');
//2.创建服务器
let app = express();
//3.托管静态资源
/*
(1)如果请求路径为/ , express会自动读取www下面index.html响应返回
(2)如果请求路径是以www中文件夹开头,express会自动根据url拼接路径返回
*/
app.use(express.static('www'));
//4.写路由(接口文档)
//5.开启服务器
app.listen(3000,()=>{
console.log('服务器开启成功');
})
//1.导入模块
const express = require('express');
//2.创建服务器
let app = express();
//3.托管静态资源
app.use(express.static('www'));
//4.配置中间件(jq的插件) : 本质都是给req或者res原型添加成员
//4.1 body-parser中间件 : 解析post参数
//(1)导入中间件
const bodyParser = require('body-parser');
//(2)使用中间件 : 给req添加body属性,存储解析好的post参数
app.use(bodyParser.urlencoded({
extended: false }));
//5.写路由(接口文档)
/*接收get请求参数
req.query
*/
app.get('/hero/list',(req,res)=>{
console.log( req.url );
//获取get请求参数 : express会自动帮我们解析get参数并且添加到req的原型query属性中
console.log( req.query );
res.send( req.query )
});
/*接收post请求参数
(1)使用body-parser插件
(2)req.body
*/
app.post('/hero/add',(req,res)=>{
console.log( req.url );
console.log( req.body );
res.send( req.body )
});
//6.开启服务器
app.listen(3000,()=>{
console.log('服务器开启成功');
})
适合所有第三方模块
/*
第三方模块使用流程
1. 初始化项目 : npm init -y
*** 注意点:文件夹不能有中文
* 生成 package.json文件 : 记录整个项目使用了那些第三方模块以及对应的版本号
2. 装包(下载): npm install 模块名
* 生成 package-lock.json文件 :记录每一个包的下载地址
* 提高下一次更新速度,类似于浏览器收藏夹功能
* 生成node_modules文件夹 : 第三方模块资源文件
* 类似于前端的libs,专门存放第三方模块资源的
3. 用包 : 官网文档CV
*/
//1.导入爬虫模块
var Crawler = require("crawler");
//2.创建爬虫对象
var c = new Crawler({
maxConnections : 10,
// This will be called for each crawled page
callback : function (error, res, done) {
if(error){
console.log(error);
}else{
//爬虫成功回调
//将爬取到的网页DOM树赋值给jq的$ (目的:使用jq的语法来操作DOM树)
var $ = res.$;
// $ is Cheerio by default
//a lean implementation of core jQuery designed specifically for the server
// console.log($("html").text());
// console.log( $('#jSearchHeroDiv>li').html() );
console.log( $('html').text() );
}
done();
}
});
//3.开始爬虫
// Queue just one URL, with default callback
c.queue('https://mc.163.com/index.html');
ar Crawler = require("crawler");
var fs = require('fs');
var c = new Crawler({
encoding:null,
jQuery:false,// set false to suppress warning message.
callback:function(err, res, done){
if(err){
console.error(err.stack);
}else{
//将爬取好的文件通过fs模块写入文件
fs.createWriteStream(res.options.filename).write(res.body);
}
done();
}
});
//绝大多数网站,都有反爬机制。只有小众网站没有
//浏览器可以下载,但是服务端爬虫无效。反爬:检测你这个请求是通过浏览器发出来,还是服务端(解决方案:让服务端伪装成浏览器来发这个请求)
c.queue({
url:"http://upos-hz-mirrorks3u.acgvideo.com/upgcxcode/75/11/112251175/112251175-1-6.mp4?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfq99M=&uipk=5&nbs=1&deadline=1571396695&gen=playurl&os=ks3u&oi=2005998532&trid=a4c624adafe64ababb2a851334eaf87eh&platform=html5&upsig=2a29cd105837278e3b4c92181fe3eb59&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=0",
filename:"./video/11111.mp4",//写入文件名 默认在根目录
headers:{
'User-Agent': 'requests'}//让服务端伪装成客户端
});
node指令 | 作用 |
---|---|
npm init -y | 初始化 |
npm i express | 搭建nodejs服务器 |
npm i body-parser | 解析post请求 |
nodemon + 当前文件名 | 自动刷新 |
npm i xpress-fileupload | 处理文件上传 |
npm i mysql-ithm | 操作mysql数据库 |
npm i xpress-fileupload
npm i xpress-fileupload
const* fileUpload = require('express-fileupload');
app.use(fileUpload());
npm init -y
npm i express
npm i body-parser
app.use(express.static('www'));
1.跨域 :是一个固定格式报错。(没有之一)
2.什么是跨域?
window.location.href
3.同源策略 :协议 和 id 和 端口号 一致
4.浏览器同源策略存在的理由
5.如何解决跨域限制
第一种 :CORS
目前的主流方案,也是最简单的方案
简单快捷,后台只需一行代码,跟前端没有任何关系
第二种:JSONP
面试专用,前端需要写代码
工作原理: 服务器 在返回响应报文的时候,在响应头中 设置一个允许的header
res.setHeader('Access-Control-Allow-Origin', '*');
app.use((req, res, next) => {
//任何请求都会进入这个use中间件
res.setHeader('Access-Control-Allow-Origin', '*')//设置响应头
next()//执行下一个中间件
})
express有一个自带的中间件cors,它的作用是自动给每一个res设置默认请求头
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ef59Tn3S-1599793552994)(Nodejs课程笔记/day04.assets/1571858796482.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XqgEG2b7-1599793553004)(Nodejs课程笔记/day04.assets/1571858867308.png)]今日易错点:
新增数据 用法
**insert into 表名(字段名) value(值)**
删除数据
delete from 表名
查询数据
select 字段 from 表名
查询所有字段
select * from 表名
修改数据
update 表名 set 字段 = 新值
指定条件修改
update student set name = “黑马一哥’ where id = 3
%为通配符,一般搭配like关键字使用
查询所有字段以关键字开头的数据
select * from 表名 where 字段 like 关键字%
查询所有字段以关键字结尾的数据
select * from 表名 where 字段 like %关键字
查询所有字段包含关键字的数据
select * from 表名 where 字段 like %关键字%
使用or关键字
-- 找到student表中age小于10,或者age大于100的数据
select *from student where age < 10 or age > 100;
今日易错点
注意点:
编辑按钮:使用window.location.href给编辑页面传id
window.location.href='./update.html?id={ { v.id }}'
删除按钮:
<!-- 模板引擎一 :英雄列表 -->
<script id="hero_list" type="text/html">
{
{
each heros v }}
<tr>
<td> {
{
v.name }} </td>
<td> <img src="{
{ v.skill }}" width="100px" height="100px"> </td>
<td><img src="{
{ v.icon }}" width="72px" height="72px"></td>
<td class="manager">
<button class="btn btn-success" onclick="location.href='./update.html?id={
{ v.id }}'">编辑</button>
<button id={
{
v.id }} class="btn btn-danger">删除</button>
</td>
</tr>
{
{
/each }}
</script>
<script>
// 入口函数 : 等页面加载完毕后执行
$(function () {
/* 查询英雄详情 */
$('#searchBtn').click(function (e) {
e.preventDefault();
$.ajax({
url: 'http://127.0.0.1:3000/hero/list',
type: 'get',
dataType: 'json',
data: {
search: $('#search').val() },
success: function (backData) {
$('#heroListBody').html(template('hero_list', backData))
}
});
})
/* ajax查询列表 */
$('#searchBtn').click();
/* 删除英雄 */
$('tbody').on('click', '.btn-danger', function () {
$.ajax({
url: 'http://127.0.0.1:3000/hero/delete',
type: 'post',
dataType: 'json',
data: {
id: $(this).attr('id') },
success: function (backData) {
if (backData.code == 200) {
alert('删除成功');
window.location.reload();
} else {
alert(backData.msg);
}
}
});
})
})
</script>
<script>
// 入口函数
$(function(){
/* 1. 获取上个页面的信息 */
let id = window.location.href.split('=')[1];
console.log(id);
/* 2. 查询英雄详情 */
$.ajax({
url:'http://127.0.0.1:3000/hero/info',
type:'get',
dataType:'json',
data:{
id},
success: function(backData){
console.log(backData);
$('#name').val(backData.data.name);
$('#skill').val(backData.data.skill);
$('#iconImg').attr('src',backData.data.icon);
console.log(backData.data.icon);
}
});
/* 2. ajax发送请求 */
//1.给file表单元素注册onchange事件
$('#icon').change(function () {
//1.2 获取用户选择的图片
let file = this.files[0];
//1.3 将文件转为src路径
let url = URL.createObjectURL(file);
//1.4 将url路径赋值给img标签的src
$('#iconImg').attr('src', url);
});
/* 3. 文件上传 */
$('.btn-success').on('click',function(e){
//禁用表单默认提交事件
e.preventDefault();
//创建FormData对象:参数是表单dom对象
let fd = new FormData($('form')[0])
fd.append('id',id)
$.ajax({
url:'http://127.0.0.1:3000/hero/update',
type:'post',
dataType:'json',
data:fd,
contentType: false,
processData: false,
success: function(backData){
console.log(backData);
if (backData.code == 200) {
alert('编辑成功');
window.location.href = './index.html'
}else{
alert('编辑失败');
}
}
});
});
})
</script>
<script>
// 入口函数
$(function(){
/* 2. ajax发送请求 */
//1.给file表单元素注册onchange事件
$('#icon').change(function () {
//1.2 获取用户选择的图片
let file = this.files[0];
//1.3 将文件转为src路径
let url = URL.createObjectURL(file);
//1.4 将url路径赋值给img标签的src
$('#iconImg').attr('src', url);
});
/* 3. 文件上传 */
$('.btn-insert').on('click',function(e){
//禁用表单默认提交事件
e.preventDefault();
//创建FormData对象:参数是表单dom对象
let fd = new FormData($('form')[0])
$.ajax({
url:'http://127.0.0.1:3000/hero/add',
type:'post',
dataType:'json',
data:fd,
contentType: false,
processData: false,
success: function(backData){
console.log(backData);
if (backData.code == 200) {
alert('新增成功');
window.location.href = './index.html'
}else{
alert('新增失败');
}
}
});
});
})
</script>
图片文件
与对应的 验证码文本
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yZIr1AcW-1599793553007)(课程资料/上课资料–imgs/验证码node安装与使用.png)]
验证码工作流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vDe9HOgC-1599793553009)(课程资料/上课资料–imgs/验证码工作流程.png)]
/* svg 验证码模块 */
const svgCaptcha = require('svg-captcha');
let captchaText = ''; // 声明全局变量存储验证码文本
/* 5.6 验证码 */
app.get('/captcha', (req, res) => {
// 1.请求
console.log(req.url);
// 2.1 生成图片 + 文本
var captcha = svgCaptcha.create({
size: 4,
noise: 2,
color: true,
// background:'#d1c'
});
// 2.2 文本 :服务器自己存起来 (答案)
captchaText = captcha.text;
// 2.3 图片:响应返回浏览器
res.type('svg');
res.status(200).send(captcha.data);
})
<img class="code" src="http://127.0.0.1:3000/captcha" alt="">
<script src="./libs/md5.min.js">script>
$(form表单).serialize()
与 new FormData(form表单区别)
ES6教程传送门:http://es6.ruanyifeng.com/#docs/promise
Promise 是一个构造函数
,用于创建Promise对象
Promise作用:解决回调地狱
/* 为什么要学Promise?
1.Promise作用 :解决回调地狱问题
回调地狱 :异步回调 层层嵌套
*/
// 需求: 一次读取文件 a.txt , b.txt , c.txt , d.txt 这三个文件内容
cons fs = require('fs');
// (1)不能直接按照顺序写,因为异步操作是无序的
// (2)解决方案 :在回调函数中嵌套执行
// 弊端 :形参回调地狱(异步回调 层层嵌套,麻烦不方便维护)
//读取文件a
fs.readFile('/data/a.txt','utf8',(err,data)=>{
if(err){
throw err;
}else{
console.log(data);
//读取文件b
fs.readFile('/data/b.txt','utf8',(err,data)=>{
if(err){
throw err;
}else{
console.log(data)
//读取文件c
fs.readFile('/data/c.txt','utf8',(err,data)=>{
if(err){
throw err;
}else{
console.log(data);
//读取文件d
fs.readFile('/data/d.txt','utf8',(err,data)=>{
if(err){
throw err;
}else{
console.log(data)
}
})
}
})
}
})
}
})
使用流程 Promise是一个后遭函数,用于创建promise实例
let p = new Promise((resolve,reject)=>{ //异步操作 })
p.then(data=>{ //处理成功数据 },err=>{ //处理失败数据 })
/*
1.Promise是一个构造函数,返回一个Promise对象
2.使用流程
(1)实例化Promise对象 :将异步操作放入Promise中
(2)调用then()方法:处理异步操作结果
*/
const fs = require('fs');
/*
参数 :回调函数(resolve,reject)=>{ //异步操作 }
resolve : 完成回调
reject :失败回调
*/
let p = new Promise( (resolve,reject)=>{
//异步操作:读取文件a
fs.readFile(`${
__dirname}/data/a.txt`,'utf8',(err,data)=>{
if(!err){
//成功
// (1)resolve: 执行then方法里面的第一个函数
reslove(data);
}else{
// 失败
// (2)reject: 执行then方法里的第二个函数
reject(err);
}
})
} )
//调用promise实例的then方法
//第一个参数:成功的回调
//第二个参数:失败的回调
p.then(data=>{
console.log(data);
},err=>{
console.log(err)
})
promise本质不是修改异步的顺序(异步永远是无序的),而是通过控制异步结果的顺序,从而实现异步代码有序执行
/*
1.Promise注意点及原理:
1.1 Promise对象有三种状态
* pending(进行中)
* fulfilled(已成功)
* rejected(已失败)
1.2 Promise状态改变只有两种情况
* 从pending(进行中)变为fulfilled(成功)
* 从pending(进行中)变为rejected(失败)
1.3 注意 :Promise对象在创建的时候,里面的异步就会立即执行
***** 不要在创建promise的时候回处理异步结果,应该调用resolve()或reject()交给then()方法来处理
1.4 promise解决回调地狱 :在上一个promise的then方法中返回下一个promise实例对象
1.5 坤哥个人总结 :promise本质不是修改异步的顺序(异步永远是无序的),而是通过控制异步结果的顺序,从而实现异步代码有序执行
*/
const fs = require('fs');
//(1)创建三个异步操作 promise
//读取文件a
let p1 = new Promise((resolve,reject)=>{
// 读文件
fs.readFile('./data/a.txt','utf8',(err,data)=>{
if(!err){
// 成功
resolve(data);
}else{
// 失败
reject(err);
}
})
})
let p2 = new Promise((resolve,reject)=>{
if(!err){
// 成功
resolve(data);
}else{
// 失败
reject(err);
}
})
let p3 = new Promise((resolve, reject) => {
//异步操作: 读取文件a
fs.readFile(`${
__dirname}/data/c.txt`, 'utf8', (err, data) => {
if (!err) {
//成功
resolve(data);
} else {
//失败
reject(err);
}
});
});
let p4 = new Promise((resolve, reject) => {
//异步操作: 读取文件a
fs.readFile(`${
__dirname}/data/d.txt`, 'utf8', (err, data) => {
if (!err) {
//成功
resolve(data);
} else {
//失败
reject(err);
}
});
});
//(2)调用promise实例的then方法
//第一个参数:成功的回调
//第二个参数:失败的回调
p1.then(data=>{
console.log(data);
return p2; //在第一个promise的then方法中返回第二个promise对象
})
.then(data=>{
//p2的then
console.log(data);
return p3;
})
.then(data=>{
console.loh(data);
return p4;
})
.then(data=>{
console.log(data);
})
const fs = require('fs);
//1.封装一个函数 :根据文件名生成 文件读取的promise
function createPromise(filename){
return new Promise((resolve,reject)=>{
fs.readFile(`${
__dirname}/data/${
filename}.txt`,'utf8',(err,data)=>{
if(!err){
resolve(data);
}else{
reject(err);
}
})
})
}
let p1 = createPromise('a')
let p2 = createPromise('b')
let p3 = createPromise('c')
let p4 = createPromise('d')
//2.解决希求:先读a,读完a后读b,一次读取
p1.then(data=>{
console.log(data);
return p2;
})
.then(data=>{
console.log(data);
return p3;
})
.then(data=>{
console.log(data)
return p3;
})
.then(data=>{
console.log(data)
})
catch() : 捕捉then方法中的错误err
const fs = require("fs");
/* promise实例对象的catch方法: 用于捕获异步操作的错误信息 */
//1.封装一个函数 :根据文件名生成 文件读取的promise
function createPromise(filename){
return new Promise((resolve,reject)=>{
fs.readFile(`${
__dirname}/data/${
filename}.txt`,'utf8',(err,data)=>{
if(!err){
resolve(data);
}else{
reject(err);
}
})
})
}
//2.解决需求:要先读a,读完a后读b
p1.then(data=>{
console.log(data);
return p2;
})
.then(data=>{
console.log(data);
return p3;
})
.then(data=>{
console.log(data)
return p3;
})
.then(data=>{
console.log(data)
})
.catch(err=>{
//catch :上面任何一个then出错了都会进入这个方法
console.log(err);
})
all() : 将多个promise对象放入数组中合并成一个promise
const fs = require('fs');
//Promise是一个构造函数,用于创建promise实例
//封装一个创建promise的函数
function createPromise(filename){
return new Promise((resolve,reject)=>{
fs.readFile(`${
__dirname}/data/${
filename}.txt`, 'utf8', (err, data) => {
if (!err) {
//成功
resolve(data);
} else {
//失败
reject(err);
}
});
});
};
let p1 = createPromise('a');
let p2 = createPromise('b');
let p3 = createPromise('c');
let p4 = createPromise('d');
// Promise.all([p1,p2,p3,p4]) : 多个promise合成一个
let pArr = Promise.all([p1,p2,p3,p4])
// (2)调用promise实例的then方法
pArr.then(data=>{
//执行时机:pAll中所有的promise全部都完成才会执行then
// data : 数组。 数组中每一个元素就是每一个promise的结果
console.log(data)
})
race() : 将多个Promise合并成一个Promise
const fs = require('fs');
// Promise是一个构造函数,用于创建promise实例
// 封装一个创建promise的函数
function createPromise(filename){
return new Promise((resolve,reject)=>{
fs.readFile(`${
__dirname}/data/${
filename}.txt`, 'utf8', (err, data) => {
if (!err) {
//成功
resolve(data);
} else {
//失败
reject(err);
}
});
});
};
let p1 = createPromise('a');
let p2 = createPromise('b');
let p3 = createPromise('c');
let p4 = createPromise('d');
//Promise.all([p1,p2,p3,p4]) : 多个promise合成一个
let pArr = Promise.race([p1,p2,p3,p4]);
//(2)调用promise实例的then方法
pArr.then(data =>{
//执行时机 : pAll中任何一个promise完成就会执行then
//data : 每一个执行的promise的结果
console.log(data)
})
箭头函数
中没有this:这意味着 call() apply() bind()无法修改箭头函数中的this
箭头函数中的this指向:访问上一个作用域的this
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<body>
<script>
/* ES6箭头函数中的this
(1)箭头函数中没有this :这意味着call() apply() bind() 无法修改箭头函数中的this
(2)箭头函数中的this指向 :访问上一个作用域的this
2.学习路线 : 对比法
2.1 function函数中的this : 谁 ‘调用’ 我, 我就指向谁
* 跟你怎么声明没关系,取决于调用 (变化的)
普通函数 : this指向window
对象方法 : this指向对象
构造函数 : this指向new创建的对象
2.2 箭头函数中的this : 谁 '声明' 我,我就指向谁
* 跟你怎么调用没关系,取决于声明 (不变的)
*/
// 1.全局函数:window
let fn = () =>{
console.log(this);
}
fn();//window
fn.call({
a:11 });//window 箭头函数中的this无法修改,因为箭头函数没有this
// 2. 对象方法:window (因为对象无法开辟作用域,obj所在作用域还是window)
let obj ={
sayHi:()=>{
console.log('学习使我快乐')
console.log(this);
}
};
obj.sayHi();//window
// 3.局部函数
var person ={
play:function(){
console.log('paly中的this');
console.log(this);//person
//在局部作用域声明一个箭头函数
let fn2 = () =>{
console.log('fn2在一级链中被声明,我的this就是一级链的this')
console.log(this);//person
}
fn2();
}
};
person.paly();
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<script>
/*
二维数组 :数组每一个元素都是一个数组
*/
let arr = [['a','b','c'],['d','e','f'],['g','h','i']];
console.log(arr);
// 降维
// 方式一:数组的concat()拼接数组
// let newArr = [];
// for(let i = 0;i < arr.length;i++) {
// newArr = newArr.concat(arr[i]);
// };
// console.log(newArr);
// 方式二:使用ES6的拓展运算符
let newArr = [];
for(let i = 0;i < arr.length;i++) {
newArr.push(...arr[i]);
};
console.log(newArr);
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<body>
<script>
/*
升维 :一维数组生成二维
*/
let arr = [
{
type: '电子产品',
name: 'iPhone',
price: 8888
},
{
type: '家具',
name: '桌子',
price: 100
},
{
type: '食品',
name: '瓜子',
price: 10
},
{
type: '家具',
name: '椅子',
price: 380
}, {
type: '电子产品',
name: '小米手机',
price: 1380
}, {
type: '食品',
name: '辣条',
price: 5
}, {
type: '食品',
name: '咖啡',
price: 50
}
];
let newArr = []; //升维之后的数组
let obj = {}; //记录一维数组种类
for(let i = 0; i