前端知识
Posted Ronin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端知识相关的知识,希望对你有一定的参考价值。
Day01
练习:查询出工资在7000以上的男员工的姓名,性别,生日,工资这几个列,显示工资最高的前3个人。
select ename,sex,birthday,salary from emp
where salary>7000 && sex=1
order by salary desc
limit 0,3;
1.复杂查询
(1)聚合查询/分组查询
示例:查询出所有员工的数量
select count(*) from emp;
练习:通过员工的编号列查询出所有员工的数量
select count(eid) from emp; #推荐使用主键列
练习:通过所属部门编号列查询出所有员工的数量
select count(deptId) from emp; #null无法统计在内
聚合函数
函数:是一个独立的功能体,需要提供若干个数据,返回处理的结果
count()/sum()/avg() /max() / min()
数量 总和 平均 最大 最小
练习:查询出所有男员工的工资总和
select sum(salary) from emp where sex=1;
练习:查询出10号部门的平均工资
select avg(salary) from emp where deptId=10;
练习:查询出工资最高的女员工的工资是多少
select max(salary) from emp where sex=0;
练习:查询出年龄最大的员工的生日是多少(生日最小)
select min(birthday) from emp;
分组查询:先按照指定的列分组,分组以后再进行聚合查询。
分组查询通常只能查询聚合函数和分组条件
示例:查询出男女员工的平均工资、最高工资、最低工资分别是多少
select avg(salary),max(salary),min(salary),sex from emp group by sex;
练习:查询各部门员工的最高工资,员工数量,平均工资
select max(salary),count(eid),avg(salary),deptId from emp group by deptId;
示例:获取日期中的年份部分 2021-6-4
select year(\'2021-6-4\');
练习:查询出所有员工出生的年份
select year(birthday) from emp;
练习:查询出1993年出生的员工有哪些
select * from emp where year(birthday)=1993;
md5加密函数
select md5(\'123456\');
year() 获取日期中的年份
md5() 对字符串进行加密
(2)子查询
是多个SQL命令的组合,把一个SQL命令的结果作为另一个SQL命令的条件
示例:查询出工资最高的员工
步骤1:查询出工资的最高值——22000
select max(salary) from emp;
步骤2:通过工资查询员工
select * from emp where salary=22000;
综合:
select * from emp where salary=(select max(salary) from emp);
练习:查询出比tom工资高的员工有哪些
步骤1:查询出tom的工资 —— 6000
select salary from emp where ename=\'tom\';
步骤2:查询出工资高于6000的员工有哪些
select * from emp where salary>6000;
综合:
select * from emp where salary>(select salary from emp where ename=\'tom\');
练习:查询出高于平均工资的男员工有哪些
步骤1:查询出平均工资 —— 8533.333333
select avg(salary) from emp;
步骤2:查询出高于平均的男员工
select * from emp where salary> 8533.333333 && sex=1;
综合:
select * from emp where salary>(select avg(salary) from emp) && sex=1;
练习:查询出和tom同一年出生的员工有哪些
步骤1:查询出tom的出生年份 —— 1990
select year(birthday) from emp where ename=\'tom\';
步骤2:查询出1990年出生的员工
select * from emp where year(birthday)=1990 && ename!=\'tom\';
综合:
select * from emp where year(birthday)=(select year(birthday) from emp where ename=\'tom\') && ename!=\'tom\';
(3)多表查询
要查询的列是分布在不同的表中,前提在创建表的时候已经建立了关联
示例:查询出所有员工的姓名及其部门名称
select ename,dname from emp,dept where deptId=did;
select emp.ename,dept.dname from emp,dept where emp.deptId=dept.did;
内连接
select ename,dname from emp inner join dept on deptId=did;
和之前的查询结果一样
左外连接
select ename,dname from emp left outer join dept on deptId=did;
显示左侧表中所有的记录,先写哪个表哪个就是左
outer关键字可以省略
右外连接
select ename,dname from emp right outer join dept on deptId=did;
显示右侧表中所有的记录,后写哪个表哪个就是右
outer关键字可以省略
全连接
full join on
mysql不支持全连接写法
解决方法:将左外连接和右外连接的结果联合起来,合并相同的记录。
union 联合后,合并相同的记录
union all 联合后,不合并相同的记录
(select ename,dname from emp left outer join dept on deptId=did)
union
(select ename,dname from emp right outer join dept on deptId=did);
学习一门编程语言的步骤
(1)了解背景知识:历史、现状、特点、应用场景
(2)搭建开发环境,编写hello world
(3)变量和常量
(4)数据类型
(5)运算符
(6)逻辑结构
(7)函数和对象
(8)通用的小程序
(9)第三方的库和框架
(10)个人项目
程序员必做50题
https://wenku.baidu.com/view/...
《javascript高级程序设计》第4版
1.JS概述
(1)历史
1995年,JS最早出现在Netscape的浏览器中
1996年,IE3中也可以出现了JS,称作JScript
1997年,JS被提交给了ECMA组织,制定了JS的标准规范ECMAScript
2009年,JS遵循CommonJS规范,开始向服务器端发展
(2)现状
JS就可以运行在客户端浏览器,也可以运行在服务器端
(3)特点
解释型语言,编译一行执行一行
弱类型语言
基于对象
跨平台
(4)应用场景
开发浏览器端的交互效果,进行服务器端开发,例如:创建WEB服务器、访问数据库、调用其它的服务器...
2.开发环境
(1)浏览器端
每个浏览器都有自带的一套JS解释器执行JS代码
世界上5大浏览器:谷歌、火狐、edge、Safari、欧朋
内核
(2)服务器端
Node.js
下载地址:https://nodejs.org
在命令行cmd下输入 node -v 查看到版本号
(3)运行JS
浏览器端
创建01.html和01.js,将js文件嵌入到html
<script src="01.js"></script>
Node.js
node 拖拽要运行的文件 回车
3.JS的语法规范
区分大小写
每行代码结束的分号可以省略
分为单行注释(//)和多行注释(/ /)
4.变量
存储数据的容器
(1)声明变量
var x=1;
var a=1,b=2;
使用关键字var来声明变量,也可以一次声明多个变量
(2)变量的命名规则
可以由字母、数字、下划线、美元符号组成,不能以数字开头,不能使用关键字
语义化(可读性)
用户名 user_name userName yongHuMing
密码 password
(3)变量的赋值
变量声明后未赋值则为undefined(未定义)
变量声明后可以被重新赋值,并且赋不同类型的值,这是弱类型语言的特点
练习:声明多组变量分别保存商品的单价和数量,声明变量暂时为空,用于保存总价,计算总价并打印结果。
5.常量
和变量一样用于存储数据的容器,声明后必须赋值,不允许重新赋值
const pi=3.14;
使用const声明常量
课后任务
(1)复习今天内容,整理思维导图
(2)练习:
声明变量保存半径,声明常量保存圆周率,分别声明变量保存计算的面积和周长
交换两个变量的值
a = 1, b= 2 交换后 a=2,b=1
(3)预习js第2天 数据类型 运算符
http://www.codece.com/archive...
day02
1.数据类型
分为原始类型和引用类型
原始类型分为数值型、字符串型、布尔型、未定义型、空
(1)数值型
整型
10进制
1 2 3 .... 7 8 9 10 11 ... 15 16
8进制
1 2 3 ... 7 10 11 12
16进制
1 2 3 ... 7 8 9 a ... f 10
8进制以0开头的数字,例如012
16进制以0x开头的数字,a~f代表10~15,不区分大小写
浮点型
3141.5E-1
314.15
31.415E+1
3.1415E+2
typeof 检测数据类型
(2)字符串型
被引号包含的数据,不区分单双引号
查看任意一个字符的Unicode码
\'a\'.charCodeAt()
(3)布尔型
只有两个值,分别是true和false,代表真和假
通常用于保存只有两个状态的数据,例如是否登录、是否在线... 一些运算符的结果也是布尔型
(4)未定义型
只有一个值是undefined,代表一个空值,例如声明了变量未赋值为undefined
(5)空
只有一个值是null,类型是object,常结合对象一起使用
2.数据类型转换
分为隐式转换和强制转换
1)隐式转换
在运算过程中自动产生的数据转换
(1)数字+字符串 数字转换为字符串
1 + \'2\' // \'12\'
(2)数字+布尔型 布尔型转换数值 true -> 1 false -> 0
2 + true //3
2 + false //2
(3)布尔型+字符串 布尔型转为字符串
true + \'5\' //\'true5\'
加号(+)的作用
执行数字之间的加法运算
执行字符串之间的拼接
练习:查看以下程序的运行结果
var a = 3, b = true, c = \'tedu\';
console.log(a+b+c); //\'4tedu\'
console.log(b+c+a);//\'truetedu3\'
console.log(c+a+b);//\'tedu3true\'
NaN:Not a Number(不是一个数字)
在将一个数据转换为数值型时候,没有成功得到一个数字就会返回NaN
NaN和任意数字执行运算,结果还是NaN
所有的隐式转换为数字都是会自动调用函数Number完成的
2)强制转换
(1)强制转换为数值型
Number()
Number(\'1\') //1
Number(true) //1
Number(false) //0
Number(undefined) //NaN
Number(null) //0
Number(\'1a\') //NaN
(2)强制转换为整型
parseInt()
强制将字符串和小数转为整型
parseInt(\'3.94\') //3
parseInt(\'6.18a\') //6
parseInt(\'a6.18\') //NaN
parseInt(5.9) //5
undefined null true false都是返回NaN
(3)强制转换为浮点型
parseFloat()
强制将字符串转换为浮点型
parseFloat(\'3.14\') //3.14
parseFloat(\'6.18a\') //6.18
parseFloat(\'6a\') //6
parseFloat(\'a6.18\') //NaN
(4)数值和布尔型强制转字符串
toString()
var num = 5;
num.toString() //\'5\'
3.运算符
表达式:由数据本身或者由运算符连接的操作数据组成的形式称作表达式
运算符分为算术运算符、比较运算符、逻辑运算符、位运算符、赋值运算符、三目运算符
(1)算术运算符
- / % ++ --
% 取余
++ 自增,在原来的基础之上加1
-- 自减,在原来的基础之上减1
- / % ++ --
(2)比较运算符
< >= <= ==(等于) !=(不等于) ===(全等于) !==(不全等于)
等于:只是比较两者的值是否相同,可能会发生隐式转换
全等于:同时比较类型和值,都相同结果才是true,否则false
不等于:比较值是否不相同
不全等于:同时比较类型和值,有一个不等为true,否则false
3>\'10\' 数字和字符串比较,字符串转为数值
\'3\'>\'10\' 字符串比较,比较的是首个字符的Unicode码
\'3\' -> 51 \'1\' -> 49
3>\'10a\' //false
3<\'10a\' //false
3==\'10a\' //false
NaN和任何值比较(> < >= <= == ===)结果都是false
NaN == NaN //false
(3)逻辑运算符
&& || !
&& 逻辑与,关联的两个条件都为true,结果是true,否则false
|| 逻辑或,关联的两个有一个为true,结果是true,否则false
! 逻辑非,取反
短路逻辑
逻辑与,如果第一个条件是false,就不再执行第二个条件
逻辑或,如果第一个条件是true,就不再执行第二个条件
练习:以下程序运行是否会报错
var a = 3;
a > 1 && console.log(num);
a < 5 || console.log(num);
短路逻辑关注点在于是否会执行第二个表达式。
练习:声明变量保存一个人的年龄,使用短路逻辑,如果满18岁打印‘成年人’
(4)位运算符
模拟计算机底层的运算,先把数据转为2进制,然后进行运算;当运算完以后再把结果转回成10进制。
1 2 3 4 5 6 7 8
1 10 11 100 101 110 111 1000
课后任务
(1)复习今天内容,整理思维导图
(2)练习:声明变量保存任意一个年份,使用短路逻辑,如果是闰年打印\'闰年\'
能被4整除 并且不能被100整除 或者被400整除
2020 2100 2000
(3)预习js第3天 ,if if-else if-else嵌套...
http://www.codece.com/archive...
day03
1.运算符
(1)位运算符
模拟计算机底层的运算,先把数据转为2进制,然后进行运算;当运算完以后再把结果转回成10进制。
1 2 3 4 5 6 7 8
1 10 11 100 101 110 111 1000
& 按位与,上下两位都是1结果是1,否则是0
| 按位或,上下两位含有1结果是1,否则是0
^ 按位异或,上下两位不同是1,相同是0
按位右移,删除最后的位数,在原来基础之上除以2再取整,例如7>>1 执行 parseInt(7/2)
<< 按位左移,在末尾补0,在原来的基础之上乘以2,例如3<<1 执行3*2
3 & 7 7&11 12 | 8 6 ^ 15
011 0111 1100 0110
111 1011 1000 1111
——— ———— ———— ————
011 0011 1100 1001
(2)赋值运算符
= += -= *= /= %= ...
运算赋值:先执行运算,再执行赋值
练习:声明变量保存商品的价格,让该商品执行打八折,最后打印价格
(3)三目运算符
一目运算符:由一个运算符连接的一个操作数据或者表达式 ! ++ --
二目运算符:由一个运算符连接的两个操作数据或者表达式
三目运算符:由两个运算符连接的三个操作数据或者表达式
条件表达式 ? 表达式1 : 表达式2
如果条件表达式为true,执行表达式1
如果条件表达式为false,执行表达式2
2.浏览器端函数
alert() 弹出警示框
prompt() 弹出提示框(输入框),需要使用变量保存用户输入的值,类型是字符串型,如果点击取消返回null
练习:弹出两次提示框,分别输入数字,最后计算两个数字相加的和,并将结果以警示框形式弹出
程序 = 数据 + 算法
程序的执行方式:顺序执行、选择执行、循环执行
3.流程控制
(1)if语句
满30减20
if(条件表达式){
语句块
}
如果if后的语句块中只有一行代码,则大括号可以省略的
以下5种情况隐式转换为布尔型为false:0 NaN \'\' undefined null
(2)if-else语句
if(条件表达式){
语句块1
}else{
语句块2
}
(3)if-else嵌套
if(条件表达式1){
语句块1
}else if(条件表达式n){
语句块n
}else{
语句块n+1 //以上所有的条件都是false
}
(4)switch-case
是一种特殊的多项分支语句
switch(表达式){
case 值1: //如果表达式和case后的值相同,会执行对应的语句块
语句块1
break;
case 值n:
语句块n
break;
default:
语句块n+1
}
表达式在和case后的值比较的时候,用的是全等于(===)
对比if-else和switch-case
if-else可以进行各种条件的比较,switch-case只能进行全等于的比较
switch-case的代码结构更为清晰,执行效率更高
课后任务
(1)复习今天内容,整理思维导图
(2)练习:弹出两次提示框,分别输入商品的单价和数量,计算出总价,假设总价满1000元打九折,当前会员卡内有余额1200,如果足以执行,警示框弹出\'pay success\',否则警示框弹出\'pay error\'
html和js两个文件
(3)预习JS第4天
http://www.codece.com/archive...
day04
循环
一遍又一遍执行相同或者相似的代码
循环的两个要素
循环条件: 控制循环的执行
循环体: 要重复执行的代码
1.while循环
while(循环条件){
循环体
}
2.break
在循环体中使用,用于跳出循环,不再执行任何循环中的代码
练习:当循环条件为true,计算10~20之间所有整数的乘积
101112...*20
3.do-while循环
do{
循环体
}while(循环条件);
4.for循环
for(初始值;循环条件;增量){
循环体
}
5.break和continue
continue:跳过后续循环体代码,还会往后继续执行
break:跳出循环,结束循环的执行
练习:打印1~100之间所有的整数,不包含能被3或者4整除的数字
6.循环嵌套
在一个循环体的内部出现了另一个循环
任意两个循环之间都可以相互嵌套
课后任务
(1)复习今天内容,整理思维导图
(2)练习:
①假设有本金10000万,银行年利率4%,存5年,一共有多少钱(利滚利)。
②声明变量保存任意一个数字,查看改数字是否为素数(质数),如果是打印\'素数\',否则打印\'非素数\'
素数:除了1和自身以外,中间不能被其它的数字整除
③打印九九乘法表
1*1=1
12=2 22=4
(3)预习js第5天 函数
www.codece.com/archives/93
day05
1.函数
Number()/parseInt()/parseFloat()/alert()/prompt()
函数分为系统函数和自定义函数
函数:是一个功能体,需要提供若干个数据,返回处理的结果 —— 用于封装重复执行的代码
(1)创建函数
function 函数名称(){
函数体 //封装重复的代码
}
调用
函数名称()
每调用一次,就会执行一次函数体中的代码。
练习:创建函数getSum,在函数体中封装计算1~100之间所有整数的和并打印结果;调用多次
(2)创建带有参数的函数
function 函数名称(参数列表){
函数体
}
调用
函数名称(参数列表)
创建函数时的参数称作形参,调用函数时的参数称作实参,实参会赋值给形参,实参的数量可以和形参的数量不匹配,如果形参未被赋值则为undefined
练习: 创建函数getSum,传递任意一个数字,计算1~任意数字之间所有整数的和并打印结果,调用多次
练习:创建函数getCount,传递任意两个年份,统计两个年份之间所有闰年的个数,调用多次
(3)创建带有返回值的函数
function 函数名称(参数列表){
函数体
return 值; //返回值,函数调用后返回的结果
}
调用
函数名称(参数列表) //得到函数的返回值
如果函数中没有写return或者return后没有任何值,则返回undefined
一旦执行return,就会跳出函数的执行
练习:创建函数getMax,传递任意两个数字,返回最大值。
练习:创建函数getMax2,传递任意三个数字,返回最大值
练习:创建函数getStatus,传递订单的状态码,返回对应的中文状态
1-等待付款 2-等待发货 3-运输中 4-已签收 5-已取消 其它-无法追踪
switch-case
对比return和break
return用于函数中,跳出函数的执行
break用于循环和switch-case,跳出循环或者switch-case语句
练习:创建函数isPrime,传递任意一个数字,判断是否为素数,返回布尔型的值
练习:创建函数isRun,传递任意一个年份,判断是否为闰年,返回布尔型的值
2.变量的作用域
全局变量:在全局作用域(函数以外)声明的变量就是全局变量,可以在任意的作用域下访问到
局部变量:在函数作用域下声明的变量就是局部变量,只能在当前的作用域下访问到
在函数内不加var声明的变量是全局变量,后期在严格模式下报错,不推荐
变量提升:程序执行前,会将var声明的变量提升到所在作用域的最前边,只是提升声明,赋值不提升
3.函数的作用域
全局函数:在全局作用域下创建的函数,可以在任意的作用域访问
局部函数:在函数作用域下创建的函数,只能在当前的作用域访问
函数提升:程序执行前,会将函数整体提升到所在作用域的最前边
斐波那契数列
第1项和第2项固定是1,从第3项开始,每项的值是前两项相加的和
1 1 2 3 5 8
课后任务
(1)复习今天内容,整理思维导图
(2)练习(选做):
创建函数fib,传递任意一个数字,返回斐波那契数列第n项的值
例如 fib(6) -> 8
fib(5) -> 5
(3)预习JS第6天
Day06
匿名函数 对象
1.递归
是一个函数的内部调用自身这个函数,本身是一个死循环
递归一直运行会产生内存泄漏,造成系统崩溃
如何使用:
要有边界条件,结合着return使用
JS属于单线程运行逻辑,无法充分利用CPU内核,递归对CPU消耗比较大,JS不适合深层次的递归嵌套。
2.匿名函数
function(){ }
没有名称的函数
(1)创建函数
函数声明
function fn(){
}
函数表达式
var fun=function(){
}
变量名称就是函数名称
调用 fun()
对比函数名称和函数名称()
函数名称():调用函数,得到函数的返回值
函数名称:本质上就是一个变量,保存了一个函数
对比函数声明和函数表达式创建函数的区别
函数声明存在函数提升,可以先写调用再写创建;
函数表达式只是变量声明提升,必须先写创建再写调用
练习:使用函数表达式创建函数getSum,传递任意两个数字,返回两个数字之间所有整数的和。
(2)匿名函数自调用
目的是为了防止全局污染
(function(){
//函数作用域下,里边的变量都是局部变量
})();
(3)回调函数
将函数作为参数来传递到另一个函数
function tao(madai){
madai() //调用传递的回调函数
}
function dong(){
}
tao(dong) //dong是回调函数
tao(function(){ }) //匿名函数是回调函数
3.系统函数
isNaN() 判断一个值是否为NaN,会隐式转换为数值型,
是NaN -> true 不是NaN -> false
isFinite() 判断一个值是否为有限值,只有Infinity是无限值,其它都是有限值
2/0 -> Infinity
eval() 执行字符串表达式
4.对象
是一组属性和方法的集合
一部手机,属性有颜色、品牌、CPU、内存... 方法有打电话、发短信、玩游戏、看视频、办公...
涛哥,属性有发色、身高、体重... 方法有摊煎饼、养兔子、跑接力赛...
万物皆对象
(1)JS中的对象
自定义对象:用户自己创建的对象
内置对象:JS提供的对象
宿主对象:根据不同的执行环境划分
(2)自定义对象创建方式
对象字面量
内置构造函数
自定义构造函数
(3)对象字面量
{ 属性名1: 属性值1, 属性名2: 属性值2.... }
属性名的引号可以省略,如果含有特殊字符必须添加
练习:创建一个商品对象,包含的属性有编号,标题,价格,是否在售
(4)访问属性
对象.属性名
对象[\'属性名\']
如果访问没有的属性,则返回undefined
练习:创建一个图书对象,包含的属性有编号,书名、作者、价格;修改图书的价格,添加图书的出版社,出版时间;最后打印对象
(5)内置构造函数
new Object() 创建一个空对象,需要单独的添加每个属性
练习:创建一个汽车对象,包含有汽车的品牌,颜色,长度,宽度
(6)遍历属性
for(var k in 对象){
k代表每个属性名
对象[k] 代表属性名对应的属性值
}
练习:使用对象字面量创建一个学生对象,包含有学号,姓名,性别,分数;遍历对象得到每个属性
课后任务
(1)复习今天内容,整理思维导图
(2)练习:创建对象包含一组成绩,遍历对象属性,计算出总成绩和平均成绩
(3)预习js第7天 数组
Day07
1.检测属性是否存在
对象.属性名 === undefined 存在 -> false 不存在 -> true
对象.hasOwnProperty(\'属性名\') 存在 -> true 不存在 -> false
\'属性名\' in 对象 存在 -> true 不存在 -> false
练习:创建对象保存一条商品的数据,包含有编号,标题,价格属性,如果价格属性存在,在原来的基础之上打九折,如果产地属性不存在则添加该属性,最后打印对象。
2.对象中的方法
方法对应的是一个函数
var person = {
play: function(){
this 指代调用方法的对象
}
}
person.play(); //调用
练习:创建一个圆的对象,包含的属性有半径、圆周率,添加两个方法,分别是计算面积和周长,并将计算的结果返回;最后调用两个方法
3.数据的存储
原始类型,将数据直接存储在栈内存;
引用类型,将数据存储在堆内存中,然后自动生成一个16进制地址,然后将地址保存在栈内存
null:表示空地址,没有指向任何堆内存数据
引用类型的数据如果不被任何的地址所指向就会自动销毁,直接赋值为null,就可以销毁引用类型的数据。
4.数组
就是一组数据的集合
(1)字面量创建数组
[ 元素1, 元素2 ... ]
练习:创建数组,包含一组成绩;创建数组,包含一组商品的标题;
(2)访问数组元素
数组[下标]
下标:自动为每个元素添加的编号,从开始的整数
如果访问不存在的元素,则结果为undefined
练习:创建数组包含有多个国家的名称,修改其中的一个元素,在末尾添加两个元素
(3)数组的长度
数组.length 获取数组元素的数量
在数组末尾添加元素 数组[ 数组.length ] = 值
练习:创建一个空数组,添加若干个汽车的品牌名称
(4)内置构造函数创建数组
new Array(元素1,元素2,...)
new Array(4) 创建数组,初始化长度为4,可以添加更多个元素
练习:创建数组,包含多个城市的名称;
创建数组,初始化长度为5,添加5张图片的名称
(5)数组的分类
索引数组:以0及以上的整数作为下标
关联数组:以字符串作为下标,只能单独的添加元素
关联数组不能使用length属性获取数组的长度
(6)遍历数组元素
依次访问数组中的每个元素
for-in
for(var k in 数组){
k 代表下标
数组[k] 下标对应的元素
}
循环 —— 推荐用法
for(var i=0;i < 数组的长度;i++){
i 代表下标
数组[i] 下标对应的元素
}
练习:创建数组,包含一组成绩,遍历数组元素,计算出总分和平均分
(7)API
应用程序编程接口:JS中预定义的函数或者对象下的方法
toString() 将数组转为字符串
join(\'-\') 将数组转为字符串,默认用逗号分割元素,可以指定分割符号
concat(arr2,arr3...) 拼接多个数组,arr2,arr3代表要拼接的数组
课后任务
(1)复习今天内容,整理思维导图
(2)练习:
使用遍历数组元素方式,翻转数组中的元素
[\'a\',\'b\',\'c\',\'d\'] -> [\'d\',\'c\',\'b\',\'a\']
将一组数字进行从小到大排序,(冒泡排序) 选做
[23,9,45,6,78] -> [6, 9, 23, 45, 78]
循环嵌套
(3)预习JS第8天 字符串对象
Day08
1.数组
(1)API
reverse() 翻转数组元素
sort() 对数组进行排序,默认是按照首个字符的Unicode码从小到大排序
sort( function(a,b){
return a-b;//按照数字从小到大排序
//return b-a; //按照数字从大到小排序
} )
如何学习API:作用、需要哪些参数、返回值
数组API还需要查看原数组是否会发生变化。
slice(start,end) 截取数组元素,start开始的下标,end结束的下标,不包含end,如果end为空截取到最后,如果下标是负数表示倒数;返回截取到的元素,格式为数组。
练习:创建数组,保存a~h,每个字母是一个元素,分别截取bc,f,将截取的数组拼接到一起。
splice(start, count, v1,v2) 删除数组元素,start开始的下标,count删除的数量,count为空删除到最后,下标为负数表示倒数,v1,v2表示删除后补充的元素,返回删除后的元素,格式为数组;原数组会发生变化。
练习:创建数组,保存a~h,每个字母是一个元素,删除cd,替换f为m,在下标为1的位置插入z
push() 在数组的末尾添加一个或者多个元素,返回数组的长度,原数组会发生变化
pop() 删除数组末尾的一个元素,返回删除的元素,原数组发生变化
unshift() 在数组的开头添加一个或者多个元素,返回数组的长度,原数组会发生变化
shift() 删除数组开头的一个元素,返回删除的元素,原数组发生变化
indexOf() 判断数组中是否含有某个元素,存在返回下标,如果不存在返回-1
练习:创建数组包含\'和谐福\',\'友善福\';判断是否含有敬业福,如果没有则把该福字添加到数组;判断是否含有和谐福,如果有则删除该福字。
(2)二维数组
对数据进行二次分类
[ [ ], [ ], [ ] ]
访问
数组[下标][下标]
2.字符串对象
包装对象:目的是为了让原始类型的数据像引用类型的数据一样,具有属性和方法,一共三种包装对象,字符串对象,数值对象,布尔对象
new String() 将数据强制转换为字符串,返回对象
String() 将数据强制转换为字符串,返回字符串
(1)转义字符
转换字符本身的意义
\\\' 将具有特殊意义单引号转为普通引号
\\n 将普通的字符n转义为换行符
\\t 将普通的字符t转义为制表符(tab键效果)
练习:打印出以下路径 C:\\Users\\web
(2)API
length 获取字符串的长度
charAt() 获取下标对应的字符,也可以使用数组格式 字符串[下标]
练习:声明变量保存javascript,遍历字符串,查找a出现的次数
indexOf() 查找字符串,返回满足条件的第一个的下标,找不到返回-1
lastIndexOf() 查找字符串,返回满足条件的最后一个的下标,找不到返回-1
练习:声明变量保存用户输入的邮箱,判断邮箱中是否含有@,如果没有则打印\'非法的邮箱\',否则打印\'合法邮箱\'
toUpperCase() 将英文字母转大写
toLowerCase() 将英文字母转小写
slice(start, end) 截取字符串,start开始的下标,end结束的下标,end为空截取到最后,下标为负数表示倒数,返回截取到的字符串
substr(start, count) 截取字符串,start开始的下标,count截取的长度,count为空截取到最后,下标为负数表示倒数,返回截取到的字符串
split(str) 将字符串转为数组,按照指定的字符str分割
3.Math对象
不需要创建,可以直接使用API
PI 获取圆周率
abs() 求绝对值
ceil() 向上取整
floor() 向下取整
round() 四舍五入取整
max() 获取一组数字最大值
min() 获取一组数字最小值
pow(x,y) 计算x的y次方
random() 获取随机,范围 0~1 >=0 <1
课后任务
(1)复习今天内容,整理思维导图
(2)练习:
将一句英文中每个单词首字母大写,其余字母小写
hOw aRE yOu -> How Are You
随机获取a~z之间的4个字母,放入到一个新数组
(3)预习JS第9天 Date对象
Day09
双色球
红球:在1~33之间随机取6个数字,不能重复,进行从小到大的排序
蓝球:在1~16之间随机取1个,可以和之前的红球重复
把以上的7个数字放入到一个数组。
1.Date对象
用于对日期时间的存储和计算
(1)创建
new Date(\'2021/6/17 10:20:30\')
new Date(2021,5,17,10,20,30) 月份范围0~11 代表1~12月
new Date(1683036000000) 存储距离计算机元年的毫秒数对应的日期时间
new Date() 存储当前操作系统的时间
(2)获取
getFullYear/getMonth/getDate
月份范围0~11 对应1~12月
getHours/getMinutes/getSeconds/getMilliseconds(毫秒)
getTime 获取距离计算机元年毫秒数
getDay 获取星期 范围0~6 对应星期日~星期六
(3)转为本地字符串格式
存在兼容性问题,用于测试
toLocaleString() 获取完整的
toLocaleDateString() 获取日期部分
toLocaleTimeString() 获取时间部分
(4)修改
setFullYear()/setMonth()/setDate()
setHours()/setMinutes()/setSeconds()/setMilliseconds()
setTime() 设置距离计算机元年毫秒会,产生具体的日期时间
练习:创建对象保存当前操作系统的日期时间,修改为3天后,修改为7个小时前。
2.Number对象
new Number() 将数据转为数值型,返回对象
Number() 将数据转为数值型,返回数值
toFixed(n) 强制保留小数点后n位
toString(n) 强制转为字符串,可以通过n设置进制
3.Boolean对象
new Boolean() 将数据转为布尔型,返回对象
Boolean() 将数据转为布尔型,返回布尔型数据
4.错误处理
(1)常见的错误
语法错误(SyntaxError):出现了中文符号,缺少括号等
引用错误(ReferenceError):使用了未声明的变量
类型错误(TypeError):函数或者对象下的方法找不到
自定义错误:程序员自己指定的错误
throw 错误内容
(2)错误处理
try{
尝试执行,可能出现错误
}catch(err){
捕获错误,一旦try中出现错误才会执行
将错误放入到err中
进行错误处理
}
5.ES6
ECMAScript ES
ES6是JS的第6版标准规范
ES7 ES8
ES2015 ES2016 ... ES2021
(1)块级作用域
let声明变量不存在变量的提升,不允许重复声明
let声明的变量不是全局变量
大括号之间的语句块就是块级作用域,例如:if、else、for、while...
块级作用域下let和const声明的变量和常量是局部的
练习:计算1~100之间所有整数的和,变量使用let声明
var,let,const的区别
var声明的变量存在变量提升,允许重复声明
let,const存在块级作用域,任何情况下都不是全局的
var,let允许重新赋值
const声明后必须赋值,不允许重新赋值
(2)参数的默认值
function fn(a,b,c=0){
b = b || 0; //es6之前的默认值的方式
}
fn(5000)
课后任务
(1)复习今天内容,整理思维导图
(2)练习: 创建函数,传递任意一个日期,最后返回这个日期是一年中的第几天
(3)预习nodejs第1天
Node.js day01
1.ES6
(3)箭头函数
简化了匿名函数的写法,不等价匿名函数
()=>{ }
sort( (a,b)=>{
return a-b;
} )
如果箭头函数的函数体中只有一行代码并且是return形式,可以简化为
sort( (a,b)=>a-b )
练习:使用箭头函数创建函数,传递任意三个数字,返回平均数。
(4)模板字符串 模板字符串 ${ JS表达式 }
解决了字符串的拼接问题
练习:创建对象保存一条员工的数据,包含属性姓名、性别(1/0)、工资、部门名称,最后打印以下格式
姓名:xx
性别:男女
工资:18000.00元
部门:xx
1.Node.js概述
(1)对比JS
JS运行在客户端浏览器,存在多种解释器,有代码兼容性问题;Node.js运行在服务器端,只有V8引擎一种解释器,不存在代码兼容性问题。
两者都有相同内置对象和自定义对象,不同的宿主对象
JS用于开发浏览器端的交互效果,Node.js用于服务器端功能开发,例如数据库的访问,其它服务器的调用
(2)运行方式
脚本模式
node 文件的路径 回车
交互模式
node 回车 进入交互模式
退出 两次ctrl+c / ctrl +d / .exit
(3)特点
属于单线程运行逻辑,不会产生死锁,支持数万个并发连接,适合做基于社交网络的大规模WEB应用
(4)网址
www.nodejs.org 官网
www.nodejs.cn 中文网
2.全局对象
(1)global对象
检测一个变量或者函数是否为全局的
在交互模式下属于是全局作用域,里边的变量和函数都是全局的
在脚本模式下不属于全局作用域,里边的变量和函数都不是全局的,可以防止全局污染
练习:编写文件03_global.js,声明变量、创建函数,查看是否为全局的
JS下的global叫做window
练习:编写04_window.js,04.html,把js嵌入到html中,声明变量和创建函数,检测是否为全局。
(2)console对象
console.log(1) //输入日志
console.info(2) //输出消息
console.warn(3) //输出警告
console.error(4) //输出错误
console.time() 开始计时
console.timeEnd() 结束计时
开始计时和结束计时提供的值要保持一致
练习:分别使用while、do-while、for循环100000次的耗时
(3)process对象
进程
计算机在运行软件的时候,都会产生相应的进程
process.arch 查看当前CPU的架构
process.platform 查看当前的操作系统
process.version 查看当前Node.js版本
process.pid 查看当前进程的编号
process.kill(编号) 结束指定编号的进程
(4)Buffer对象
缓冲区,是内存中临时存储数据的区域
let buf=Buffer.alloc(5, \'ab涛\')
创建Buffer,设置大小为5个字节,并填充数据,每个汉字占3个字节
String(buf) / buf.toString()
将Buffer数据转为字符串
3.定时器函数
(1)一次性定时器
开启
let timer=setTimeout(回调函数, 间隔时间);
当间隔时间到了,会调用一次回调函数
清除
clearTimeout(timer)
(2)周期性定时器
开启
let timer = setInterval(回调函数, 间隔时间)
每隔一段时间,调用一次回调函数
清除
clearInterval(timer)
练习:开启一次性定时器,每隔2秒打印‘滴滴滴’
练习:清除定时器
(3)立即执行定时器
开启
let timer = setImmediate(回调函数)
清除
clearImmediate(timer)
开启
process.nextTick(回调函数)
4.模块
每个文件是一个模块,每一个模块都是一个独立的功能
一个模块引入其它的模块
一个模块也可以被其它的模块引入
require() 是一个函数,用于引入其它的模块
module.exports 导出的对象,默认是一个空对象,如果要导出哪些内容需要放入到这个对象
课后任务
(1)复习今天内容,整理思维导图
(2)练习
创建主模块main.js和功能模块circle.js,主模块引入功能模块,在circle.js中创建两个函数,传递半径,返回圆的周长和面积,最后导出这两个函数,最后在主模块下调用。
(3)预习Node.js第2天 同步异步
1.模块系统
require: 是一个函数,用于引入其它的模块,得到导出的对象
module:当前模块对象
module.exports:当前模块导出的对象
__dirname:是一个局部变量,当前模块的绝对路径
__filename:是一个局部变量,当前模块的绝对路径+模块名称
2.模块分类
分为自定义模块、第三方模块、核心模块
以路径开头 不以路径开头
文件形式 require(\'./circle.js\')
用于引入自定义模块 require(\'querystring\')
用于引入官方提供的核心模块
目录形式 require(\'./02_tao\')
首先会到目录下寻找package.json文件中main对应的文件,如果找不到则会寻找index.js require(\'tao\')
首先会到同一级目录下的node_modules目录中寻找tao,如果没有找到会一直往上一级的node_modules目录中寻找;用于引入第三方模块
练习:在03_1.js中引入同一级的03_2目录模块,在03_2目录中含有文件index.js,创建一个函数返回任意3个数字的最大值,最后导出;在03_1.js中调用导出的函数。
3.包和npm
CommonJS:是一种规范,制定了Node.js的模块化概念
包:通常指的是目录模块
npm:是用于管理包的工具模块,在Node.js安装的时候会附带安装
npm -v 查看版本号
网址:https://www.npmjs.com/
(1)切换命令行的路径
①cd 完整的路径
如果有盘符的变化 盘符名称: 回车
②在要进入的目录的空白区域,按住shift,单击鼠标右键,选择\'在此处打开powershell窗口\'
(2)使用npm
npm init -y 生成package.json文件,作为项目说明文件,可以用于记录下载安装的包的信息
npm install 包的名称 下载安装指定的包,将包放入到node_modules目录中,如果目录不存在会先创建,同时生成package-lock.json,用于记录所有包的版本号
npm install 自动下载package.json和package-lock.json中记录的包
npx:是npm安装的时候附带安装
npx -v 查看版本号
npx -p node@8 node 拖拽文件 下载指定版本的Node.js运行文件,运行完以后再把下载的Node.js删除
4.查询字符串模块(querystring)
查询字符串:浏览器向WEB服务器发请求,传递的数据的一种方式,位于浏览器的地址栏中。
https://search.jd.com/Search?...笔记本&enc=utf-8
查询字符串模块用于操作查询字符串的工具
parse() 将查询字符串解析为对象
练习:将以下查询字符串数据解析为对象
pname=小米Air&price=4199
显示为以下格式 商品名称:xxx 价格:xxx元
5.URL模块
URL:统一资源定位,互联网上的任何资源都有对应的URL
http://www.codeboy.com:9999/p...
协议 域名/IP地址 端口号 文件在服务器的路径 查询字符串
new URL( ) 将一个URL解析为对象,获取URL的各个部分
练习:获取以下URL中的传递的数据
https://www.tmooc.cn:443/cour...
最后打印出以下格式
班级:WEB2105 课程部分:nodejs
5.文件系统模块(fs)
用于操作服务器端的文件,例如文件的读取、写入、删除....
文件分为目录形式和文件形式
(1)查看文件的状态
fs.statSync(文件的路径) / fs.stat(文件的路径, 回调函数)
isFile() 是否为文件
isDirectory() 是否为目录
(2)创建目录
fs.mkdirSync(目录的路径)
(3)移除目录
fs.rmdirSync(目录的路径)
6.同步和异步
同步:在主程序中执行,会阻止后续代码的执行,通过返回值来获取结果
异步:在一个独立的线程执行,不会阻止主程序后续代码的执行,将结果以回调函数的形式放入到事件队列
课后任务
(1)复习今天内容,整理思维导图
(2)练习:
3秒钟以后,一次性创建1~10,总共10个目录;创建成功后,再10秒以后,再把以上10个目录一次性移除
(3)预习nodejs第3天 http协议 http模块 创建WEB服务器
1.fs模块
回调函数
参数1:可能产生的错误
参数2:成功的结果,只有结果是数据形式才会出现
(1)读取目录
readdirSync(目录的路径) / readdir(目录的路径, 回调函数)
读取的结果为数组
(2)清空写入文件
writeFileSync(文件的路径,数据) / writeFile(文件的路径,数据,回调函数)
如果文件不存在,则先创建文件然后写入数据
如果文件已经存在,会清空文件内容然后写入数据
(3)追加写入文件
appendFileSync(文件的路径,数据) / appendFile(文件的路径,数据,回调函数)
如果文件不存在,则先创建文件然后写入数据
如果文件已经存在,会在文件的末尾追加写入数据
练习:使用同步的方法往2.html写入数据 \'这是一条新闻\'
(4)读取文件
readFileSync(文件的路径) / readFile(文件的路径, 回调函数)
读取的结果为buffer数据格式
(5)删除文件
unlinkSync(文件的路径) / unlink(文件的路径, 回调函数)
练习:分别删除文件1.txt 和 2.html
(6)判断文件是否存在
existsSync(文件的路径)
存在->true 不存在 -> false
(7)拷贝文件
copyFileSync(源文件路径, 目标文件路径) / copyFile(源文件路径, 目标文件路径, 回调函数)
练习:如果目录mydir不存在则创建该目录,如果文件stu.txt存在,则把文件拷贝到mydir目录
2.文件流
createReadStream() 创建可读取的文件流
createWriteStream() 创建可写入的文件流
on(事件名称, 回调函数) 添加事件,事件名称是固定的字符串,一旦监听到事件会自动执行回调函数
pipe() 管道,可以将读取的流添加到写入的流
3.http协议:浏览器和WEB服务器之间的通信协议
(1)通用头信息
Request URL:请求的服务器端的资源
Request Method:请求的方法,对资源的操作方式 get/post/delete/put
Status Code:响应的状态码
1**:接收到了请求,还没有做出响应
2**:成功的响应
3**:响应的重定向,跳转到另一个URL
4**:客户端错误
5**:服务器错误
(2)响应头信息(response)
Content-Type:响应的内容类型 text/html;charset=utf-8
Location:设置要跳转的URL
(3)请求头信息(request)
(4)请求主体
显示传递的数据,不是每一次都出现
4.http模块
可以用来创建WEB服务器
(1)创建服务器
const http = require(\'http\'); //引入http模块
const app = http.createServer();//创建WEB服务器
app.listen(8080,()=>{ });//设置端口
(2)接收请求作出响应
//给服务器添加事件
app.on(\'request\', (req,res)=>{
req 请求对象
req.url 获取请求的URL,显示的端口号后的部分,例如 /jianbing
req.method 获取请求的方法
res 响应对象
res.writeHead(状态码, 头信息) 设置响应的状态码和头信息,第二个参数可以为空
res.write() 设置响应到浏览器的内容
res.end() 结束并发送响应
});
同步:在主程序中执行,会阻止后续代码执行,通过返回值获取结果
异步:在一个独立的线程执行,不会阻止主程序后续代码执行,通过回调函数获取结果
练习:编写文件05_http.js,创建WEB服务器,设置端口为8080,根据请求作出响应
/ 响应 \'<h1>这是首页</h1>\'
/study 跳转 \'https://www.tmooc.cn\'
/login 响应网页 1.html (先读取文件的数据,然后作为响应的内容)
其它 响应 404 not found
课后任务
(1)复习今天内容,整理思维导图
(2)练习:创建web服务器,设置端口8080,根据请求作出响应
/index 响应 \'<h1>学子商城</h1>\'
/ 跳转到 /index
/reg 响应 reg.html
其它 404 not found
(3)预习nodejs第4天 express
框架:是一整套解决方案,简化了已有的功能,添加了之前没有的功能
Node.js框架:express、koa、egg
1.express框架
express是基于Node.js平台,快速、开放、极简的WEB开发框架
属于是第三方模块,需要先下载安装
npm install express
(1)创建WEB服务器
const express = require(\'express\'); //引入express第三方模块
const app = express();//创建WEB服务器
app.listen(8080); //设置端口
(2)路由
根据请求的URL和请求的方法来作出特定的响应
包含三部分:请求的URL、请求的方法、回调函数
req请求对象
req.url 获取请求的URL
req.method 获取请求的方法
req.query 获取get传递的数据,格式为对象
res响应对象
res.send() 设置响应的内容并发送
res.redirect() 设置响应的重定向并发送
res.sendFile() 设置响应的文件并发送,使用绝对路径__dirname
以上三个方法在路由中只能执行一次
练习:编写文件03_express.js,使用express模块创建web服务器,设置端口为8080,添加路由(get /search),响应文件search.html
练习:添加路由响应提交按钮的请求(get /mysearch),响应 \'搜索成功\'
2.数据传递的方式
名称 格式 在路由获取
get方式 http://127.0.0.1:8080/mysearc... req.query
post方式 URL中不可见,在http协议的请求主体 req.on(\'data\', (chunk)=>{
chunk.toString()
需要使用查询字符串解析为对象
})
路由传参 http://127.0.0.1:8080/package... app.get(\'/package/:pname\',
(req,res)=>{
req.params
})
练习:添加路由(get /login),响应登录的网页login.html
点击提交再次向服务发送请求(post /mylogin),响应\'登录成功\'
练习:添加路由(get /reg),响应注册的网页register.html
点击提交,向服务器发送请求(post /myreg),响应
注册成功
用户:xxx 邮箱:xxx 手机:xxx
练习:添加到购物车路由(get /shopping),传递商品的编号lid和数量num,最终响应以下格式
商品的编号:xx
购买的数量:xx
商品模块
列表 修改 删除
/product/list /product/update /product/delete
用户模块
列表 修改 删除
/user/list /user/update /user/delete
3.路由器
路由器可以统一管理路由,还可以给一组路由添加统一的前缀
路由器
const r = express.Router();//创建路由器对象
//往路由器下添加路由
module.exports = r; //导出路由器对象
WEB服务器
//引入
app.use(\'/product\',productRouter); //挂载并添加前缀
课后任务
(1)复习今天内容,整理思维导图
(2)完成用户路由器(user.js),添加路由(get /list),最后导出,挂载到WEB服务器下
(3)预习Node.js第5天 中间件 复习mysql数据库
1.中间件
拦截对服务器端的请求,也可以作出响应
express下中间件分为应用级中间件、路由级中间件、内置中间件、第三方中间件、错误处理中间件
(1)应用级中间件
也称为自定义中间件,本质上就是一个函数
app.use(URL, 回调函数) 拦截特定的请求
app.use(回调函数) 拦截所有的请求
练习:添加到购物车路由(get /shopping),传递商品的价格price;添加中间件对传递的价格打9折;最后在路由中显示以下效果
商品的价格:900
http://127.0.0.1:8080/shoppin...
(2)路由级中间件
app.use(拦截的URL, 路由器)
(3)内置中间件
托管静态资源
客户端请求静态资源(html,css,js,图像...),不需要再创建路由,让客户端自动的到指定的目录下查找。
app.use( express.static(\'要托管的目录\') );
练习:将静态资源托管到files目录
练习:编写文件04_three.js,创建WEB服务器,托管静态资源到public目录,目录中含有登录的网页login.html,点击提交向服务器发请求(post /mylogin),获取传递的数据,响应‘登录成功,欢迎:xx’
(4)第三方中间件
第三方中间件以第三方模块的形式出现,需要先下载安装
//1.引入中间件模块
const bodyParser = require(\'body-parser\');
//2.使用中间件,将所有post请求的数据解析为对象
//把对象放入到了请求对象下 req.body
app.use( bodyParser.urlencoded({
extended: false //false不使用第三方的查询字符串模块,就会使用核心模块querystring
}) )
//3.在路由中获取数据,格式为对象
req.body
2.mysql模块
Node.js下,专门用于操作mysql数据库的第三方模块
npm install mysql 下载安装
mysql命令
mysql -uroot
mysql.exe -h127.0.0.1 -P3306 -uroot -p
mysql -uroot<拖拽脚本
insert into emp values(...);
delete from emp where eid=5;
update emp set sex=1,... where eid=7;
select * from emp;
select * from emp where ename=\'lucy\' or 1 ;
SQL注入:在让用于提供的值中,拼接了其它的SQL命令。
占位符(?): 先对数据进行过滤,过滤完以后再替换占位符
mysql.createConnection() 创建连接对象
connect() 测试连接
query(SQL命令, 要过滤的数据, 回调函数)
课后任务
(1)复习今天内容,整理思维导图
(2)练习:创建web服务器,托管静态资源到public目录,包含部门添加的网页add.html,点击提交,向服务器发请求(post /add),获取传递的数据,将数据插入到tedu下dept表中,响应\'部门添加成功\'
1.mysql
连接池:开始的时候创建一批的连接,可以被反复的使用,用完后会归还。
mysql.createPool() 创建连接池对象
query() 执行SQL命令
2.RESTful接口
接口:后端为前端提供的动态资源(对数据的增删改查)
RESTful:是一种接口的设计规范
(1)URL
员工资源
http://127.0.0.1:8080/v1/emps 多个资源
版本 资源名称(复数形式)
http://127.0.0.1:8080/v1/emps/5 单个资源
编号
http://127.0.0.1:8080/v1/user... 对资源特殊操作
登录
(2)请求的方法
对资源的操作方式
get 获取资源
delete 删除资源
put 修改资源
post 新建资源
(3)过滤数据
针对于多个资源的操作
http://127.0.0.1:8080/v1/emps...
通过分页过滤的数据 当前页码 每页数据量
http://127.0.0.1:8080/v1/emps...
过滤一组区间的数据
(4)返回结果
格式为JSON对象:字符串形式的对象,属性名必须用双引号,属性值是字符串也得是双引号
包含状态码(人为规定)、消息、数据
例如:用户登录的返回结果
{"code":200, "msg":"登录成功"}
例如:获取用户的列表
{"code":200, "msg":"获取成功", "data": [ ... ] }
练习:编写app.js文件,创建WEB服务器,设置端口;托管静态资源到public目录,包含员工添加网页add.html,点击提交向服务器发请求(post /v1/emps),获取传递的数据,将数据插入到tedu下的emp表中,最后响应{"code":200, "msg": "员工添加成功"}
练习:查找员工员工接口(get /v1/emps/编号),在路由中获取传递的数据,查询编号对应的员工,最后响应{code:200 ,msg:\'查询成功\', data: [ ]}
ApiPost接口测试工具
www.apipost.cn
3.正则表达式
课后任务
练习:编写删除用户的接口(delete /v1/emps/编号),获取传递的编号,执行SQL命令,如果删除成功响应 {code: 200, msg:\'删除成功\'},否则 响应{code:201,msg:\'删除失败\'}
选做:修改员工(put /v1/emps)
1.正则表达式相关函数
test() 检测字符串是否符合规则
replace(规则,替换的字符串) 查找并替换
search(规则) 查找符合规则的第一个,返回下标,找不到返回-1
match(规则) 查找符合规则的所有的,返回数组
修饰符
i 忽略大小写
g 全局查找
- 正则表达式完整视频
https://pan.baidu.com/s/1IgYS... 提取码:nbx3 - 字符串正则相关函数的用法总结
https://pan.baidu.com/s/1Rvqr... 提取码:08yj
正则表达式大全
https://www.cnblogs.com/dream...
练习:
在app.js下创建WEB服务器并设置端口
在user.js下创建路由器对象,添加用户注册路由(post /reg),响应\'注册成功\';导出路由器对象
在app.js下引入路由器user.js(./routes/user.js),挂载到WEB服务器,添加前缀/v1/users
apipost: post http://127.0.0.1:8080/v1/user...
练习:
在pool.js中创建连接池对象,导出连接对象
在user.js中引入连接池(../pool.js),执行SQL命令
pool.query()
练习:在user.js中添加用户登录的接口(post /login),获取post请求的数据,验证数据是否为空,到数据库中查询用户名和密码同时匹配的数据(条件查询),如果有响应‘登录成功’,否则‘登录失败’
练习:在user.js中添加修改用户的接口(put /),以body方式传递(uid,email, phone, user_name, gender),判断各项数据是否为空,执行SQL命令
User.js
//引入express模块
const express = require(\'express\');
//引入连接池摸
const pool = require(\'../pool.js\');
//创建路由器对象
const r = express.Router();
//1.用户注册接口(post /reg)
//请求方法:post
//地址:http://127.0.0.1:8080/v1/user...
r.post(\'/reg\',(req,res,next)=>{
//1.1获取post请求的数据
let obj = req.body;
console.log(obj);
//1.2验证数据是否为空
if(!obj.uname){
res.send({code: 401,msg: \'uname不能为空\'});
//阻止往后执行
return;
}
if(!obj.upwd){
res.send({code: 402,msg: \'upwd不能为空\'});
return;
}
if(!obj.email){
res.send({code: 403,msg: \'email不能为空\'});
return;
}
if(!obj.phone){
res.send({code: 404,msg: \'phone不能为空\'});
return;
}
//验证手机号码格式
//如果格式不符合
if( !/^1[3-9]\\d{9}$/.test(obj.phone) ){
res.send({code: 405,msg: \'手机号码格式不正确\'});
return;
}
//1.3执行SQL命令,插入数据
pool.query(\'insert into xz_user set ?\',[obj],(err,result)=>{
if(err){
//如果有错误,抛给下一个错误处理中间件
next(err);
return;
}
console.log(result);
//如果没有错误
res.send({code: 200,msg: \'注册成功\'});
});
});
//2.用户登录(post /login)
//请求方法:post
//地址:http://127.0.0.1:8080/v1/user...
r.post(\'/login\',(req,res,next)=>{
//2.1获取post传递的数据
let obj = req.body;
console.log(obj);
//2.2验证是否为空
if(!obj.uname){
res.send({code: 401,msg: \'uname不能为空\'});
return;
}
if(!obj.upwd){
res.send({code: 402,msg: \'upwd不能为空\'});
return;
}
//2.3执行SQL命令
pool.query(\'select * from xz_user where uname=? and upwd=?\',[obj.uname,obj.upwd],(err,result)=>{
if(err){
next(err);
return;
}
console.log(result);
//结果是数组,如果数组的长度为0,说明登录失败,否则登录成功
if(result.length === 0){
res.send({code: 201,msg: \'登录失败\'});
}else{
res.send({code: 200,msg: \'登录成功\'});
}
});
});
//3.修改用户(put /)
//请求方法:put
//地址:http://127.0.0.1:8080/v1/users
r.put(\'/\',(req,res,next)=>{
//3.1获取post请求的数据
let obj = req.body;
console.log(obj);
//3.2验证数据是否为空
//遍历对象得到每个属性
let i = 400;//初始化,保存状态码
for(let k in obj){
//每次循环,i加1
i++;
//console.log(k,obj[k]);
//判断属性值是否为空,如果为空则提示该属性名不能为空
if(!obj[k]){
res.send({code: i,msg: k+\'不能为空\'});
return;
}
}
//执行SQL命令
pool.query(\'update xz_user set ? where uid=?\',[obj,obj.uid],(err,result)=>{
if(err){
next(err);
return;
}
console.log(result);
//结果是对象,判断对象下的affectedRows,如果是0说明修改失败,否则修改成功
if(result.affectedRows === 0){
res.send({code: 201, msg: \'修改失败\'});
}else{
res.send({code: 200, msg: \'修改成功\'});
}
});
});
//导出路由器对象
module.exports = r;
app.js
//引入第三方模块express
const express = require(\'express\');
//引入用户路由器
const userRouter = require(\'./routes/user.js\');
//创建WEB服务器
const app = express();
//设置端口
app.listen(8080);
//将post请求的数据解析为对象
app.use(express.urlencoded({
extended: false
}));
//挂载用户路由器,添加前缀/v1/users
app.use(\'/v1/users\',userRouter);
//错误处理中间件
app.use( (err,req,res,next)=>{
//查看得到的错误信息
console.log(err);
//响应500
res.status(500).send({code: 500,msg: \'服务器端错误\'});
} );
Pool.js
//引入mysql模块
const mysql = require(\'mysql\');
//创建连接池对象
const pool = mysql.createPool({
host: \'127.0.0.1\',
port: \'3306\',
user: \'root\',
password: \'\',
database: \'xz\',
connectionLimit: 15
});
//导出对象
module.exports = pool;
用户列表(get /),传递当前的页码和每页的数据量,进行分页查询,获取传递的数据(req.query) ,最后响应 {code: 200, msg:\'查询成功\' ,data: [..]}
http://127.0.0.1:8080/v1/user...
删除用户(delete /编号)
http://127.0.0.1:8080/v1/users/5
查找用户(get /编号)
http://127.0.0.1:8080/v1/users/5
检测用户名是否可用
检测邮箱
以上是关于前端知识的主要内容,如果未能解决你的问题,请参考以下文章