一、基础知识储备
CS架构:客户端(需要客户先安装)/服务器;
BS架构:浏览器(可直接使用浏览器运行)/服务器;
软件开发周期:软件定义期(可行性研究阶段,需求分析阶段)——软件开发期(概要设计阶段,编码实现阶段,测试阶段)——软件维护期(软件维护阶段)
二、常用快捷键
Alt+Tab:切换当前的窗口;
Windows+d:显示或者隐藏桌面;
Windows+e:打开“此电脑”或者“文件资源管理器”;
Windows+r:打开“运行”窗口,可以快速打开软件,例如:cmd(命令行)/mspaint(画图)/calc(计算器)/mstsc(连接远程云服务器)
三、数据库
1.关系型数据库逻辑结构
数据库服务器Server -> 数据库Database -> 数据表Table -> 行Row -> 列Column;
2.mysql为中小型数据库,可用于各种操作系统;
3.部署结构
(1)服务器端
mysqld.exe(相当于start键,是启动文件,占用的端口是3306)
服务器端主要负责储存维护数据
(2)客户端
mysql.exe
客户端负责连接数据库服务器
4.mysql.exe -h127.0.0.1 -P3306 -uroot -p
-h(host连接服务器域名/IP地址,连接自己电脑的localhost/127.0.0.1)
-P(post端口)
-u(user用户名,mysql管理员用户名为root)
简写为mysql -uroot
用小键盘上的上下箭头可以调出以前写的代码,Esc取消上述操作
5.常用的管理命令
show databases;——查询所有数据库
use 数据库名称;——进入指定数据库
show tables;——查看当前所处的数据库有哪些表
desc 数据表名称;——描述指定数据表中表头都有哪些项
quit;——退出连接
select * from 数据表名称;——查询数据表中数据
6.下面介绍的是脚本模式时脚本文件写法,结果可以去交互模式下查看,我的电脑有问题输入utf8 依旧会乱码,所以需要在进入mysql之前输入chcp 65001+enter来手动改变一下编码,防止以后乱码;
set names utf8;#客户端服务器使用utf8编码;
drop database if exists xizi;#如果存在数据库xizi则丢弃它;
creat database xizi charset=utf8;#创建数据库xizi并使用utf8编码;
use xizi;#打开xizi数据库;
#创建笔记本分类的表family;
create table family (
fid int primary key, #编号并附加主键约束
fname varchar(20) #分类名称
);
#输入数据
insert into family values
("10","小米"),
("20","戴尔"),
("30","联想");
#创建保存笔记本数据的表laptop
create table laptop (
lid int primary key auto_increment, #编号并附加主键约束以及设置为自增列
title varchar(50) unique not null, #标题
price decimal(7,2) default 9999, #价格
stime date default "2022-10-24" , #上架时间
isonsale boolean, #是否在售
familyid int, #所属类别编号
#将familyid作为外键列,取值必须到family的fid去找
foreign key(familyid) references family(fid)
);
#输入数据
insert into laptop values("1","小米先锋",null,"2022-10-1",true,"10");
insert into laptop values("2","戴尔三","45563.22","2020-9-15",false,"20");
insert into laptop values("3","联想拯救","10050.24",null,true,"30");
#只给编号,标题,上架时间提供值;其他列不提供值,会自动应用默认值
insert into laptop(lid,title,price,isonsale,familyid) values(4,"devile","10002.33",true,30);
insert into laptop values("7","戴尔3.0",default,default,false,"20");
insert into laptop values(null,"戴尔3.1",default,default,false,"20");
insert into laptop values(null,"戴尔3.9",default,default,false,"20");
insert into laptop values(null,"戴尔3.2",default,default,false,"20");
insert into laptop values(null,"戴尔3.3",default,default,false,"20");
insert into laptop values(null,"戴尔3.4",default,default,false,"20");
insert into laptop values(null,"戴尔3.5",default,default,false,"20");
insert into laptop values(null,"戴尔3.6",default,default,false,"20");
delete from laptop where lid="2";#删除数据
update 数据表 set 列名称=...,列名称=...,列名称=... where 条件(比如id="2")
7.常见简称
定义数据结构(DDL)【create/drop/alter(修改)】、操作数据(DML)【insert/delete(删除)/update(修改】、查询数据(DQL)【select】、控制用户权限(DCL)【grant(授权)/revoke(收权)】
8.列类型
(1)数值型
tinyint/smallint/int/bigint/float/double/decimal/boolean
整数型
tinyint微整形,占一个字节,范围【-128,127】
smallint小整形,占两个字节,范围【-32768,32767】
int整形,占4个字节,范围【-2147483648,2147483647】
bigint大整形,占8个字节,范围很大
浮点型
float单精度浮点型,占四个字节
double双精度浮点型,占8个字节
demcial(M,D)定点小数,小数点不会发生变化,M代表总的有效位数,D代表小数点后的有效位数
布尔型
只有两个值,分别是true和false代表真和假;用于储存只有两个值的数据,例如:性别,是否在线,是否是会员
(2)日期时间型
date/time/datetime
date日期型“2022-10-22”
time时间型
“15.50.30”
datetime日期时间型
“2022-10-12 15.50.30”
(3)字符串型
varchar/char/text
varchar(M)变长字符串(空间浪费少)
char定长字符串(视情况而定)
9.列约束
(1)primary key主键约束
一个表格里只能有一个主键,声明主键约束的列,不允许重复的值,主键约束的列的上禁止插入null(一次性插入多条数据,
允许在主键约束里使用一次null,这可能导致出错,所以不推荐使用一次性插入)
(2)not null非空约束
声明了非空约束的列禁止插入null
(3)unique唯一约束
声明了唯一约束的列上不允许 插入重复的值,但允许插入null,甚至是多个null
(4)default默认值约束(default+默认值)
在插入数据的时候,如果不提供的值可以使用列的默认值。步骤分为两步:
【1.设置默认值,通过default设置,如果不设置的话,默认值是null.
2.使用默认值,不提供值时会自动使用默认值】
(5)check检查约束
用户根据自己需求添加的约束,MySQL不支持这种约束,认为这种约束会严重影响数据的插入速度。
例如:create table student(score tinyint check(socre>=0 and score<=100));
(6)foreign key(外键列(familyid)) references family(另一个表的主键列fid)外键约束
目的是为了确保两表之间建立关联,便于后期的查询,声明了外键约束的列,插入的值必须在另一个表的主键列中出现过
(注意事项:外键约束的列上允许插入null,外键列和对应的另一个表的主键列类型要保持一致(如int对int)
(7)auto_increment自增列
自动增长,声明了自增列,在插入的值的时候,只需要赋值为null就会获取当前的最大值然后加1插入
(注意事项:自增列必须添加在整数形式的主键列上,允许手动赋值)
10.其他说明
null是关键字,使用时不能加引号
多个约束可以同时使用,之间敲个空格即可
11.简单查询
查询特定的列
查询所有的列
给列起别名
as
显示不同的记录
distinct
查询时执行计算
查询结果排序
order by
asc(升序) / desc(降序)
条件查询
where
比较运算符
> < >= <= = !=
and(&&) / or(||)
is null/is not null
in()/not in()
模糊条件查询
% _
like
分页查询
两个已知条件
当前的页码
每页的数据量
开始查询的值=(当前的页码-1)*每页的数据量
limit 开始查询的值, 每页的数据量
注意:开始查询的值和每页的数据量必须是数值,不能加引号
12.复杂查询
聚合查询/分组查询
count()/sum()/avg()/max()/min()
group by
year()
子查询
多表查询
内连接
inner join on
左外连接
left outer join on
右外连接
right outer join on
全连接
mysql不支持
解决方案
union
union all
四、JS
1.数据类型(ES5)
原始类型
数值型,字符串型,布尔型,空null,未定义undefined【ES6新增:Symbol类型、bingint类型】
引用类型
2.数据类型转换
数值型+字符串——字符串
数值+布尔型——数值型
字符串+布尔型——字符串
强制转换——Number(),parseInt(),parseFloat(),toString()
3.%取余,/正常运算5/2=2.5
4.switch-case只能进行全等(===)的条件判断
switch(表达式){
case 值1:语句块1 break
case 值2:语句块2 break
.......
case 值n:语句块n break
default:语句块N+1}
5.While(循环条件){循环体}——停止循环用break
do{循环体}while(循环条件)——停止循环用break
6.for(初始值;循环条件;增量){循环体}
continue跳过并继续
break结束
7.return和break对比
return用于函数中,作用是结束函数的调用,不再执行函数体
break用于循环或者switch-case语句,用于结束对应语句
8.递归
function say(){console.log("从前有座山") say()}
9.如何面向对象:封装,继承,多态
10.斐波那契数列
function f(n){
if(n==1 || n==2){
return 1
}else{
return f(n-1)+f(n-2)
}
}
console.log(f(4))
11.函数提升优于变量提升
//c()
var c=3
function c(){
console.log(9)
}
c()//c is not a function
12.回调函数
把函数作为参数传递
function tao(madai){
console.log(1)
madai()
}
function nan(){
console.log(2)
}
tao(nan)
13.匿名函数自调用
;(function(){})()
14.系统函数
isNaN()检测一个字符串中是否含有非数字
有,返还true
没有,返还false
eval()执行字符串中表达式
15.js中的对对象
自定义对象
内置对象:js提供的对象
宿主对象:根据执行环境划分
浏览器dom
在浏览器中存在兼容性问题
node.js------mysql对象
在node.js中因为因为只有node一种环境,所有不用考虑兼容问题
16.访问对象中的属性
对象.属性名
对象[属性名]
17.对象遍历
for(var k in user){console.log(k,user[k])}
18.栈内存和堆内存(地址传递)
原始类型的数据为栈内存
数值型,字符串型,布尔型,空,未定义型
引用类型的数据为堆内存
比如对象,函数,数组
19.数组遍历(ES5)
for(var i=0;i<arr.length;i++){console.log(arr[i])}
【ES6】array.forEach(element => { });
20.数组API
toString()数组转字符串
reverse()翻转数组元素
sort()对数组进行排序,默认是按首字母的编码顺序
join()将数组转换为字符串,可以指定连接符
arr0.concat(arr1,arr2)拼接多个数组
slice(start,end)截取数组元素,左闭右开,返还截取的元素
start开始的下标,end结束的下标,左闭右开——end为空时截取到最后
splice(start,count,v1,v2...)删除数组元素
start开始的下标
count删除数量count为空时删除到最后
v1,v2将继承开始的下标向后延续
push()在数组末尾添加元素,返还数组长度
unshift()在数组开头添加元素,返还数据长度
shift()删除数组开头一个元素,返还删除元素
indexOf()检测数组中是否含有某个元素,返回下标,找不到返还-1
21.字符串对象API
length获取字符串长度
charAt查找下标对应的字符等价于字符串[下标]
indexOf()
lastindexOf()
slice()
split()将字符串转为数组,每个字符串是一个元素,需要指定分割符
面试题
翻转字符串abcdef->fedcba
var n="abcdef"
console.log(n.split("").reverse().join(""))
英文字母转大写toUppertCase()
英文字母转小写
toLowerCase()
22.Math对象API
Math.PI——获取圆周率
Math.abs()——获取绝对值
Math.pow(x,y)——获取x的y次方
Math.random()——获取随机数,范围【0,1)
Math.ceil()——向上取整
Math.floor()——向下取整
Math.round()——四舍五入
Math.max()
Math.min()
23.Date对象(堆内存)
计算机元年1970年1月1日0:0:0:0
new Date()获取当前时间
new Date(时间戳)
d.getFullYear()
d.getMonth()+1【月份0-11对应1-12月】
d.getDate()
d.getHours()
d.getMinutes()
d.getSeconds()
d.getMillisecond()毫秒
d.getDay()星期0-6对应日-六
d.getTime()获取时间戳
Date.now()获取当前操作系统时间戳
设置日期时间
setFullYears()/setMonth()/setDate()/setHours()/setTime()/setHours()/setMintes()/setSeconds()...
转换为本地字符串
d.toLocalString()
24.Number对象
Number()
toFixed(n)保留小数后n位
25.赋值执行顺序是从右向左进行的
五、ES6正式开始
1.ES6(ECMAScript6)JS的第六套标准规范
(1)块级作用域:let声明的变量不允许重复声明,let声明的变量存在提升(存在暂存死区),但不允许访问,大括号之 间的语句就是块级作用域
const声明的变量专门用来声明常量,不能重复声明,声明了就必须赋值,存在块级作用域中
(2)可以给参数设置默认值了:
function add(a=0,b=0,c=0){}
(3)箭头函数:对匿名函数的简化,和匿名函数不完全一样
()=>{}
如果箭头函数只有一行代码并且是return可以省略花括号和return,例如:(a=>console.log(1))()
(4)模板字符串 `${}`
2.对象
全局对象
global(在浏览器下为window)
console对象
在浏览器下输出
console.log()打印日志
console.warn()打印警告
console.info()打印消息
console.error()打印错误
console.time()开始计时
console.timeEnd()结束计时
process对象
进程:计算机运行的每个软件都可以成为进程,进程有相应的CPU,内存的消耗
process.arch查看CPU架构
process.platform 查看操作系统
process.pid 进程编号
process.kill(“进程编号”)结束指定编号进程
Buffer对象
buffer缓冲区,是内存中临时存储数据的空间
module对象
每个文件就是一个模块,每个模块是一个独立的功能体
require("./eye.js")引入模块
module.exports={myA:a,myB:b}暴露对象
3.路径
console.log(__filename)//当前对象的绝对路径+模块名称
console.log(__dirname)//当前对象的绝对路径
4.模块
自定义模块
核心模块
第三方模块
会在目录下寻找package.json文件中main 对应的文件,找不到的话,会自动寻找index.js
例如:require("tao")会自动去node_modules目录下去寻找,找不到不断往上一级去寻找0
5.npm
npm init -y初始化,生成项目描述文件package.json,记录项目相关信息
npm install 包的名称
例如:npm i express;npm i -g nodemon;npm install mysql
npm i 会下载package.json和'package-lock.json中记载的文件
6.网址URL
协议+域名或者IP地址+端口号+文件的路径名+?查询的字符串
7.定时器(异步)
一次性定时器:setTimeout(function(){console.log("boom")},3000)
清除clearTimeout()
周期性定时器:setInterval(回调函数,间隔时间)
清除clearInterval()
立即执行定时器
setImmediate(function(){})
clearImmediate()
process.nextTick(回调函数)
注意:process.nextTick()会插队setImmediate(),会先执行
8.文件系统模块
fs.readFile()读取指定文件中的内容
fs.writeFile()用来向指定文件中写入内容
9.同步stateSync与异步async
10.服务器编写与路由编写例子
例子
server.js
//引入express模块
const express=require("express")
//建立WEB服务器
const app=express()
//引入路由器
const userRouter=require("./router/user.js")
//建立端口8080
const port=8080
app.listen(port,()=>{
console.log("服务器连接成功,端口号:"+port)
})
//中间件...
//将post传递的参数转换为对象
app.use(express.urlencoded({
extended:false
}))
//设置路由器路径
app.use("/v1/consume",userRouter)
//静态托管
app.use(express.static("./public"))
//设置错误处理中间件
app.use( (err,req,res,next)=>{
if(err){
console.log(err)
res.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:"consumedb",
connectLimit:15
})
//暴露连接池
module.exports=pool
user.js
//引入express模块
const express = require("express")
//引入连接池模块
const pool = require("../pool.js")
//创建路由器
const r = express.Router()
//暴露路由器
module.exports = r
//路由的编写
//消费记录查询
//初始化页面,消费记录查询页面,需要按录入的消费日期降序排列
//http://127.0.0.1:8080/v1/consume/select?limit=5
r.get("/select", (req, res, next) => {
let obj = req.query.limit
let n = parseInt(obj)
//未传n参数也会报错,因为n没有设置默认值,如果用户不传值,就是NAN
n = n ? n : 10 //有值用值,无值使用默认值10
let sql =
"select consumeName,consumePrice,consumeCount,consumeDate,consumeType from consumeInfo order by consumeDate desc limit ?"
pool.query(sql, [n], (err, result) => {
if (err) {
next(err)
return
}
res.send(result)
})
})
//添加消费信息
//当点击“录入消费信息”链接时,跳转到添加消费记录页面consumeAdd.html,进行非空验证
//http://127.0.0.1:8080/v1/consume/add
r.post("/add",(req,res,next)=>{
let obj=req.body
let consumeName=obj.consumeName
let consumePrice=obj.consumePrice
let consumeCount=obj.consumeCount
let consumeDate=obj.consumeDate
let consumeType=obj.consumeType
if(!consumeName){
res.send({code:201,msg:"商品标题不能为空!"})
}
if(!consumePrice){
res.send({code:201,msg:"商品价格不能为空!"})
}
if(!consumeCount){
res.send({code:201,msg:"商品数量不能为空!"})
}
if(!consumeDate){
res.send({code:201,msg:"消费日期不能为空!"})
}
if(!consumeType){
res.send({code:201,msg:"消费类型不能为空!"})
}
let sql="insert into consumeInfo set ?"
pool.query(sql,[obj],(err,result)=>{
if(err){
next(err)
return
}
res.send({code:200,msg:"消费记录录入成功!"})
})
})
五. git
git config --global uer.name "用户名"
git config --global user.email "用户邮箱"
git init 初始化仓库
git status查看git仓库状态
git add 文件名称或者全部添加git add .
提交git commit -m "提交说明"
git log查看所有提交日志
git reset --hard 提交的ID
clear清屏
copy复制,paste粘贴
git reflog查看所有提交的日志已经回退记录等
git branch 查看所有分支
git checkout 分支名称 切换分支
git merge 分支名称(所写分支与当前分支合并)
git clone 克隆
git push 推送
git pull 拉取
git remove -v查看远程仓库别名
git remove add 别名 链接
git branch -d 分支名称
删除已经合并的分支
git branch -D 分支名称
强制删除分支,不管是否合并
六、HTML5
加粗<b></b> <strong></strong>
倾斜<i></i> <em></em>
下划线<u></u> <ins></ins>
删除线<del></del> <s></s>
平方 x<sup>2</sup> x的平方
下角标 x<sub>1</sub>
版权声明圈C
©
注册商标圈R
®
商标符号TM小写的
™
关闭符号X
×
带圈的关闭符号
⊗
空格
小于
<:
大于
>
预格式化标签
<pre></pre>
去掉table表格的边框间距
style="border-collapse:collapse;"
colspan="n"
跨列,从当前单元格开始合并n个单元格
rowspan="n"
跨行,从当前单元格开始合并n个单元格
input
type
text
password
submit
radio单选
checkbox多选
checked默认选中状态
reset重置
date
range
month
week
url
search
email
number
min="10" max="30" step="2"
<textarea></textarea>
多行文本域
可加属性如:cols="20" rows="10" style="resize:none;"设置文本域大小用户不可调
<select></select>下来选择框,默认是单选,加multiple属性变成多选
<select><option value="1">选项一</option>(加selected设置默认选中状态)</select>
七、AJAX(AJAX是效果:不刷新页面更新网页)
let xhr=XMLHttpRequest()
xhr.onreadyStatechange()
readyState有五种取值
0:尚未初始化
1:正在加载中
2:加载完毕
3:正在处理
4:处理完毕
xhr.open(methed,url)
methed:"POST"/"GET"/"PUT"/"DELETE"
xhr.setRequestHeader("Content-type":"application/x-www-form-urlencoded;charset=UTF-8")
如果是post或者是put请求要记得加
xhr.οnlοad=function(){ let result=xhr.responseText console.log(result)
status
1xx提示性响应消息,服务器接受请求,需要客户端继续执行后续操作
2xx成功的响应消息
3xx请求需求转向另一个地址(重定向)
4xx客户端引起的错误
5xx服务器端运行错误
xhr.send()}
八、JSON语法规则
1.一段JSON格式的数据本质上是字符串
2.一段JSON字符串只能有一个根-这个根——这个根要么是对象"{}"要么是数组“[]”
3.一个JSON对象中,可以包含多个键值对,格式:“键名”:“键值”
4.JSON的键值可以是如下类型:“字符串”,数字,true/false,对象,数组,null
5.JSON中的键名和字符串键值必须用引号,而且是双引号
6.JSON中两个数据间的分隔符用逗号表示,但是最后一个数据后面不能加逗号
九、JSON
序列化
把服务器编程语言中的数据转换为JSON格式的字符串
let jsonString=JSON.stringify(obj)
反序列化
把浏览器中接收到的JSON格式的字符串转回js对象
let jsonDate=JSON.parse(jsonString)
十、CSS
1.W3C公司推出的
1996-CSS1
1998-CSS2
2005-至今CSS3
2.伪类选择器
:hover{}悬停触发
:active{}按住触发
:link{}未激活前状态
:visited{}激活之后的状态
a标签伪类元素的优先级排序
:link>:visited>:hover>:active
:focus{}获取焦点
3.伪元素
::before{content:"";}
指的是元素内容最开始的位置插入
::after{content:"";}
指元素内容最末尾的位置插入
4.选择器权重计算
标签和伪元素:1
伪类,属性类:10
id选择器:100
内联:1000
!important 10000
5.rgba()
6.opacity透明度
0-1取值
7.去除幽灵空白节点(img)
display:block
8.三角形写法
.sjx{width:0;border:100px solid transparent;border-top:red;}
9.怪异盒子模型
box-sizing:border-box
10.overflow
overflow:visible
默认允许溢出
overflow:auto
溢出方向出现拖动条
overflow:scroll
双方向出现拖动条
overflow:hidden
溢出隐藏,超出父元素范围的
11.如何形成BFC结界(子元素不会洒落出父元素)
1.overflow属性的三个值形成bfc结界:auto,scroll,hidden(BFC解决高度坍塌)
2.给父元素设置高度(解决高度坍塌)
3.给父元素也加float让父子元素同层(解决高度坍塌)
4.clearfix::after{
context:'';
display:block;
clear:both;
}
BFC结界一旦形成就能避免了父子组件粘连的问题
BFC结界一旦形成,重新计算在父元素内部浮动元素所占的高度,防止高度坍塌
12.背景图background-image
background-image:URL(路径)
重复方式
background-repeat:repeat -x
x轴方向平铺重复
background-repeat:repeat -y
background-repeat:no-repeat
不重复平铺
背景图定位
background-position
left bottom
-128 0
背景图大小
background-size:100% auto
background-size:contain(最长边占满为止)
background-size:cover(最短边占满为止)
background-image:linear-gradient(90deg,blue 10px, red 20px)(渐变色)
13.em父元素字体的倍数
rem根元素字体的倍数
14.定位position
z-index层级没有单位,值越大层级越高,可以为负数
相对定位relative
相对自己原来位置的定位
绝对定位absolute
参照距离自己最近的祖先元素的定位(证据是这个祖先元素存在定位属性),如果一直没有,就会找到根元素头上
固定定位fixed
参考HTML根元素的定位(浏览器的窗口)
15.谷歌浏览器默认字号16px,最小12px
font-size
font-family
font-weight
16.行高
line-height
17.span
文本修饰线
text-decoration:underline;下划线
text-decoration:none;无线条
text-decoration:line-through;删除线
文本溢出省略号三句话
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
首行缩进
text-indent:2em;
18.垂直对齐方式
vertical-align:top
vertical-align:middle
vertical-align:bottom
19.结构性伪类选择器
:nth-child(2)
odd奇数
even偶数
20.弹性布局
display:flex;
主轴的排序
flex-direction:row/column
flex-direction:row/column-reverse
换行表现
flex-wrap:nowrap
flex-wrap:wrap
flex-wrap:wrap-reverse
简写
flex-flow:row wrap
主轴对齐方式
justify-content:flex-start;
justify-content:flex-end;
justify-content:center;
justify-content:space-evenly
justify-content:space-around
justify-content:space-between
交叉轴对齐方式
align-items:flex-start
align-items:flex-end
align-items:center
多行交叉轴对齐方式(多行显示的前提是要换行flex-wrap:wrap)
align-centent:flex-start
align-centent:flex-end
align-centent:center
align-centent:space-between
align-centent:space-around
align-centent:space-evenly
收缩规则
flex-shrink项目中缩小的比例,默认值是1,不允许为负数
flex-grow项目中放大的比例,默认值是1,不允许为负数
flex-basis项目初始尺寸,设置之后主轴上设置的长度失效,以本属性设置的为准
简写
flex:放大 缩小 主轴尺寸
flex:1 0 200px
21.过渡
transtion:1s background-color, 1s 1s border-radius;
/*过渡 用1s过渡背景颜色 等待一秒,然后用1s过渡圆角
22.变换transform
平移函数
transform:translateX(20px);
transform:translateY(30px);
transform:translate(20px,30px);对应:【x,y】
如果只写一个默认是X
transfrom:translate(150px)
旋转函数:
z轴旋转:transform:rotate(-30deg)
x轴旋转:transform:rotateX(-10deg)
y轴旋转:transform:rotateY(20deg)
缩放
0-1缩小,大于一放大
transform:scaleX(2)
transform:scaleY(2)
transform:scale(2)【X,Y同时放大】
扭曲
transform:skewX(-40deg);
transform:skewY(-40deg);
transform:skew(-40deg);【X,Y同时扭曲】
以上函数可以同时使用
transfrom:rotate(10deg) scale(2)
23.动画
关键帧
@keyframes move{
0%{transform:translateX(0);}
100%{transform:translateX(300px);}
}
动画
animation:name duration;
关键帧名字 执行时间
十一、JS高级
【小常识:判断是否是闰年:(i%4===0&&i%100!==0)】
1.声明提升
声明操作(var/function) 会提升到作用域的顶部, 然后再执行代码
function: 整体提升 && 如果是函数表达式 不会提升
2.作用域: 一个具有特殊功能的对象类型
全局: window
局部: 函数运行时临时生成的对象, 函数执行结束后会销毁
3.作用域链
就近原则: 函数中使用一个变量, 优先使用自身声明的, 自己没有则到上层查找
4.闭包
为什么: 防止使用的来自其他作用域的变量被销毁
我们利用他: 规避全局变量污染, 制作私有的变量,缺点是会占用内存
5.arguments
保存所有函数收到的实参
6.函数的重载(技巧)
通过判断实参的类型 或 个数不同, 执行不同的逻辑代码
7.原型链:原型链是一条对象隐式原型不断往上指向的一条指向链,尽头是Object的隐式原型,也就是null
function Rect(length, width) {
var obj = {}
obj.length = length
obj.width = width
// 如何让 对象 obj 知道是哪个函数生的他
// 对象的 __proto__ 属性: 称为 原型链
// 对象通过 __proto__ 属性, 链接到他爸爸的原型
obj.__proto__ = Rect.prototype
return obj
}
// JS作者, 为构造函数提供了一个仓库, 用来存放公共的方法
// prototype: 原型, 就是公共的仓库
console.dir(Rect);
8.// 面试题: new运算符做了什么事?
// 再次创建矩形构造函数
function Rect(length, width) {
// new运算符会自动声明名字是 this 的变量
// this: 这个; 外国人理解: 这个对象
// var this = {}
// 对于外国人的意思: 这个对象 的 长度 = 长度;
this.length = length
this.width = width
// prototype是对象类型, 引用类型. 地址存储到 __proto__ 里
// this.__proto__ = Rect.prototype
// return this
}
9.默认的前缀是 window.
10.// 只要书写 'use strict' 在JS脚本的顶部, 那么其下方的代码就会进入严格模式
// 1. 没有用var声明过的变量, 不允许使用! -- 有效规避写错单词导致的全局污染
'use strict'
// 严格模式: 来自 ES5 -- JS第五个版本, 在2009年出版. 也称为ES2009
// 可以为JS开启严格模式: 很多存在风险的代码 书写时会产生报错, 辅助程序员写出更加健壮的代
码
10.this指向
对象.函数名() : 对象
函数名() : window
new 函数名(): 实例对象
11. var a = 10;
function test() {
// new触发: 隐式 var this = {}
this.a = 100;
}
var t = new test(); // 其中的this是实例对象
console.log("t:", t); //t: test {a: 100}
console.log(a); //10
test(); //直接触发, this 是window
console.log(a); //100
12.原型的继承操作
修改this指向
(1)暂时修改
call
临时借用: 先把函数存储到对象中, 然后调用, 删除
call: 所有的实参要1个一个传递
giveMoney.call(emp, 0.7, 2000)
apply
apply: 所有的实参放在数组里传递
giveMoney.apply(emp, [0.7, 2000])
应用场景: 可以把数组作为参数传递给 不接收数组做参数的函数
(2)永久修改
bind: 与call 和 apply 很相似
// call, apply: 会临时放在对象中, 然后立刻触发函数
// bind: 绑定. 函数和对象绑定在一起, 但是不会触发. 返回绑定完毕的新函数
var gm = giveMoney.bind(emp, 0.4, 5000)
console.dir(gm);
13.展开符...
... : 去掉[], 称为展开
14./ let/const 是否存在提升?
// 通常说法: let/const 不存在提升
// 准确答案: let/const 存在提升, 但是 提升之后处于`暂存死区`状态 -- 在声明代码未执行前,
变量不可使用
// 利用强制的报错: 规范程序员的行为 先声明 再使用
// Cannot access 'a' before initialization
// 无法访问a, 在 声明a的代码运行前
15.高阶函数
every
every: 每个, 用来检查数组中的每个元素 是否都满足条件
// 全真则真, 有假为假, 逻辑类似于 逻辑与 &&
var a = nums.every((value, index, array) => {
// 参数1: 当前元素
// 参数2: 当前元素的序号
// 参数3: 当前元素所在的数组, 即 nums
console.log('value:', value);
console.log('index:', index);
console.log('array:', array);
// 他们的关系: array[index] == value
// 返回值: 验证的结果 布尔类型
return value < 50
})
some
some: 一些, 判断数组中是否有一些满足条件的. 即只要有就行
// 类似逻辑运算符中的 逻辑或 || , 有一个为真就算真
filter: 过滤数组中的每一个元素, 把符合要求的过滤出来, 组成新的数组
var a = emps.filter(v => v.salary > 10000)
console.log(a)
${}: 就是在字符串中, 可以书写 JS 代码的范围
var words = `${sname}今年${age}岁, 明年${age + 1}岁`
console.log(words);
map
// map: 映射 - 按照一定的规则把数组的每个元素修改后 形成新的数组
var nums = ['mike', 'lucy', 'lily', 'kitty']
var a = nums.map(v => v.toUpperCase())
console.log(a)
forEach
遍历数组的方案:
for..in: 用于遍历对象类型的
reduce: 数组的元素整合, 最终得到一个值
16.解构语法
var phone = {
name: "iPhone13",
price: 7999,
desc: {
maker: 'Apple',
year: '2021.9'
},
tags: ['最佳cpu', 'iOS系统', '动态高刷']
}
// 要求: 解构出所有的属性
var { name: pname, price, desc: { maker, year }, tags: [t1, t2, t3] } = phone
console.log(pname, price, maker, year, t1, t2, t3);
17.Promise
// 面试必背概念:
// Promise 分三种状态
// pending: 准备状态, 刚new出来 还没执行
// fulfilled(已完成): 调用resolve之后进入
// rejected(被拒绝): 调用 reject 之后计入
// 状态切换, 只能是:
// pending -> fulfilled
// pending -> rejected
new Promise((resolve, reject) => {
// resolve: 解决, 代表成功
// 触发 resolve, 就会把其参数传递给 then中的函数
resolve({ msg: 'resolve被触发' })
// reject: 拒绝, 代表失败
// 触发 reject, 就会把参数传递给 catch中的函数
reject({ msg: "reject被触发" })
})
.then(res => {
console.log('res:', res);
}).catch(err => {
console.log('err:', err);
})
【async function(){ awaite function(注意:异步函数promise)】
18.正则表达式
正则表达式的字面量写法: 用 /正则表达式/
// 修饰符: /正则/修饰符
// g: global全局, 所有
var words = '壮壮666, 今天250 还是 520'
var r = /\d/g // 类似于 '' 是字符串, // 就是正则
console.dir(r) // direct:直接输出
// 字符串拥有一个 match 方法, 可以查询出符合正则要求的字符
// match: 匹配
var a = words.match(r)
console.log(a)
// 正则替换: 把字符串中指定的内容进行替换
var words = 'Hello壮壮, goodgay'
// 要求: 把英文换成 *
// replace: 替换
// 参数1: 正则 参数2: 要换成什么
var a = words.replace(/[a-z]/ig, '*')
console.log(a)
var phone = '18845987878'
// 需求: 中间4个数字改成*
// \d : 代表1个数字
// {n}: 代表n个
// () : 称为捕获组 -- 抓取正则表达式中的一部分, 序号从1开始数
var r = /(\d{3})(\d{4})(\d{4})/
//捕获组序号 1 2 3
var a = phone.replace(r, '$1****$3')
// 猜猜 $1 $3 什么意思? $n 就代表 第n个捕获组的值
console.log(a)
// 变化: xxx-xxxx-xxxx
var a = phone.replace(r, '$1-$2-$3')
console.log(a
// 用户输入手机号, 我们来验证是否正确
// prompt: 弹出一个提示框 手机用户信息
var phone = prompt('亲, 请输入手机号. 壮壮会尽快联系您')
console.log(phone)
// 正则验证
// 正则表达式.test(字符串)
// ^: 代表字符串开头
// $: 代表字符串结尾
// 第一位是1 第二位3-9 剩下9个数字, 一共11位
var r = /^1[3-9]\d{9}$/
// test: 测试 正则.测试(字符串)
// 验证字符串是否符合正则的要求
var a = r.test(phone)
console.log(a ? '合法手机号' : '手机号错误,壮壮很气哦');
十二、DOM
1.DOM核心理念: 找到他 -> 操作他
document.getElementById()
document.getElementsByClassName()
document.getElementsByTagName('h4')
document.getElementsByName('sex')
选择根元素:document.documentElement
document.body.firstElementChild.firstElementChild
document.body.children[0]
querySelector: 查单个, 返回值是对象本身
querySelectorAll: 查多个, 返回值是类数组, 拥有forEach 能遍历
document.querySelector('#zz')
document.querySelectorAll('.ok')
id: getElementById 返回值是一个元素
tag: getElementsByTagName 返回值类数组
class: getElementsByClassName 返回值类数组
name: getElementsByName 返回值类数组
2.自定义属性
<!-- 每个元素本身自带很多很多属性: 系统属性 -->
<!-- 自定义属性: 需要用 data- 来声明, 存储在 dataset 里 -->
<!-- 自定义属性名可以用 多个 - 讲个, 最终转成小驼峰 -->
<!-- y-zz-kk-kaka 转为 yZzKkKaka -->
<a data-x="鹏鹏" data-y-zz-kk-kaka="壮壮" data-z="边边" href="http://tmooc.cn"
id="a1" class="danger">tmooc</a>
<script>
const a1 = document.querySelector('#a1')
console.dir(a1) //后台找到这些属性
// 读取自定义属性:
console.log(a1.dataset.x);
自定义属性
语法: data-属性名=值
读取: dataset.属性名
3.事件冒泡
事件的冒泡机制: 当子元素发生事件, 会传递给父元素
4.事件委托
事件冒泡机制: 元素上触发的事件,会传递给父元素
事件委托: 通过父元素 帮子元素完成事件
适用场景: 子元素动态新增
注意: 父元素可能有很多子元素, 所以需要做判断 来针对某一类子元素做事
box.onclick = function (e) {
console.log('box: 侦测到点击');
// 事件触发的当事人(元素)
console.log('target:', e.target)
// 判断: 如果是子元素 img 触发的, 才变圆
console.dir(e.target)
//后台查看: 哪个属性能够判断是 图片标签??
// 有三个属性: localName : 值是全小写
// nodeName tagName : 值是全大写
if (e.target.localName == 'img') {
e.target.style.borderRadius = '50%'
}
}
事件参数中, target 属性代表触发事件的当事人
5.阻止默认事件
const a = document.querySelector('a')
// 默认情况: 点击 a 触发 href 的跳转操作
a.onclick = function (e) {
// 事件参数中, 包含很多事件相关的属性
// prevent:阻止 default:默认
// preventDefault: 阻止默认事件的发生
e.preventDefault()
alert("访问Tmooc")
事件监听器
}
6.事件监听器
// 团队合作时: 多人同时为一个按钮添加不同的事件
const btn = document.querySelector('button')
// onclick: 是一个属性, 同一时间只能存储一个函数
// 后赋值的覆盖之前的值
//1
btn.onclick = function () {
alert("范凯喜欢壮壮")
}
//2
btn.onclick = function () {
alert('东东喜欢壮壮')
}
// addEventListener: 可以为一个事件绑定多个函数
// 参数1: 事件名 (没有on) 参数2:相关的函数
btn.addEventListener('click', function () {
alert('边边喜欢壮壮')
})
btn.addEventListener('click', function () {
alert('浩浩喜欢壮壮')
})
// 面试题: 为DOM元素绑定事件的方式有哪些?
// onclick 或 事件监听器
// 面试题: 有什么区别
// onclick: 只能绑定一个
// 事件监听器: 可以绑定多个事件
7.页面滚动事件
scrollTop: 滚动 顶部 -- 滚动距离顶部的偏移量
// 版本原因: 旧版本从body中读, 新版本从 documentElement读
// 用户的浏览器是新的还是旧的不知道, 所以从左到右, 哪个能读到 就用哪个
const y = document.body.scrollTop || document.documentElement.scrollTop
console.log('y:', y);
十三、BOM
BOM
// open(要打开的网页地址, 打开方式)
// 打开方式: _blank新标签 _self:当前标签
open('http://www.baidu.com', '_self')
location.reload()刷新
location.replace('http://tmooc.cn')替换网址
history.forward()前进
history.back()后退
history.go(1)前进
history.go(0)刷新
history.go(-1)后退
十四、jquery
// 函数重载技巧: 函数根据参数的个数/类型不同, 做不同的事
// 参数是对象类型: 用于同时设置多个样式
$('div').css({
// css的属性名存在大量的 -
// 但是JS中, - 是变量名的非法字符, 所以两个方案:
// 要么用字符串代表, 要么改成小驼峰
'font-size': '30px',
backgroundColor: 'blue',
'border-radius': '10px',
margin: '5px'
})
$('#box span').click(function () {
// this: 原生的DOM元素, 代表当前点击项
// this.classList.toggle('active')
console.log(this)
// 要想用JQ提供的方法, 就需要把原生DOM元素转成JQ的
// $(DOM元素): 转为JQ类型的对象
console.log($(this))
// $(this).toggleClass('active')
// 排他:
// siblings: 兄弟姐妹
// 当前项.添加样式.兄弟项.移除样式
$(this).addClass('active').siblings().removeClass('active')
})
选择器简单: 写法 和 判断
$ 代替 document.querySelectorAll
判断: 无需判断单个还是多个, 都用同一个选择器写法$
自带遍历:
JQ提供的各种方法, 都会自动遍历查找出来的元素, 挨个做操作
函数重载技巧:
同一个方法, 传递不同的参数 个数/类型, 出现不同的效果
class操作
addClass: 添加
removeClass: 删除
toggleClass: 切换
hasClass: 判断有没有
siblings(): 查询到所有兄弟元素
<a href="http://tmooc.cn" title="Hello Tmooc" id="a1" class="danger" data-xx="XXX"
data-yy="YYY">Tmooc</a>
<script src="./vendor/jquery-3.6.0.js"></script>
<script>
// 属性分两种: 系统的 和 自定义的
// 原生读取方式分 直接读 和 getAttribute
const $a = $('a')
// 底层是: a.href 的读法
console.log($a.prop('href')) //property: 属性,资源
// attribute: 属性, 底层是 a.getAttribute('href')
console.log($a.attr('href'))
// 总结: prop 用的更多
// 自定义属性: 原生 元素.dataset.xx
console.log($a.data('xx'))
console.log($a.data('yy'))
// 修改: 两个参数是修改
$a.prop('title', '晕晕')
$a.attr('id', 'aaaa')
lt: 小于
gt: 大于
eq: 等于
兄弟关系
next:下一个兄弟
prev:上一个兄弟
// 期望: 点击英雄后, 替换
$('#heros img').click(function () {
// replace: 替换
// with: 和...
// clone: 克隆, 即 复制元素
$('h2+img').replaceWith($(this).clone())
})
更多的选择器
上方的兄弟们: prevAll
下方的兄弟们: nextAll
内容中包含: contains
准备就绪
当在外部JS文件中书写, 需要把代码放在 $(function(){ }) 中执行
使用外部JS文件, 理论上 应该在body的最后进行引入.
防止使用者 在head 中引入, 导致DOM未加载前 就使用了JS的情况
输入框事件
焦点 focus
失去焦点 blur
变化 change
实时变化 input
作者没有封装对应函数, 需要使用通用事件绑定语法: on
键盘 keyup
通过事件参数 读取按键编号 keyCode 区分按键, 13是回车
新增子元素: append
委托: 通过on 携带3个参数实现
on(事件名, '选择器,选中指定的子元素', 回调函数)
this指向:修改为触发事件的当事元素
委托模式适合场景: 动态新增的子元素
删除元素: remove
克隆: clone 复制元素
替换: replaceWith
ajax:
get请求: $.get(请求地址, 回调函数) 回调函数接收到数据
十五、跨域问题
同源策略:浏览器的安全策略,URL有三个基本组成部分:协议+ip/域名+端口号,三者必须完全相同称之为同源
协议+ip/域名+端口号
不满足同源策略就是跨域
vue如何处理跨域
@vue/cli@5.0 配置vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
// 配置代理服务器
proxy: {
// 自定义请求头,指定是有 /demo 开头的请求都是用代理服务器
'/demo': {
// 往哪个服务器请求
target: 'http://localhost:3000/',
pathRewrite: {
// 去掉请求路径中的 /demo
"^/demo": ""
}
},
}
}
})
注意:在启动脚手架的时候会启动一个内置的web服务器,同源策略是浏览器的行为,而服务器和服务器之间发请求不存在跨域,所以我们配置代理实际由内置的web服务器中转了请求,此种方式仅局限于开发阶段
@vue/cli@4.5 默认没有vue.config.js,需要手动创建
module.exports = {
devServer: {
proxy: {
'/demo': {
target: 'http://localhost:3000/',
pathRewrite: {
"^/demo": ""
}
},
}
}
}
cors模块
const express = require('express')
// 安装cors模块: npm i cors 在my-server目录下执行
const cors = require('cors')
明日安排
说完express的 代理解决跨域
开始Vue阶段
jQuery特点: 通过封装技巧, 简化了DOM的代码
Vue特点: 通过自动化技巧, 让你不用写DOM代码 一样能做项目!
const app = express()
app.listen(3000, ()=>{
console.log('服务器开启成功!');
})
app.use(express.static('public'))
// 在所有接口前书写:
// app.use(cors()) //解决跨域: 允许所有来源
// 白名单: 指定某几个
app.use(cors({
// 把允许的域名放在数组里即可
origin:['http://127.0.0.1:3000', 'http://127.0.0.1:5500']
}))
跨域: 如果网页通过ajax请求数据, 数据所在的接口服务器和当前网页非同一个, 就会触发浏览器的同源
策略
解决方案:
CORS: 最推荐 -- 在服务器上添加一个白名单, 如果发送请求的来源 属于白名单范围, 就能正常访问,
不会被拒绝
PROXY: 代理 -- 适合服务器代码不可修改的场景
例如: 使用斗鱼的接口, 但是遭遇跨域报错 -- 无法修改
创建文件夹 my-server
在my-server 下执行: npm init -y 初始化
再执行: npm i express 安装express模块
再执行: npm i cors 安装跨域模块
再执行: npm i express-http-proxy 代理模块
proxy代理
const express = require('express')
// 跨域
const cors = require('cors')
// 代理
const proxy = require('express-http-proxy')
const app = express()
// 启动代理服务器: nodemon app.js 或 node app.js
app.listen(3000, ()=>{
console.log('服务器启动完毕!');
})
app.use(cors())
// 代理负责转发请求, 必须放在跨域 下方书写
// 所有访问 /dy 接口的请求, 都进行转发
// 即 localhost:3000/dy
app.use('/xyz', proxy('http://dy.xin88.top'))
//http://localhost:3000/xz/data/product/index.php
app.use('/xz', proxy('http://www.codeboy.com:9999'))
// 范式:
// app.use('接口地址', proxy(要代理到的网站))
服务器传给同源的服务器,同源的服务器再传给浏览器
————————————————————————————————
注意小错题
<!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>
<button id="btn" class="danger">按钮</button>
<script>
let student = {
className: "软件版",
say() {
console.log("我的名字是" + this.className);
return undefined; //不写return,系统会自动在后面加return undefined
},
};
//btn.onclick = student.say();//btn.οnclick=undefined//赋值操作从右向左进行
// btn.onclick = student.say;
// btn.onclick = function () {
// student.say();
// };
// btn.onclick = function () {
// student.say;
// };
</script>
</body>
</html>