前端:用户可见的界面,数据展示在页面上给用户看到
后端:分为服务器端和数据库
- 服务器端:把前端要展示的数据存储到数据库中,前端需要时把数据库的数据再传递给前端
(服务器端:我们学习php语言,php语言运行在apache服务器上)
- 数据库:一个存储数据的仓库(mysql),可以让后端进行数据的增删改查(mysql)

展示方面:前端之间看到,布局,图文,交互和特效。
后端没办法直接看到,数据存取,业务逻辑
使用技术:前端HTML5,Css3,javascript,Ajax,vue,react
后端java、php、python、算法,数据库,服务器
工作职责:前端web前端开发,移动端和小程序
后端业务逻辑实现,功能接口实现
-
我们是一个 前端开发工程师
-
还有一个工作叫做 后端开发工程师(JAVA,PHP,nodejs)
-
我们一个网站的组织架构基本上由下面的步骤完成
用户 => 前端 => 后端 => 数据库

比如: 我们浏览一个新闻网站
1)用户输入网址
2)前端人员就要把对应的页面给到用户,在页面打开的过程中,想后端人员索要新闻信息
3) 后端人员接收到前端人员索要新闻信息以后,就去数据库中找到对应的新闻信息数据给前端人员
4) 前端人员接收到后端人员给的新闻信息以后,使用我们的办法吧新闻信息数据渲染在页面上
5) 页面就打开了,用户就可以看到一个新闻网站了
再比如:
用户登陆一个网站
1) 当用户书写完表单内容以后,点击提交按钮的时候
2) 前端人员拿到用户填写的内容,把数据整合好传送给后端人员
3) 后端人员接收到数据以后,去数据库中进行比对,看看有没有对应的数据
4) 然后告诉前端人员,你给我的用户名和密码是否正确
5) 前端吧信息反馈给客户看到
- 如果正确就是跳转页面
- 如果不正确提示用户名或者密码有问题
一、为什么要用服务器:
我们不可能把所有的网页数据全部存储到电脑上,第一不安全,第二太大。
所有我们把前端需要的数据存放在网路的另一端,需要的时候通过网络来进行请求。
二、什么是服务器
它就是一个电脑,当他跑起来一些程序的时候,就是一个服务器。
我们的电脑也能变成一个服务器,只要跑一些特殊的程序就可以,只不过它没有专业的服务器运算,
存储的能力强
常见的服务器软件:
目前常用的服务器就是Apache和Tomcat
我们要学习的服务器就是apache,它是php的运行环境
服务器语言端除了PHP还有,JSP(java),ASP,python,nodeJS,go等等。
PHP:personal home page;
三、服务器是通过什么被访问
什么是ip地址:
为计算机网络相互连接进行通信而设计的协议。具有唯一性
什么是域名:
域名:每一台计算机都有一个唯一ip地址,特别难记,所以出现了今天的(域名)。像www.baidu.com
端口号:简单理解为当你使用ip地址访问到电脑以后,帮你确定访问的是哪一个服务器软件
https://www.baidu.com:443
协议 域名 端口号
http协议的默认端口号是80
https协议的默认端口号是443
端口:服务器端也有文件夹(0-255)
文件夹内部有子文件夹,(0-255)
0~ 605535 多个端口
-
php是一门后端语言。是一门服务端语言。运行在服务器端
-
.php是PHP的后缀,我们能看懂代码即可
-
主要目标是允许web开发人员快速编写动态网页
一句话概括:PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。
为什么要学习一个后端语言呢?
-
目前市场上的需求,要求前端人员掌握一个后端语言
-
方便和后端开发人员进行交互
-
补充:服务器端除了PHP还有JAVA, JSP,python,nodejs,go等语言。
PHP优点:
-
跨平台,同时支持多种数据库(mysql(关系型数据库),MongoDB(非关系型数据库))
-
安全性和效率好
-
使用成本低
-
相比其他后端语言,简单易学
缺点:
- 安装比较复杂,配置比较多,太灵活
PHPStudy(PHP运行环境一键安装包)PHPstudy是搭建服务器的工具,我需要把我写的php代码放在phpstudy工具的WWW目录下,‘www’就是服务器的目录,即放置项目代码的目录。
自己的计算机访问自己的服务器,可以在地址栏里输入locahost或者127.0.0.1
一、注意点
- PHP 脚本可放置于文档中的任何位置。PHP 脚本以 <?php* 开头,以 *?> 结尾:
<?php
// 此处是 PHP 代码
?>
-
PHP 文件的默认文件扩展名是 “.php”
-
PHP语句以分号结尾;
-
PHP 代码块的关闭标签也会自动表明分号(因此在 PHP 代码块的最后一行不必使用分号)
二、PHP中的注释
PHP 代码中的注释不会被作为程序来读取和执行。它唯一的作用是供代码编辑者阅读。
PHP支持三种注释:
<?php
// 这是单行注释
# 这也是单行注释
/*
这是多行注释块
它横跨了
多行
*/
?>
三、PHP变量
变量是存储信息的容器:
<?php
$x=5;
$y=6;
$z=$x+$y;
echo $z;
?>
**注释:**请把变量视为存储数据的容器。
变量规则:
-
变量以 $ 符号开头,其后是变量的名称
-
变量名称必须以字母或下划线开头
-
变量名称不能以数字开头
-
变量名称只能包含字母数字字符和下划线(A-z、0-9 以及 _)
-
变量名称对大小写敏感($y 与 $Y 是两个不同的变量)
四、PHP输出
-
echo和print之间的差异
-
echo能够输出一个以上的字符串
-
print只能输出一个字符串,并始终返回1
-
echo 比 print 稍快,因为它不返回任何值。
<?php
echo "<h2>PHP is fun!</h2>";
echo "Hello world!<br>";
echo "I'm about to learn PHP!<br>";
?>
展示如何用 echo 命令来显示字符串和变量:
<?php
$txt1="Learn PHP";
$txt2="W3School.com.cn";
$cars=array("Volvo","BMW","SAAB");
echo $txt1;
echo "<br>";
echo "Study PHP at $txt2";
echo "My car is a {$cars[0]}";
?>
五、PHP的数据类型
三大类:
-
基本数据类型1.1 整型1.2 小数1.3 布尔类型1.4 字符串
-
复合数据类型2.1 数组类型2.2 对象类型
-
特殊数据类型3.1 null
六、PHP字符串
var_dump() 会返回变量的数据类型和值
字符串可以是引号内的任何文本。您可以使用单引号或双引号:
<?php
$x = "Hello world!";
echo $x;
echo "<br>";
$x = 'Hello world!';
echo $x;
?>
七、PHP整数
整数是没有小数的数字。int
<?php
$x = 5985;
var_dump($x);
echo "<br>";
$x = -345; // 负数
var_dump($x);
echo "<br>";
?>
八、PHP 浮点数
浮点数是有小数点或指数形式的数字。float
<?php
$x = 10.365;
var_dump($x);
echo "<br>";
?>
九、PHP逻辑
逻辑是 true 或 false。
$x=true;
$y=false;
var_dump($x);
十、PHP数组
数组在一个变量中存储多个值。
$arr = array('hello','hi','world')
for($i =0;i<count($arr);$i++){
echo $arr[$i].'<br>';
}
<?php
$cars=array("Volvo","BMW","SAAB");
var_dump($cars);
?>
十一、PHP与前端交互(重点)
PHP接收前端的数据
$_GET[‘参数名’]
$_GET['username']获取usersname
$_GET['password']获取password
$_POST[‘参数名’]
$_REQUEST['参数名']
请求参数有中文的解决方案:
header('Content-type:text/html;charset=utf-8');
<?php
header('Content-type:text/html;charset=utf-8');
$nick = $_GET['name'];
?>
一、数据库的概念
概念:数据库是按照数据结构来组织,存储和管理数据的仓库。一个数据库时由多张数据表组成的。
库:仓库
表:一个仓库被分为了很多的部分,很像类 (Student)
字段:很像类的属性 ( id name sex password)
每个字段的数据类型:
int–>整数类型
float–>浮点数
char–> 定长字符串
varchar—>变长字符串
blob—>二进制类型
date–>日期类型


二、常见的数据库
关系型数据库
oracle、mysql、SQLServer、DB2、sybase
非关系型数据库
Redis、HBAse、CouchDb、MongoDB
三、MySQL的使用
使用工具:phpstudy 。点击mySQL管理器,选择MYSQl-front,进入SQL编辑器
-
创建数据库:鼠标右键(可视化面板) 代码:create database 数据库名
-
打开一个库 use mydb
-
创建表:
create table students(
id int not null primary key AUTO_INCREMENT,
name varchar(8) not null,
sex char(4) not nul,
age tinyint not null
)
primary key: 表示唯一的主键
id int not null primary key AUTO_INCREMENT,
- 增加一条记录
insert into student(username,userpass) values('张三丰','123');
- 删除
delete from student where username='张三丰
- 查询
select * from student where username='张' and usersex='男'
查询出来的是一个表格的形式
- 改
update student set usersex='女' where username='张三丰'
练习:
- 新增insert [into] 表名[{列名1,列名2,…}] values (值1,值2)
例如:
insert into students(name,sex,age) values('孙丽华','女',21)
- 查询select 列名称 from 表名称[查询条件]
select name,age,from students;
select* from students;
select* from students where age>12
select* from students where name like '%王%'; 模糊查询
select* from students where id<5 and age>20
- 删除
delete from 表名称 where 删除条件;
delete from students;删除表中的所有数据
delete from students where id=2;删除表中id为2的数据
delete from students where age<20;删除表中年龄小于20
- 修改update 表名称 set 列名称=新值 where 更新条件
update students set age = age+1
update students set name='张伟鹏',age=19 where tel='13067999999'
四、创建数据库和表
练习:
五、PHP连接MySql
一、连接数据库:mysqli_connect();
语法:mysqli_conncet(servername,username,password,dbname);
参数:
-
servername:规定要连接的服务器的名称:默认是’localhost:3306’
-
username:规定登录所使用的用户名,默认值是拥有服务器进程的用户
-
password:规定登录所用的密码,默认是’’
-
dbname:表示式数据库名
返回值:返回一个代表到 MySQL 服务器的连接的对象。
示例:
$con = mysqli_connect('localhost','root','root','mydb')
if(!$con){
echo('连接失败')
}else{
echo('连接成功')
}
二、增加内容:
给students表中插入数据
$sql = 'insert into student(username,password) values("1988","洪七公")'
mysqli_query($conn,$sql)返回插入成功还是失败. 成功返回true。失败返回false
if(mysqli_query($conn,$sql)){
echo '新记录插入成功'
}else{
echo 'error'.$sql.'<br>'.mysqli_error($conn)
}
mysqli_num_rows()表示影响行的个数
$rowCount = mysqli_num_rows($result);
if ($rowCount==0) {
echo '登录失败,用户名或者密码错误';
}else{
echo '<script>location.href="http://www.baidu.com"</script>';
}
三、查询:
$sqlstr ='select*from student';
$result = mysqli_query($conn,$sqlstr);//执行查询后的sql语句后,返回的是查询的结果
查询行:$query_num = mysqli_num_rows($result)
查询列:$query_cols = mysqli_num_fields($result)
$query_row = mysqli_fetch-array($result);拿出结果集中的某一行,返回的是拿到的行
函数返回结果集中行的数量:mysqli_num_rows(result);
函数返回结果集中字段(列)的数量:mysqli_num_fields(result)
函数从结果集中取得一行作为关联数组:mysql_fetch_array(result)
六、前后端交互
1、接收前端发来的数据
2、逻辑处理
3、响应数据
注册
// 接收前端数据
header('content-type:text/html;charset=utf-8');
$name = $_POST['username'];
$pass = $_POST['password'];
//连接数据库
$con = mysqli_connect('localhost','root','root','my2102');
// 处理逻辑
if ($con) {
$sql = 'insert into book(username,userpass) values("'.$name.'","'.$pass.'")';
//执行插入语句,返回的是布尔值
$result = mysqli_query($con,$sql);
}else{
echo '连接失败';
}
// 响应
if ($result) {
echo '注册成功';
}else{
echo '注册失败';
}
mysqli_close($con);
登录
header('content-type:text/html;charset=utf-8');
// 接收前端数据
$username = $_POST['username'];
$password = $_POST['password'];
// 处理逻辑
// 1. 连接数据库
$conn = mysqli_connect('localhost','root','root','my2102');
if ($conn) {
echo '连接成功';
$sql = 'select * from book where username="'.$username.'" and userpass="'.$password.'"';
执行查询语句,返回的是一个表格,需要通过mysqli_num_rows($result)来查看影响了多少行
$result = mysqli_query($conn,$sql);
}else{
echo '连接失败';
}
// 响应
mysqli_close($conn);
$rowCount = mysqli_num_rows($result);// mysqli_num_rows: 影响行的个数
if ($rowCount) {
echo '<script>location.href="http://www.baidu.com"</script>';
}else{
echo '用户或者密码错误';
}
AJAX(Asynchronous Javascript And XML)是异步的javascript和XML
传统网站中,如果需要更新页面内容,必须重载整个网页页面。
ajax是可以在不刷新加载整个页面的情况下,对网页的某部分进行更新。
网站欣赏:
http://www.baidu.com
https://juejin.cn/backend
http://www.toutiao.com
同步交互:客户端向服务器端发送请求,必须等到结果返回,才能进行其他的业务操作
异步交互:客户端向服务器端发送请求,不必等到结果返回,就可以进行其他的业务操作。


AJAX的核心对象是XMLHttpRequest,即AJAX的异步操作,和服务器交互主要依赖该对象。

以前浏览器负责显示页面和发送请求接收响应(和后端交互)。两件事情同一时刻只能做件,没法同时进行。这样会让用户感觉不好(友好性不好),比如:当浏览器发送请求时,就没法显示内容,这时浏览器中是空白显示,给用户的感觉不好。
现代浏览器,使用XMLHttpRequest对象,可以把浏览器解脱出来,可以让浏览器只负责显示,而完成请求的事情由XMLHttpRequest对象负责。这样两者各负其责,效率更高,效果更好,用户体验很好,用户永远不会看到浏览器空白。
XMLHttpRequest的属性
属性解读:
在客户端与服务器的通信过程中,
XMLHttpRequest.readyState 体现着当前请求以及服务端响应的状态。
它的值有
0:初始化,XMLHttpRequest对象还没有完成初始化
1:载入,XMLHttpRequest对象开始发送请求
2:载入完成,XMLHttpRequest对象的请求发送完成
3:解析,XMLHttpRequest对象开始读取服务器的响应
4:完成,XMLHttpRequest对象读取服务器响应结束
xhr.readyState属性值是0、1、2、3、4。其中状态4代表响应完成。
-----------------------------------------------------------------------
服务器响应完成之后,我们通常会使用 XMLHttpRequest.status代表响应中的数字状态码。
代表着我们的 Ajax 请求的状态成功与否。
200 服务器已经成功处理了请求并响应到网页
404 请求失败,请求所希望得到的资源未被在服务器上发现(一般都是请求路径的错误)
500 服务器遇到错误,无法完成请求
1、创建XMLHttpRequest对象
var request = new XMLHttpRequest();
2、设置请求参数
xhrReq.open(method, url, async);
method: 代表HTTP请求的方法名,比如 GET、POST。
url: 代表着要想向其发送请求的 url。
async: 表示是否异步。true代表异步,默认为异步
3、发送请求
request.send();
4、接收响应
request.onreadysatechange = function()
}
思考:
1、在代码中我们要在什么样的时机开始处理响应呢?
响应结束(request.readyState==4)并且响应成功(request.status == 200)
2、异步的体现怎么体现出来的?
get请求
在数据交互中,我们经常会使用 GET 请求来查询数据
xhr.open("GET", "http://localhost:8080/simple/get?name=张三&age=18");
xhr.send();
post发送请求:
Ajax 中,我们通常使用 POST 方法来进行提交数据也是非常重要
xhr.open("POST", "http://localhost:8080/simple/post");
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send("name=zhangsan&age=18");
oTxt.onblur = function()else{
oBox.innerHTML = '亲, 用户名不可以'
}
}
}
}
<?php
header('Content-type:text/html;charset=utf-8');
# 获取前端数据
$username = $_GET['username'];
# 逻辑处理
$conn = mysqli_connect('localhost','root','root','my_2021');
if ($conn) {
# 数据的保存
$sql = 'select * from student where username="'.$username.'"';
$rseult = mysqli_query($conn,$sql); // $rseult会是多条数据
}else{
echo '连接失败';
}
# 响应给前端
$count = mysqli_num_rows($rseult); //返回一个数据,代表查找到了几个
if ($count==0) {
echo '1'; //用户名可用
} else {
echo '0';
}
?>
<?php
header('Content-type:text/html;charset=utf-8');
# 1.接收前端的信息
$username = $_POST['username'];
$userpass = $_POST['password'];
echo $username;
# 2.逻辑处理
# 2.1 php连接数据库 ,返回一个布尔值,true成功,false失败
// mysqli_connect 连接数据库
// mysqli_query 查询是否连接成功,成功后执行sql语句
$conn = mysqli_connect('localhost','root','root','my_2021');
if ($conn) {
echo '连接成功';
# 只是一条插入语句
$sql = 'insert into student(username,userpass) values("'.$username.'","'.$userpass.'")';
# 执行 sql语句 执行会有两个结果 true执行成功 false 执行失败
$result = mysqli_query($conn,$sql);
}else{
echo '连接失败';
}
# 3. 响应
if ($result) {
echo '1';
} else {
echo '0';
}
# 关闭服务器
mysqli_close($conn);
?>

一个函数被作为参数传递给另一个函数。函数B作为函数A的参数,函数B在函数A内部调用,函数B称为函数A的回调函数。
语法:
function A(callback){
callBack()
}
B也是一个函数
A(B)
语法一:
function success(callback){
callback()
}
success(function(){
console.log(1);
})
语法二:
function success(callback){
callback("张三")
}
success(function(data){
console.log(data);
})
封装ajax,发送一个get请求
普通版本
function ajaxget()
}
}
ajaxget();
-----------------------------------------------------------------
回调函数版本
function ajaxget(callback)
}
}
ajaxget(funciton(data){
console.log(data);
})
封装的原则:
封装之前,需要想一下,后期用户调用时传递什么参数方便的原则来进行封装
有些用户想后期这么调用
$.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
或者说:
$.ajax({
type: "POST",
url: "some.php",
data: {name:'张三',age:18},
success: function(msg){
alert( "Data Saved: " + msg );
}
});
function $ajax(options)
if (options.type == 'POST')
xhr.onreadystatechange = function ()
}
}
// 将对象格式的请求参数转为username=zhangsan&password=12345格式
function formdata(data) {
let arr = [];
// 对象的遍历:for in循环
for (let k in data) { //
arr.push(k + '=' + data[k])
}
return arr.join('&');//username=zhangsan&password=12345 // arr: [username='zhansgan',password='12233']
}
百度搜索提示案例
<?php
$music = $_GET['music'];
if ($music=='你') {
echo '[{"msg":"你是我的眼"},{"msg":"你是我的小苹果"},{"msg":"你是我的小辣椒"}]';
}
?>
otxt.oninput = function () </li>`
})
} else {
str = ''
}
oul.innerHTML = str;
}
})
}
名词解释:
1. 会话:用户进入网站 开始浏览到结束浏览的这样的一个过程 就称为一次会话
2. http无状态:因为服务器没有“记忆能力”。它就无法支持需要连续多个步骤的“事务”操作。
例如电商购物,首先要登录,然后添加购物车,再下单、结算、支付,这一系列操作都需要知道用户的身份才行,但“无状态”服务器是不知道这些请求是相互关联的。Cookie 技术可以解决这个问题。
HTTP 是一种不保存状态。
随着 Web 的不断发展,因无状态而导致业务处理变得棘手的情况增多了,比如用户登录到一家购物网站,即使他跳转到该站的其它页面后,也需要能继续保持登录状态,网站为了能够掌握是谁送出的请求,需要保存用户的状态。
HTTP/1.1 虽然是无状态协议,但为了实现期望的保持状态功能,引入了 Cookie 技术,有了 Cookie 再用 HTTP 协议通信,就可以管理状态了。
4.1 cookie的状态管理
cookie具体如何进行状态管理呢?
HTTP协议本身是无状态的。什么是无状态呢,即服务器无法判断用户身份。
Cookie实际上是一小段的文本信息(key-value格式)。
客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。
当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。
服务器检查该Cookie,以此来辨认用户状态。
cookie的生成过程: 打开浏览器—>输入网址—>回车—>域名解析—>访问服务器
—>返回主页—>将cookie存储在浏览器
用户要访问二级页面时,打开新的窗口,会自动判断上一个页面中
是否含有cookie,如果有,就将cookie数据带入到下一个页面


4.2 什么是cookie?
是会话跟踪技术
4.3 cookie的特点
(1)cookie存储在客户端浏览器里面,信息存储于用户硬盘,因此可以作为全局变量。
(2)cookie是与浏览器相关的。不同浏览器所保存的cookie也是不能互相访问的。
(3)cookie可能被用户删除。
(4)cookie默认是会话级别的.
会话级别:就是当浏览器关闭,那么cookie立即销毁,但是我们也可以在存储的时候手动设置cookie的过期时间
(5)cookie有数量与大小的限制,数量在50个左右,存储的数据量 4k 大小,cookie只支持存储string类型的数据。
(6)路径限制:存cookie时候可以指定路径,只允许子路径读取外层cookie,外层不能读取内层。
4.4 cookie数据的存和取
document.cookie = "键=值" 存储cookie
document.cookie 获取cookie
存储cookie
<body>
<input type="button" value="存" id = "s"/>
<input type="button" value="取" id = "g" />
<a href="2.html" target="_blank">跳转至二级页面</a>
</body>
<script>
let oSave = document.getElementById("s");
let oGet = document.getElementById("g");
//存cookie
oSave.onclick = function(){
document.cookie = "name=laowang";
alert("存储cookie成功");
}
oGet.onclick = function(){
alert(document.cookie);
}
</script>
4.5 cookie的生存周期
生存周期 就是cookie数据在浏览器上保存的时间
document.cookie = "键=值;expires=时间对象"
4.5 cookie的封装
<script>
//封装一个获取cookie值得方法
function getCookie(key)
}
//没cookie,或者有cookie,但是没找到key 得不到cookie, 返回一个空字符串
return "";
}
//封装一个设置cookie值得方法
function setCookie(key,value,day)
//删除cookie
function delCookie(key)
</script>
4.5 cookie登录成功
登录到首页案例
function getCookie(key)
}
return '';
}
//封装一个设置cookie值得方法
function setCookie(key, value, day)
//删除cookie
function delCookie(key)

注意点:
1、存储cookie时 ,要求存储的键和值都是字符串类型
2、获取cookie时,获取的值是字符串类型的值
3、将json字符串(jsonstr)转为数组类型,JSON.parse(jsonstr)
4、将数组类型(json)转为json字符串,JSON.stringify(jsonarr)
<table border="1px" id="table">
<thead>
<tr>
<td>商品</td>
<td>单价</td>
<td>数量</td>
<td>小计</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr>
<td>华为手机</td>
<td>7999元</td>
<td> <input type="button" value="-" class="minusnum">
<input type="text" size="2" value="1">
<input type="button" value="+" class="addnum">
</td>
<td class="xj">7999元</td>
<td><input type="button" value="删除" class="delnum"></td>
</tr>
</tbody>
</table>
let table = document.querySelector('table');
let data =
[
{ "product": "华为手机", "price": "7999元", "num": "1", "sumline": "7999元" },
{ "product": "小米手机", "price": "9888元", "num": "1", "sumline": "9888元" },
{ "product": "诺基亚手机", "price": "8999元", "num": "1", "sumline": "8999元" },
{ "product": "锤子手机", "price": "9999元", "num": "1", "sumline": "9999元" }
]
function render() </td>
<td>${item.price}</td>
<td> <input type="button" value="-" class="minusnum">
<input type="text" size="2" value="${item.num}">
<input type="button" value="+" class="addnum">
</td>
<td class="xj">${item.price}</td>
<td><input type="button" value="删除" index = ${index} class="delnum"></td>
</tr>`
})
table.children[1].innerHTML = str;
}
render();
table.onclick = function (e)
}
程序员必备基础知识:通信协议–Http,TCP,UDP
1.1 通信协议
都是通信协议,也就是通信时所遵守的规则,只有双方都按照这个规则“说话",对方才谈理解
计算机只所以能全世界互通,协议是功不可没。如果没有协议,计算机各说各话,根本谁都听不懂谁.
1.2 计算机常见的网络协议
常见的网络协设:HTTP. TCP. UDP. FTP
其中最常见的就是TCP和UDP
TCP和UDP都工作在传输层,他们的目标都是在程序之间传输数据的。他们传输的数据格式可能是图片,视频,文本文件
TCP和UDP的区别?
TCP是基于连接的一种协议,UDP基于非连接的

TCP是如何保证以上过程的呢?
- 三次握手:建立连接的过程
-
- 也就是客户端向服务器端发起连接时,会先发一包连接请求数据进行询问,是否可以和服务器建立连接
- 如果服务器端同意客户端的请求,就会发送一包数据表示确认连接
-
- 客户端收到服务器端的确认之后,再次发送一包数据,表示 双方可以进行数据传输啦
- 传输确认
- 四次挥手
-
- 客户端主动发起关闭请求,向服务器端发送一包数据,表示要关闭连接
- 服务器端收到这包数据,又发送一个确认的包给客户端
-
- 服务器端再次发送一个确认包给客户端
- 客户端收到服务端的数据包,最后发送给服务器端一个确认包


即我们通常所说的Request/Response.前端向后端发请求
需要建立连接(三次握手),如果数据传输完成,就需要断开连接〈四次挥手)
-
和服务器建立连接(三次握手)
-
建立连接后,发送一个请求给服务器(请求)
-
服务器该受到请求以后进行相应的处理并给出一个回应〈响应)
-
断开与服务器的链接
数据传输
先连接〈三次握手)—>数据传输—->断开连接(四次挥手)—->数据停止传输。
1.3 什么是Http协议
Http是基于TCP的图向连接的一种协议。HTTP协议是一种基于请求/响应模式的、无状态的协议
HTTP协议的主要特点可概括如下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。
1.4 HTTP协议之URL

1.5 HTTP协议之请求
http请求由三部分组成,分别是:请求行、消息报头、请求正文。
输入地址栏回车,对 URL 进行解析之后,浏览器确定了目标服务器和文件名,接下来就需要根据这些消息封装成一个 HTTP 请求报文发送出去

请求报文 和 响应报文 都是由三个部分组成
-
前台应用从浏览器端, 向后台服务器发送HTTP请求(请求报文)
-
后台服务器端接收到请求后, 调用服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
-
浏览器端接受到响应, 解析显示响应体

1.6 HTTP协议之响应

常见的请求方式:
get请求,将请求数据作为url一部分发送,不安全,传输数据量小,方便易用。
post请求,传输数据量大,安全,一般做表单提交。
常见响应状态码:
200 OK //客户端请求成功
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
3.0 什么叫同源
如果两个页面拥有相同的协议、域名和端口,那么这两个页面就属于同一个源,其中只要有一个不相同,就是不同源。
http://www.example.com/dir2/other.html:同源
http://example.com/dir/other.html:不同源(域名不同)
http://v2.www.example.com/dir/other.html:不同源(域名不同)http://www.example.com:81/dir/other.html:不同源(端口不同)
https://www.example.com/dir/page.html:不同源(协议不同)
3.1 什么叫同源策略
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。
如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

总结
同源策略∶Ajax请求地址与当前页面的地址必须得是同协议,同主机,同端口才可以正常发送Ajax请求,这三者有任何一个不一样,则判定此次请求是跨域请求,浏览器会泪止这个请求行为。
3.2 同源策略的目的
为了安全,如果没有同源限制,在浏览器中的cookie等其他数据可以任意读取,不同域下的进行可以任意操作,ajax任意请求其他网站的数据,包括隐私数据。
3.3 非同源受到的限制
-
cookie不能读取 (如我在自己的站点无法读取博客园用户的cookie)
-
dom无法获得。
-
ajax请求不能发送
4.1 什么叫跨域
通俗的讲,跨域访问,就是跨域名访问,即A网站的网页的代码可以访问了B网站的页面。
4.2 jsonp跨域原理
jsonp 是 json with padding 的缩写,它不属于 Ajax 请求,但它可以模拟 Ajax 请求
页面上的很多标签天生就有跨域能力,都不会受到同源策略的影响比如:img,link,iframe,script。
jsonp就是利用
jsonp 由两部分组成:回调函数和数据,回调函数是当响应到来时应该在页面中调用的函数。
-
回调函数的名字一般是在请求中指定的。
-
而数据就是传入回调函数中的 JSON 数据
4.3 jsonp跨域的实现步骤
- 将不同源的服务器端请求地址写在 script 标签的 src 属性中
<script src="www.example.com?callback=fn&username=zhangsan"></script>
- 在客户端全局作用域
function fn(data){}
- 在fn函数内部对服务器端返回的数据进行处理
function fn(data){
console.log(data);
}
- 服务器端响应数据必须是一个函数的调用,真正要发送给客户端的数据需要作为函数调用的参数。
const data = 'fn({name: "张三", age: "20"})';
echo data;
整体实现思路:
-
客户端需要将函数名称传递到服务器端
-
将script请求的发送变成动态的请求。
-
服务器端在后端返回一个函数调用
-
客户端接收到响应,直接调用全局函数
前端
<script>
function fn(data){
console.log(data);
}
// 接收后端响应的数据
</script>
<script src="data.php?callback=fn"></script>
后端:
<?php
$cb = $_GET['callback']; //接收前端的参数:callback fn
$data = "i am back";
echo $cb.'("'.$data.'")'; // fn('123')
?>
jsonp解决跨域的用途是非常广的,很多网站进去都能看到很多的jsonp跨域
4.4 jsonp跨域封装(直接拿来使用即可)
function $jsonp(options)
}
// 将js对象{}转为字符串拼接的形式 username=zhangsa&password=12345
function getParams(obj){
var arr = [];
for(var k in obj){
arr.push(k+'='+obj[k]);
}
return arr.join('&');
}
调用的的格式:
$jsonp({
url:'https://www.baidu.com/sugrec',
data:{
"prod":"pc",
"wd":"衣服",
},
success:function(data){
console.log(data);
}
})
5.1 服务器端跨域(CORS跨域)
CORS:全称为 Cross-origin resource sharing,即跨域资源共享,它允许浏览器向跨域服务器发送 Ajax 请求,克服了 Ajax 只能同源使用的限制。
只需要在后端设置:
header('Access-Control-Allow-Origin: *');//允许任何请求
header('Access-Control-Allow-Origin: 'http://localhost:3000'');允许localhost:3000发起的跨域请求,其他的都不通过
5.2 jsonp跨域
5.3 后端代理解决跨域
简述:后期做开发,我们不需要写php后端代码,。学会看后端的接口文档就可以啦
下面就是一个写好的接口文档。
后端接口:
url:'https://www.baidu.com/sugrec'
请求参数:
prod:什么端访问的pc,android
wd: 搜索内容
例如:
"prod":"pc"
"wd":"衣服"
接口文档:
请求方式:GET
请求地址: 'https://wis.qq.com/weather/common',
必要参数:
province: "陕西省",
city: "西安市",
source:'pc',
weather_type:'forecast_1h'
搜索框自动搜索
<!DOCTYPE html>
<html>
<head>
<title>千锋教育——做真实的自己,用心做教育</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
<input type="text">
<script src="./jsonp.js"></script>
<script>
var oTxt = document.querySelector('input')
oTxt.oninput = function () {
jsonp({
type:'GET',
url: 'https://suggest.taobao.com/sug',
data: {
q: this.value,
},
success: function (data) {
console.log(data);
}
})
}
</script>
</body>
</html>
1.1 同步和异步
同步代码
代码单线执行,发送服务器请求后,等待返回数据,会出现网页空白(阻塞网页运行)
异步代码
代码发送请求后继续执行后续代码,不等待服务器返回数据(网页运行流畅)
js中常见的异步执行代码:
1.ajax请求:异步 JavaScript 和 XML
2.定时器:间隔一段时间才会执行,
3.事件处理函数:满足事件触发条件才会执行
异步底层执行原理
js代码是单线执行,代码从上往下依次执行,当遇到【异步任务】时,将其储存到一个【执行队列】中,当主线的代码执行结束后,在根据服务器的处理先后顺序执行剩余的【异步任务】
1.2 js代码的执行顺序-同步和异步
js的执行顺序,先同步后异步

如上图:任务二属于异步代码(耗时操作)
异步任务:
-
定时器:setTimeout setInterval
-
ajax的异步请求的xhr.onreadystate = function(){}
-
es6的promise
console.log(1);
setTimeOut(function(){
console.log(2);
},0)
console.log(3);
-------------------------------
console.log(1);
var xhr = new XMLHttpRequest();
console.log(2);
xhr.open('get','checkUser.php?username='+this.value);
console.log(3);
xhr.send();
console.log(4);
xhr.onreadystatechange = function()
}
console.log(6);
1.3、获取取异步函数返回值
function getNum(){
return 1;
}
function getNum(),1000);
}
------------------------------------
解决方案:回调函数来解决
function getNum(callback),500)
}
getNum(function(data){
console.log(data);
})
1.4 多个异步任务,顺序执行
1.4.1 回调函数嵌套
setTimeout(function () , 2000)
}, 3000)
}, 5000)
}, 1000)
问题:
- 代码丑,冗杂,难维护
- 执行效率低
1.4.2 Promise解决(下面讲解)
问题:编写的难度比传统写法高,并且阅读代码也不是一眼能够看懂。
你只会看到一堆then,必须本身在then的回调函数里面理清逻辑。html
3.1 Promise对象
Promise(承诺),在程序中的意思就是承诺我过一段时间(通常是一个异步操作)后会给你一个结果,是异步编程的一种解决方案。
从语法上说,原生Promise 是一个对象,从它可以获取异步操作的消息
Promise 提供统一的 API,各种异步操作都可以用同步的写法进行处理。

3.2 Promise实现原理
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。
它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
promise对象的方法:
1.p.then()
1)作用是为 Promise 实例添加状态改变时的回调函数。接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。
其中,第二个函数是可选的,不一定要提供。
2)如果返回的是另一个Promise对象,后面还可以接着调用then方法。
2. p.catch()
1)用于指定发生错误时的回调函数。
2)如果返回的也是一个 Promise 对象,还可以接着调用then方法
const p = new Promise(
function (resolve, reject) {
// 一段耗时的异步操作
resolve('成功') // 获取成功的数据
// reject('失败') //获取失败的结果
}
).then(res=>{console.log(res)}).catch(err=>{console.log(err)})
-----------------------------------------------
const p1 = new Promise(function(resolve,reject){
resolve(1)
})
const p2 = new Promise(function(resolve,reject){
resolve(2)
})
const p3 = new Promise(function(resolve,reject){
resolve(3)
})
const p4 = new Promise(function(resolve,reject){
resolve(4)
})
p1.then(data=>{console.log(data);return p2;})
.then(data=>{console.log(data);return p3;})
.then(data=>{console.log(data);})
3.3 Promise特点
- 对象的状态不受外界影响。
promise有三种状态 pending(进行中) fulfilled(已成功) rejected(已失败),
只有异步操作的结果,才可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
一旦从等待状态变成为其他状态就永远不能更改状态了。
- 一旦新建Promise就会立即执行,无法中途取消。
let p = new Promise((resolve, reject) => else {
reject(n);
}
})
console.log(p);//promise对象
p对象:.then()拿到处理成功的结果 .catch()拿处理失败的结果的
p.then(data=>{
console.log(data);
}).catch(data=>{
console.log(data);
})
三个状态:"pending", "fulfilled","rejected"
2个方法:.then() .catch()
3.4 使用Promise封装ajax
function $promise(options)
if (options.type == 'POST')
xhr.onreadystatechange = function () else {
reject('错误');
}
}
}
})
}
$promise({
type: "GET",
url: 'a.php',
asycn: true,
data: "username=zhangsan"
}).then(data => {
console.log(data);
})
async/await是写异步代码的新方式,以前的方法有回调函数和Promise。
async/await是基于Promise实现的,它不能用于普通的回调函数。
async/await与Promise很像,是非阻塞的。
async/await使得异步代码看起来像同步代码,这正是它的魔力所在。
用async/ await来发送异步请求,从服务端获取数据,代码很简洁
async/await:基于prmoise,await修饰promise对象,async 修饰函数
// 第一个任务
let p1 = new Promise((resovle, reject) => , 5000)
})
// 第二个异步任务
let p2 = new Promise((resovle, reject) => , 1000)
})
// 第三个异步任务
let p3 = new Promise((resovle, reject) => , 4000)
})
async function fn() {
let n1 = await p1;
let n2 = await p2;
let n3 = await p3;
console.log(n1, n2, n3);
}
fn();
1.1 jQuery介绍
1.1.1 javascript库
JavaScript库:即 library,是一个封装好的特定的集合(方法和函数)。从封装一大堆函数的角度理解库,就是在这个库中,封装了很多预先定义好的函数在里面,比如动画animate、hide、show,比如获取元素等。
简单理解: 就是一个JS 文件,里面对我们原生js代码进行了封装,存放到里面。这样我们可以快速高效的使用这些封装好的功能了。
比如 jQuery,就是为了快速方便的操作DOM,里面基本都是函数(方法)。
常见的JavaScript 库:jQuery、Prototype、YUI、Dojo、Ext JS、移动端的zepto等,这些库都是对原生 JavaScript 的封装,内部都是用 JavaScript 实现的,我们主要学习的是 jQuery。
1.1.2 jQuery的概念
jQuery总体概况如下 :
-
jQuery 是一个快速、简洁的 JavaScript 库,其设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。
-
j 就是 JavaScript; Query 查询; 意思就是查询js,把js中的DOM操作做了封装,我们可以快速的查询使用里面的功能。
-
jQuery 封装了 JavaScript 常用的功能代码,优化了 DOM 操作、事件处理、动画设计和 Ajax 交互。
-
学习jQuery本质: 就是学习调用这些函数(方法)。
-
jQuery 出现的目的是加快前端人员的开发速度,我们可以非常方便的调用和使用它,从而提高开发效率。
1.1.3 jQuery的优点
-
轻量级。核心文件才几十kb,不会影响页面加载速度。
-
跨浏览器兼容,基本兼容了现在主流的浏览器。
-
链式编程、隐式迭代。
-
对事件、样式、动画支持,大大简化了DOM操作。
-
支持插件扩展开发。有着丰富的第三方的插件,例如:树形菜单、日期控件、轮播图等。
-
免费、开源。
1.2 jQuery基本使用
1.2.1 jQuery下载
jQuery的官网地址: https://jquery.com/,官网即可下载最新版本。
各个版本的下载:https://code.jquery.com/
版本介绍:
1x :兼容 IE 678 等低版本浏览器, 官网不再更新
2x :不兼容 IE 678 等低版本浏览器, 官网不再更新
3x :不兼容 IE 678 等低版本浏览器, 是官方主要更新维护的版本
1.2.2 体验jQuery
步骤:
-
引入jQuery文件。
-
在文档最末尾插入 script 标签,书写体验代码。
-
$(‘div’).hide() 可以隐藏盒子。
1.2.3 jQuery的入口函数
jQuery中常见的两种入口函数:
// 第一种: 简单易用。
$(function () {
... // 此处是页面 DOM 加载完成的入口
}) ;
// 第二种: 繁琐,但是也可以实现
$(document).ready(function(){
... // 此处是页面DOM加载完成的入口
});
总结:
-
等着 DOM 结构渲染完毕即可执行内部代码,不必等到所有外部资源加载完成,jQuery 帮我们完成了封装。
-
相当于原生 js 中的 DOMContentLoaded。
-
不同于原生 js 中的 load 事件是等页面文档、外部的 js 文件、css文件、图片加载完毕才执行内部代码。
-
更推荐使用第一种方式。
1.2.4 jQuery中的顶级对象$
- $是 jQuery 的别称,在代码中可以使用 jQuery 代替,但一般为了方便,通常都直接使用 $。
- 包装成jQuery对象,就可以调用jQuery 的方法。
1.2.5 jQuery 对象和 DOM 对象
使用 jQuery 方法和原生JS获取的元素是不一样的,总结如下 :
-
用原生 JS 获取来的对象就是 DOM 对象
-
jQuery 方法获取的元素就是 jQuery 对象。
-
jQuery 对象本质是: 利用$对DOM 对象包装后产生的对象(伪数组形式存储)。
注意:
只有 jQuery 对象才能使用 jQuery 方法,DOM 对象则使用原生的 JavaScirpt 方法。
1.2.6 jQuery 对象和 DOM 对象转换
DOM 对象与 jQuery 对象之间是可以相互转换的。因为原生js 比 jQuery 更大,原生的一些属性和方法 jQuery没有给我们封装. 要想使用这些属性和方法需要把jQuery对象转换为DOM对象才能使用。
// 1.DOM对象转换成jQuery对象,方法只有一种
var box = document.getElementById('box'); // 获取DOM对象
var jQueryObject = $(box); // 把DOM对象转换为 jQuery 对象
// 2.jQuery 对象转换为 DOM 对象有两种方法:
// 2.1 jQuery对象[索引值]
var domObject1 = $('div')[0]
// 2.2 jQuery对象.get(索引值)
var domObject2 = $('div').get(0)
总结:实际开发比较常用的是把DOM对象转换为jQuery对象,这样能够调用功能更加强大的jQuery中的方法。
1.3 jQuery选择器
原生 JS 获取元素方式很多,很杂,而且兼容性情况不一致,因此 jQuery 给我们做了封装,使获取元素统一标准。
1.3.1 基础选择器
$(“选择器”) // 里面选择器直接写 CSS 选择器即可,但是要加引号
1.3.2 层级选择器
层级选择器最常用的两个分别为:后代选择器和子代选择器。
基础选择器和层级选择器案例代码
<body>
<div>我是div</div>
<div class="nav">我是nav div</div>
<p>我是p</p>
<ul>
<li>我是ul 的</li>
<li>我是ul 的</li>
<li>我是ul 的</li>
</ul>
<script>
$(function() {
console.log($(".nav"));
console.log($("ul li"));
})
</script>
</body>
1.3.3 隐式迭代
- 遍历内部 DOM 元素(伪数组形式存储)的过程就叫做隐式迭代。
- 简单理解:给匹配到的所有元素进行循环遍历,执行相应的方法,而不用我们再进行循环,简化我们的操作,方便我们调用。
$('div').css("width","100px") 所有的div
1.3.4 筛选选择器
$('li').eq(n):找到第n个
$('li').first():找到所有元素中的第一个
$('li').last():找到所有元素中的最后一个
$('li:eq(3)').next():找到某一个元素的下一个兄弟元素
$('li:eq(3)').prev():找到某一个元素的上一个兄弟元素
$('li:eq(3)').nextAll():找到某一个元素的后面的所有兄弟元素
$('li:eq(3)').prevAll():找到某一个元素的前面的所有兄弟元素
$('li:eq(3)').parent(): 找到某一个元素的父元素
$('li:eq(3)').parents():找到某一个元素的所有结构父级,一直到 html
找到一组元素中的某一个:
// 在 li 的所有父级里面找到所有 body 标签 $('li').parents().find('body')
// 找到 div 标签下所有后代元素中所有类名为 box 的元素 $('div').find('.box')
筛选选择器,顾名思义就是在所有的选项中选择满足条件的进行筛选选择。常见如下 :
案例代码
<body>
<ul>
<li>多个里面筛选几个</li>
<li>多个里面筛选几个</li>
<li>多个里面筛选几个</li>
<li>多个里面筛选几个</li>
<li>多个里面筛选几个</li>
<li>多个里面筛选几个</li>
</ul>
<ol>
<li>多个里面筛选几个</li>
<li>多个里面筛选几个</li>
<li>多个里面筛选几个</li>
<li>多个里面筛选几个</li>
<li>多个里面筛选几个</li>
<li>多个里面筛选几个</li>
</ol>
<script>
$(function() {
$("ul li:first").css("color", "red");
$("ul li:eq(2)").css("color", "blue");
$("ol li:odd").css("color", "skyblue");
$("ol li:even").css("color", "pink");
})
</script>
</body>
另: jQuery中还有一些筛选方法,类似DOM中的通过一个节点找另外一个节点,父、子、兄以外有所加强。
1.3.5 排他思想
想要多选一的效果,排他思想:当前元素设置样式,其余的兄弟元素清除样式。
$(this).css(“color”,”red”);
$(this).siblings(). css(“color”,””);
1.3.6 tab切换
1.3.7 链式编程
链式编程是为了节省代码量,看起来更优雅。
$(this).css('color', 'red').sibling().css('color', '');
1.4 jQuery样式操作
jQuery中常用的样式操作有两种:css() 和 设置类样式方法
1.4.1 操作css样式方法
jQuery 可以使用 css 方法来修改简单元素样式; 也可以操作类,修改多个样式。
常用以下三种形式 :
// 1.参数只写属性名,则是返回属性值
var strColor = $(this).css('color');
// 2. 参数是属性名,属性值,逗号分隔,是设置一组样式,属性必须加引号,值如果是数字可以不用跟单位和引号
$(this).css('color', 'red');
// 3. 参数可以是对象形式,方便设置多组样式。属性名和属性值用冒号隔开, 属性可以不用加引号
$(this).css({ "color":"white","font-size":"20px"});
注意:css() 多用于样式少时操作,多了则不太方便。
1.4.2 操作css类的方法
作用等同于以前的 classList,可以操作类样式, 注意操作类里面的参数不要加点。
常用的三种设置类样式方法:
// 1.添加类
$("div").addClass("current");
// 2.删除类
$("div").removeClass("current");
// 3.切换类
$("div").toggleClass("current");
// 4. 包含类
$("div").hasClass("current");
注意:
- 设置类样式方法比较适合样式多时操作,可以弥补css()的不足。
- 原生 JS 中 className 会覆盖元素原先里面的类名,jQuery 里面类操作只是对指定类进行操作,不影响原先的类名。
1.4.3 案例-tab栏切换
1.4.4 jQuery中类操作和className的区别
- 原生的js中className会覆盖元素原先里面的类名
- addClass相当于追加类名 不影响以前的类名
1.5 jQuery属性操作
jQuery 常用属性操作有三种:prop() / attr() / data() ;
1.5.1 元素固有属性值 prop
所谓元素固有属性就是元素本身自带的属性,比如 元素里面的 href ,比如 元素里面的 type。
语法:
- 获取属性方法prop(“属性”)
- 设置属性方法prop(“属性”, “属性值”)
**注意:**prop() 除了普通属性操作,更适合操作表单属性:disabled / checked / selected 等
1.5.2 元素自定义属性值 attr
用户自己给元素添加的属性,我们称为自定义属性。 比如给 div 添加 index =“1”。
语法:
- 获取属性语法attr(“属性”) // 类似原生的getAttribute
- 设置属性语法attr(“属性”, “属性值”) // 类似原生的setAttribute
**注意:**attr() 除了普通属性操作,更适合操作自定义属性。(该方法也可以获取 H5 自定义属性)
1.5.3 移除元素的某一个属性
移除元素的自定义属性 : $(‘div’).removeAttr(‘index’)
1.6 jQuery文本属性值
jQuery的文本属性值常见操作有三种:html() / text() / val() ;
分别对应JS中的 innerHTML 、innerText 和 value 属性
1.6.1 jQuery内容文本值
常见操作有三种:html() / text() / val() ;
分别对应JS中的 innerHTML 、innerText 和 value 属性,
主要针对元素的内容还有表单的值操作。
语法:
- 普通元素内容html()(相当于原生innerHTML)
html() // 获取元素的内容
html(“内容”) // 设置元素的内容
- 普通元素文本内容text()(相当于原生innerText)
text() // 获取元素的文本内容
text(“内容”) // 设置元素的文本内容
- 表单的值val()(相当于原生value)
val() // 获取表单的值
val(“内容”) // 设置表单的值
1.7 元素操作
1.7.1 创建一个元素
var div = $(‘
’)
1.7.2 内部插入元素
// 向 div 元素中插入一个 p 元素,放在最后
$('div').append($('<p></p>'))
// 把 p 元素插入到 div 中去,放在最后
$('<p>hello</p>').appendTo($('div'))
// 向 div 元素中插入一个 p 元素,放在最前
$('div').prepend($('<p></p>'))
// 把 p 元素插入到 div 中去,放在最前
$('<p>hello</p>').prependTo($('div'))
1.7.3 外部插入元素
// 在 div 的后面插入一个元素 p
$('div').after($('<p></p>'))
// 在 div 的前面插入一个元素 p
$('div').before($('<p></p>'))
// 把 p 元素插入到 div 元素的后面
$('div').insertAfter($('<p></p>'))
// 把 p 元素插入到 div 元素的前面
$('div').insertBefore($('<p></p>'))
1.7.4 替换元素
// 把 div 元素替换成 p 元素
$('div').replaceWith($('<p></p>'))
// 用 p 元素替换掉 div 元素
$('<p></p>').replaceAll($('div'))
1.7.5 删除元素
// 删除元素下的所有子节点
$('div').empty()
// 把自己从页面中移除
$('div').remove()
1.7.6 克隆元素
// 克隆一个 li 元素
// 接受两个参数
// 参数1: 自己身上的事件要不要复制,默认是 false
// 参数2: 所有子节点身上的事件要不要复制,默认是 true
$('li').clone()
1.7.7 元素遍历
var arr = ["red","yellow","pink"]
$('div').each((index,item)=>{
$(item).css("background",arr[index])
})
1.8 元素事件绑定
因为普通注册事件方法的不足,jQuery又开发了多个处理方法,重点讲解如下:
-
on(): 用于事件绑定,目前最好用的事件绑定方法
-
off(): 事件解绑
-
trigger() / triggerHandler(): 事件触发
-
one():事件触发一次
1.8.1 绑定事件的方法
// 给 button 按钮绑定一个点击事件
$('button').on('click', function () {
console.log('我被点击了')
})
1.8.2 移除事件
// 给 button 按钮绑定一个 点击事件,执行 handler 函数
$('button').on('click', handler)
// 移除事件使用 off
$('button').off('click', handler)
1.8.3 只能执行一次的事件
// 这个事件绑定再 button 按钮身上
// 当执行过一次以后就不会再执行了
$('button').one('click', function(){})
1.8.4 直接触发事件
// 当代码执行到这里的时候,会自动触发一下 button 的 click 事件
$('button').trigger('click')
$('button').triggerHandler('click')
区别:triggerHandler只会触发JQ对象集合中第一个元素的事件处理函数,也不会产生事件冒泡。
而trigger触发JQ对象集合中所有元素的事件处理函数,而且会产生事件冒泡
1.9 元素尺寸
1.9.1 操作元素的宽和高
// 获取 div 元素内容位置的高,不包含 padding 和 border
$('div').height()
// 设置 div 内容位置的高为 200px
$('div').height(200)
// 获取 div 元素内容位置的宽,不包含 padding 和 border
$('div').width()
// 设置 div 内容位置的宽为 200px
$('div').width(200)
1.9.2 获取元素的内置宽和高
// 获取 div 元素内容位置的高,包含 padding 不包含 border
$('div').innerHeight()
// 获取 div 元素内容位置的宽,包含 padding 不包含 border
$('div').innerWidth()
1.9.3 获取元素的外置宽和高
// 获取 div 元素内容位置的高,包含 padding 和 border
$('div').outerHeight()
// 获取 div 元素内容位置的高,包含 padding 和 border 和 margin
$('div').outerHeight(true)
// 获取 div 元素内容位置的宽,包含 padding 和 border
$('div').outerWidth()
// 获取 div 元素内容位置的高,包含 padding 和 border 和 margin
$('div').outerWidth(true)
1.10 元素位置
1.10.1 元素相对页面的位置
// 获取 div 相对页面的位置
$('div').offset() // 得到的是以一个对象 { left: 值, top: 值 }
// 给 div 设置相对页面的位置
$('div').offset({ left: 100, top: 100 })
// 获取定位到一个距离页面左上角 100 100 的位置
案例:物体运动
let lf = $(‘div’).offset().left;
lf = lf + 10;
$(‘div’).offset({ ‘left’:lf })
1.10.2 元素相对于父元素的偏移量
// 只能获取 div 相对于父元素的偏移量(定位的值)
$('div').position()
1.10.3 获取页面卷去的高度和宽度
window.onscroll = function () {
// 获取浏览器卷去的高度
console.log($(window).scrollTop())
}
window.onscroll = function () {
// 获取浏览器卷去的宽度
console.log($(window).scrollLeft())
}
回到顶部
回到顶部
//先将#back-top隐藏
$('#back-top').hide();
//当滚动条的垂直位置距顶部100像素一下时,跳转链接出现,否则消失
$(window).scroll(function() else {
$("#back-top").fadeOut(1000);
}
});
//点击跳转链接,滚动条跳到0的位置,页面移动速度是1000
$("#back-top").click(function() {
$('body').animate({
scrollTop: '0'
}, 1000);
return false; //防止默认事件行为
})
1.11 动画
1.11.1 显示和隐藏
显示:
方式一:
$('div').show() // 如果元素本身是 display none 的状态可以显示出来
方式二:
$('div').show('毫秒', '速度', '回调函数')
$('div').show(1000, 'linear', function () {
console.log('我显示完毕')
})
隐藏:
方式一:
$('div').hide('毫秒', '速度', '回调函数')
方式二:
$('div').hide(1000, 'linear', function () {
console.log('我隐藏完毕')
})
切换:
方式一:
$('div').toggle()
方式二:
$('div').toggle(1000, 'linear', function () { console.log('动画执行完毕') })
1.11.2 淡入淡出
fadeIn([s],[e],[fn])
fadeOut([s,[e],[fn]])
1.11.3 下滑上滑
slideDown([s],[e],[fn])
slideUp([s,[e],[fn]])
slideToggle([s],[e],[fn])
1.11.4 自定义动画
$('.show').click(function () {
$('div').animate(
{ width: 500, height: 300 },
1000,
'linear',
function () {
console.log('动画运动完毕')
})
})
1.11.5 stop
立刻停止动画 $('div').stop() ---> 就停止再当前状态
1.12 发送 ajax 请求
1.12.1 发送 get 请求
$.get("test.cgi", { name: "John", time: "2pm" },
function(data){
alert("Data Loaded: " + data);
});
1.12.2 发送 post 请求
$.post("test.php", { name: "John", time: "2pm" },
function(data){
alert("Data Loaded: " + data);
});
1.12.3 综合发送 ajax 请求
$.ajax({
url: "page.php",
processData: false,
data: {},
success: function(data){
alert("Data Loaded: " + data);
}
});
1.12.4 发送一个 jsonp 请求
1.13 jQuery 的多库共存
我们一直在使用 jQuery ,都没有什么问题 。但是如果有一天,我们需要引入一个别的插件或者库的时候
人家也向外暴露的是 $ 获取 jQuery ,那么,我们的 jQuery 就不能用了 。那么这个时候, jQuery 为我们提供了一个多库并存的方法
1.13.1 交还jQuery命名的控制权
下面这个方法可以交还 jQuery 命名的控制权
jQuery.noConflict()
上面代码执行完毕以后 $ 这个变量就不能用了 。但是 jQuery 可以使用
console.log($) // undefined
console.log(jQuery) // 可以使用
1.13.2 完全交出控制权
下面 这个方法可以交并且传递一个 true 的时候,会完全交出控制权
jQuery.noConflict(true)
面代码执行完毕以后 $ 这个变量就不能用了 ,jQuery 这个变量也不能用了
console.log($) // undefined
console.log(jQuery) // undefined
1.13.3 更换控制权
可以用一个变量来接受返回值,这个变量就是新的控制权
var aa = jQuery.noConflict(true)
接下来就可以把 aa 当作 jQuery 向外暴露的接口使用了
aa('div').click(function () { console.log('我被点击了') })
1.1 构造函数的问题
通过构造函数实例化对象虽然很好用,但是他也存在一些问题,首先一个就是内存浪费的问题。
下面我们来看一个例子

我们可以给函数的原型添加函数,这样的话,函数所有的实例化对象都可以使用这个函数,大大减少函
数重复占用内存。
1.2 构造函数原型prototype
获取原型的方法:
- 通过对象的__proto__来获取
- 通过构造函数的prototype属性来拿到原型
构造函数通过原型分配的函数是所有对象所共享的
JavaScript 规定,每一个构造函数都有一个prototype 属性,指向另一个对象。
注意这个prototype也是 一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方
法。
举例:
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
Star.prototype.sing = function() {
console.log('我会唱歌');
}
var zsf = new Star('张三丰', 18);
var zxy = new Star('张学友', 19);
zsf.sing();//我会唱歌
zxy.sing();//我会唱歌
1.3 对象原型
刚才我们说了,每个函数都有一个prototype属性,这个属性就是构造函数的原型,那当函数被实例化以
后呢?
构造函数被实例化后的对象都会有一个属性 __proto __ 指向构造函数的 prototype 原型对象,之所以
我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 __proto __ 原型的
存在。
从而我们知道: __proto __ 对象原型和原型对象 prototype 是等价的,
proto 对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非
标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype。

1.4 constructor构造函数
上面我们说了构造函数和对象的原型,在对象的原型(proto)和构造函数(prototype)原型对象里
面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。

1.5 原型链
每一个实例对象又有一个proto属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对
象,也有proto属性,这样一层一层往上找就形成了原型链。
我们看如下图所示:

1.6 构造函数实例和原型对象三角关系
综上所述**😗*
构造函数的prototype属性指向了构造函数原型对象
实例对象是由构造函数创建的,实例对象的proto属性指向了构造函数的原型对象
构造函数的原型对象的constructor属性指向了构造函数,实例对象的原型的constructor属性也指向
了构造函数
由上面所述内容,我总结构造函数,实例化对象,原型对象三者之间的关系如下图所示:

面向对象的三个特点就是封装,继承和多态,通过继承,我们可以实现对象和方法的复用,从而提高代
码的利用率,也是代码优化的一种方案。下面我们看一下js的继承是怎么实现的?
2.1 子构造函数继承父构造函数中的属性
上面说了call方法的基本使用,下面我们看一下如何使用call完成函数的继承呢?也就是我们经常所说的
构造函数继承,主要分为三个步骤:
-
先定义一个父构造函数
-
再定义一个子构造函数
-
子构造函数继承父构造函数的属性(使用call方法)
// 1. 父构造函数
function Father(uname, age) { // this 指向父构造函数的对象实例
this.uname = uname;
this.age = age;
}
// 2 .子构造函数
function Son(uname, age, score) { // this 指向子构造函数的对象实例 3.使用call方式实现子继承父的属性
Father.call(this, uname, age);
this.score = score;
}
var son = new Son('张三丰', 18, 100);
console.log(son);
2.2 借用原型对象继承方法
当然我们也可以借用原型来继承函数,步骤大致如下所示:
– 先定义一个父构造函数
– 再定义一个子构造函数
– 子构造函数继承父构造函数的属性(使用call方法),把父方法的实例化对象赋给子方法的原型。
代码如下所示:
// 1. 父构造函数
function Father(uname, age) { // this 指向父构造函数的对象实例
this.uname = uname; this.age = age;
}
Father.prototype.money = function() {
console.log(100000);
};
// 2 .子构造函数
function Son(uname, age, score) { // this 指向子构造函数的对象实例
Father.call(this, uname, age);
this.score = score;
}
// Son.prototype = Father.prototype; 这样直接赋值会有问题,如果修改了子原型对象,父原型 对象也会跟着一起变化
Son.prototype = new Father(); // 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数
Son.prototype.constructor = Son; // 这个是子构造函数专门的方法
Son.prototype.exam = function() {
console.log('孩子要考试');
}
var son = new Son('张三丰', 18, 100);
console.log(son);
2.3 组合继承(伪经典继承)
function SuperType (name) {
this.name = name
this.colors = ["red", "blue", "green"]
}
SuperType.prototype.sayName = function () {
alert(this.name)
}
function SubType (name, age) { // 继承属性
SuperType.call(this, name) // 第二次调用SuperType()
this.age = age
}
//继承方法
SubType.prototype = new SuperType() // 第一次调用 SuperType()
Subtype.prototype.sayAge = function () {
alert(this.age)
}
实现思路:使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承
注意: 组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,成为js中最常用的继承方式
2.5 ES6继承
先看下如何定义类
class Parent {
constructor(name,age) {
this.name = name;
this.age = age;
}
getName() {
return this.name;
}
}
类的所有方法都定义在类的prototype属性上面。且class不存在变量提升,如果在class声明之前调用,
会报错。
类的继承
class Child extends Parent {
constructor(name,age,sex) {
super(name,age);
this.sex = sex;
}
}
var child = new Child('xiaoyu',12,'man');
在子类的构造函数中,如果显示声明了constructor,则必须要显示的调用super函数(这一点和Java有
点不一样)。
只有调用super之后,才可以使用this关键字,否则会报错。
1.1 函数的定义和调用
1.1.1函数的定义方式
方式1 函数声明方式 function fn(){}
方式2 函数表达式(匿名函数) var fn = function(){}
方式3 new Function() var fn = new Function(‘参数1’,‘参数2’…, ‘函数体’)
-
注意 Function 里面参数都必须是字符串格式
-
第三种方式执行效率低,也不方便书写,因此较少使用
-
所有函数都是 Function 的实例(对象)
-
函数也属于对象
1.1.2 函数的调用
普通函数的调用—>直接调用
function fn() {
console.log('人生的巅峰');
}
fn();
对象的方法—>对象调用
var o = {
sayHi: function() {
console.log('人生的巅峰');
}
}
o.sayHi()
构造函数–>new 调用
function Star(name,age) {
this.name = name;
this.age = age;
};
new Star();
立即执行函数(IIFE)
(function () { })();
高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。
- 接收函数作为参数—>回调函数
- 函数作为返回值输出
2.1 变量作用域复习
变量根据作用域的不同分为两种:全局变量和局部变量。
-
函数内部可以使用全局变量。
-
函数外部不可以使用局部变量。
-
当局部函数执行完毕,本作用域内的局部变量会销毁。
问:如何从外部读取局部变量?
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。
function f1(){
var n=999;
function f2(){
alert(n); // 999
}
f2();
}
f1();
2.2 什么是闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数。(官方说法)
简单理解就是 ,定义在一个函数内部的,它可以访问到外部函数的局部变量
function init() {
var name = "Mozilla"; // name 是一个被 init 创建的局部变量
function displayName() { // displayName() 是内部函数,一个闭包
alert(name); // 使用了父函数中声明的变量
}
displayName();
}
init();
看重点:displayName() 没有自己的局部变量。
然而,因为它可以访问到外部函数的变量,所以 displayName() 可以使用父函数 init() 中声明的变量 name 。
在一些编程语言中,一个函数中的局部变量仅存在于此函数的执行期间。
一旦 init() 执行完毕,你可能会 认为 name 变量将不能再被访问。
2.3 闭包的特点
闭包特点: 函数A嵌套函数B , 函数B能访问函数A的变量 , 函数B就是闭包
常见的闭包写法:函数A嵌套函数B , 函数B能访问函数A的变量 , 并返回函数B
1、闭包就是可以读取函数内部的变量的函数
2、闭包让我们能够从一个函数内部访问其外部函数的作用域
3、让变量的值始终保持在内存中
闭包的经典案例:
function foo() {
var local = 1
function bar() {
return ++local
}
return bar
}
var func = foo()
console.log(func());
2.4 案例讲解-点击li输出索引号
for (var i = 0; i < lis.length; i++) { // 利用for循环创建了4个立即执行函数 // 立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量
(function(i) {
lis[i].onclick = function() {
console.log(i);
}
})(i);
}
2.5 案例讲解-定时器中的闭包
for (var i = 0; i < lis.length; i++) , 3000) })(i);
}
2.6 面试题
function foo() {
var i = 0;
return function () {
console.log(i++);
}
}
var f1 = foo();
var f2 = foo();
f1();
f1();
f1();
f1();
f2();
f2();
f2();
f2();
f2();
2.7 闭包的优缺点
当函数执行完毕,本作用域内的局部变量会销毁。
闭包的优点:
数据存储三剑客:cookie、localstorage、 sessionstorage
Web Storage也是一种在客户端存储数据的一种机制,是h5的存储,主要涉及到sessionStorage和
localStroage,目的就是克服cookie带来的一些限制。
cookie的作用
- (1)解决http的无状态的缺点,在客户端存储会话信息,记录用户状态
- (2)cookie在客户端存储一些其他的数据信息
cookie的运行流程:
打开浏览器—>输入网址—>回车—>域名解析—>访问服务器—>返回主页—>将cookie存储在浏览器
—->随着浏览器的每一次请求,携带cookie发送到服务器端
cookie的封装
function getCookie(key)
}
return '';
}
// 2. 设置一个键值对,以及过期时间 setCookie('username','lisi',7)
function setCookie(key,value,day)
// 封装删除
function delCookie(key){
document.cookie = key+'="";expires=-1';
}
2.1 什么是localStorage
有一些数据确实需要存储在本地,但是不需要发送到服务器端,所以并不适合放在cookie中,那放在哪里呢?本节课学习的localstorage就是一个不错的选择。这样一来,即想存储在用户本地,又不想发送到服务器端的数据,就可以存储在localStorage中。而那些,即想存储在用户本地,又想随着请求发送到服务端的就可以使用cookie来存储。
localstorage也是一种数据存储技术,它只存在本地,不会发送到浏览器端。
什么是localStorage:数据在客户端,跨会话持久化地存储数据
2.2 localStorage的API方法
使用方法:
-
1.添加:localStorage.setItem(key, value);//value可以任何数据类型,也属于 window下的
-
2.获取:localStorage.getItem(key);
-
3.删除:localStorage.removeItem(key);//删除该存储对象中key的键值对
-
4.清除所有: localStorage.clear();//清除该存储对象中所有的键值对
2.3 localstorage的封装:
//获取
function getData(key)else{
return [];
}
}
清空
function delData(){
localStorage.clear();
}
存储
function setData(data)
2.4 localStorage存储的注意点
-
1.存储大小: localStorage会可以将第一次请求的数据直接存储到本地,相当于一个5M大小的针对于前端页面的 数据库,相比于cookie可以节约带宽。
-
2. 是否需要依赖服务器:不需要
-
3. 不同域名下:不可以共有localStorage
-
4.存储期限:持久化本地存储,除非手动删除,否则数据永远不会过期
-
5. 键和值的类型:都是字符串,不是字符串类型也会自动先转为字符串
//存:转为字符串
let obj = {"name":"Lee","age":"20"}
localStorage.setItem("user",JSON.stringify(obj));
//取:转换成对象
let user = JSON.parse(localStorage.getItem("user"))
sessionStorage,数据在客户端,会话级别的存储。也就是说当页面被关闭时,数据存储在 sessionStorage 会被清除
sessiontorage的封装:
// 增加了一个 sessiontorage ‘myCat’ 数据项
sessiontorage.setItem('myCat', 'Tom');
// 读取 sessiontorage ‘myCat’ 数据项
let cat = sessiontorage.getItem('myCat');
// 移除 sessiontorage ‘myCat’ 数据项
localStorage.removeItem('myCat');
// 移除所有的 sessiontorage 数据项
localStorage.clear();
SessionStorage的特点:
-
1. 只在本地存储,seesionStorage的数据不会跟随HTTP请求一起发送到服务器,只会在本地生效,
并在关闭标签页后清除数据
-
2. 存储上限限制:不同的浏览器存储的上限也不一样,但大多数浏览器把上限限制在5MB以下
-
3. 存储方式,seesionStorage的存储方式采用key、value的方式
-
4. 会话级别的存储
localStorage:常用于长期登录(加判断用户名已登录),适合场地保存本地的数据
sessionStoage:敏感账号的一次性登录

基本数据类型的变量保存的是一个值
引用数据类型的变量保存的是一个指针(地址),指向另一个位置。
深拷贝:赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个
var a = 10;
var b = a;
a = 100;
console.log(b);
浅拷贝:赋值时,引用赋值,相当于取了一个别名。对其中一个修改,会影响另一个
var a = [10,20,30];
var b = a;
a[0] = 100;
console.log(b);
常见问法:如何将引用数据类型进行深拷贝?
1、针对于数组,如何实现深拷贝?可以使用slice和concat方法,还可以使用ES6的展开运算符
const Arr = ["one", "two", "three"];
const fxArr = Arr.slice(0);
fxArr[1] = 'love'
console.log(Arr);
-----------------------------------------------------------------------
const Arr = ["one", "two", "three"];
const fxArr = Arr.concat(0);
fxArr[1] = 'love'
console.log(Arr);
------------------------------------------------
const Arr = ["one", "two", "three"];
const fxArr = [...Arr]
fxArr[1] = 'love'
console.log(Arr);
2、针对于对象,如何实现拷贝呢?可以使用以下几种方案?
----------------------对象一个一个赋值----------------------------------
let obj1 = {
name:"ruirui",
age:18
}
let obj2 = {}
obj2.name = obj1.name;
obj2.age = obj1.age;
obj2.name = 'shasha'
console.log(obj1);
-----------------------------ES6扩展运算符---------------------------
let obj1 = {
name:"ruirui",
age:18
}
let obj2 = {...obj1}
--------------------------对象遍历赋值------------------------------
var p = {
"id":"007",
"name":"刘德华"
}
var p2 = {};
for (let key in p) {
p2[key] = p[key];
}
p2.name = '王瑞'
console.log(p);
3、上面属于一层,如果含有多层,对象遍历赋值只能外层对象是深拷贝的,内层对象是浅拷贝
let p = {
"id":"007",
"name":"刘德华",
"books":newArray("三国演义", "红楼梦", "水浒传")//这是引用类型
}
function copy(obj){
var newobj = {};
for(var k in obj){
newobj[k] = obj[k]
}
return newobj
}
了解:发现实现不了:下面提供一种递归的思路来进行解决
var p =
}
}
**//写函数**
function copyObj(obj) {
let newObj = {};
for (let key in obj) else {
newObj[key] = obj[key];**//基本类型,直接赋值**
}
}
return newObj;
}
let pNew = copyObj(p);
pNew.wife.name = "张三疯";
pNew.wife.address.city = "香港";
console.log(pNew);
console.log(p);
函数防抖和节流,都是控制事件触发频率的方法。应用场景有很多,输入框持续输入,将输入内容远程校验、多次触发点击事件、onScroll等等。
什么是节流?
限制一个函数在一定时间内只能执行一次。
为什么要节流?
前端开发过程中,有一些事件或者函数,会被频繁地触发(短时间按内多次触发),最常见的例如,onresize,scroll,mousemove ,mousehover 等,这些事件的触发频率很高,不做限制的话,有可能一秒之内执行几十次、几百次,如果在这些函数内部执行了其他函数,尤其是执行了操作 DOM 的函数(浏览器操作 DOM 是很耗费性能的),那不仅会造成计算机资源的浪费,还会降低程序运行速度,甚至造成浏览器卡死、崩溃。这种问题显然是致命的。
问题:
问题1:对浏览器本身的性能有很大的影响
问题2: 如果是发送http请求,大量的http请求会浪费我们很多的带宽,也会给服务器本身造成很大的压力
使用函数节流对代码进行优化
函数节流的两个关键点:1、单位时间内2、只触发一次
window.onscroll = throttle(function(){
console.log(111);
})
function throttle(fn), 1000);
}
flag = false;
}
}
只要走setTimeOut,说明执行了业务代码设置为true,1s后继续执行
如果没走setTimeOut,说明没走业务代码,不执行
面试过程中主考官的问题点:
1、是否知道函数节流的概念
2、是否知道函数节流的具体使用场景
3、是否对项目本身性能有所关注
防抖:“你先抖动着,啥时候停了,我再继续执行下一步”
应用场景:一个搜索框,等输入停止了,再触发。
mousemove事件触发

函数防抖,也就是当持续触发事件的时候,函数是完全不执行的,等最后一次触发结束的一段时间之后,再去执行。先看一下效果:

分解一下需求:
- 持续触发不执行
- 不触发的一段时间之后再执行
let oTxt = document.querySelector("#txt")
oTxt.oninput = debounce(function(){
console.log(oTxt.value);
},1000)
function debounce(fn,millsec),millsec)
}
}
学习git,需要了解三个内容:git、github、gitee
1.1 什么是git
git是什么 : 是一个安装在电脑上的软件
git的作用一:管理你的文件夹的(开发人员来说,是管理项目目录的)
如果没有git,左下图就是我们的项目目录会出现的现象,有了git,右下图


使用git记录的版本,我们都可以恢复到以前的任意版本,以及查看修改记录。
git作用二:把本地的内容上传到远程
git作用三:多人协作开发
1.2 什么是github
github是一个网站,是一个国外的"网站",也是一个服务器,
作用是:接收你上传的内容,类似一个云盘
但是它只能接收git软件上传的内容
同时也是一个社交平台,开源社区,发布的项目可以被"点星–>star"
1.3 什么是gitee
gitee是一个网站,是一个国内的"网站"
和github作用一致
但是它只能接收git软件上传的内容
1.1 git的安装
1.2 git的配置
-
需要配置一个用户名和邮箱
-
查看配置信息:git config –list
-
配置全局用户名:git config –global user.name ‘你的用户名’
-
配置全局邮箱: git config –global user.email ‘你的邮箱’
1.3 git管理文件夹
git不会管理你的任何文件夹,想让你的文件夹被git管理,需要通知一下git,这个文件夹需要被管理
如何做:
- 把本地文件夹初始化称为git仓库,进入文件夹, git init,此时该目录就会被git管理
(当前目录下,会生成一个叫做.git的隐藏文件夹)
- 有了隐藏文件夹.git,表示当前目录被git管理了,当前目录以及后代目录都是被git管理啦。
注意:当你把文件夹初始化成git仓库后,git会虚拟的把你的文件夹分为三个区域(需要你自己想象一下)
工作区:你书写代码全部都在工作区
暂存区:
- 把你想形成历史版本的内容暂时存储(可以理解为论文的版本,在暂存区没有真正形成版本号)
- 暂存区可以回退到工作区
历史区:
-
你形成的一个个历史版本,只能把暂存区的内容形成历史版本
-
只能把暂存区的内容形成历史版本
-
形成的历史版本不能回退回来
-
历史区的内容最终上传到远程

1.4 git命令
-
切换目录到.git文件夹所在的目录,查看暂存状态:
-
- git status
-
把工作区的内容添加到暂存区:
-
- git 文件名称 —->单独一个文件添加到暂存区
- git add . —->所有文件添加到暂存区
-
把暂存区的内容回退到工作区:
-
- git reset HEAD – 文件名称 —> 单独撤回一个文件工作区
- git reset HEAD – . —->所有文件撤回到暂存区
-
查看历史版本:
-
- git log
-
生成历史版本:
-
- git commit -m “说明”
- 上述就会把当前暂存区的所有内容形成一个历史版本
-
回退历史版本(也就是把当前工作区回退到指定的那个时间节点的版本):
-
- git reset –hard 版本id
-
git上传到远程(第一次)
-
- 建立一个远程仓库(打开 github 或者 github 网站,点击页面的右上角 加号(+), 点击新建仓库)
- 把本地仓库和远程仓库建立连接通道:git remote add origin 远程地址
-
- 把本地的历史版本推送到远程仓库:$ git push -u origin master
-
git上传到远程(第二次)
-
- 只需要有未上传的历史版本就行
- 直接上传:输入指令: $ git push
-
远程拉取到本地
-
- 第一次拉取该远程仓库的内容:git clone 远程仓库地址
- 第 n 次拉取该远程仓库的内容:git pull
1.5 git分支
1.5.1 什么是git分支
在当前内容下, 开辟出一个 分支内容, 在分支上的所有书写,和原本内容不相干,当你需要分支上的内容的时候, 进行分支合并就可以了
1.5.2 查看所有分支
- 打开命令行, 切换目录到 .git 文件夹所在的目录
- 输入指令: $ git branch
1.5.2 创建一个新的分支
-
打开命令行, 切换目录到 .git 文件夹所在的目录
-
输入指令: $ git branch 分支名称
-
会把你当前所在的分支的所有内容复制一份放在新创建的分支上
1.5.3 切换分支
-
打开命令行, 切换目录到 .git 文件夹所在的目录
-
输入指令: $ git checkout 分支名称
-
切换到指定的分支位置,然后进行开发即可
-
把分支上本地的历史版本推送到远程仓库:$ git push -u origin 分支名称
1.5.4 合并分支
-
在 git 内的合并分支, 只有一种情况
-
你站在master分支上, 把其他分支的内容合并到自己身上
-
打开命令行, 切换目录到 .git 文件夹所在的目录
-
输入指令: $ git merge 分支名称
-
多次合并:出现vim命令界面,输入:wq 退出即可
3.1 为什么要配置公钥和私钥:
Git使用https协议,每次pull, push都要输入密码,相当的烦。
使用git协议,然后使用ssh密钥。这样可以省去每次都输密码
3.2 Git生成秘钥及配置公有代码库步骤:
1.设置账号和邮箱
git config –global user.name “自已的用户” 例:git config –global user.name “fenlin”
git config –global user.email “自己的邮箱” 例:git config –global user.email "youxiang@163.co
m"
2.查看秘钥是否存在
cd ~/.ssh
3.生成秘钥
ssh-keygen -t rsa -C “自己的邮箱与上面邮箱一致” 按三次回车例: ssh-keygen -t rsa -C "youxiang
@163.com"
4.查看秘钥,并复制到码云或github的ssh里
cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD9S2lo0iALjcBeE7dlCpXN+dN3asjaABIQOjAQJSKM
ho+UL2LQJhmbPhYQyio2IRV4sHgXUSXseZ8Dzo/B8oBiC94h25rrIb8UMmKp3Cctk1e1LabmhIVwzAZ
t
4cpyHpyryUqGbE4hy+7vBcBGwGjuQBR1cixJn3v+nc6jGtF+4UlIXDSOu9sYMiyCuqGKCjqQjvLDGRul
VmtJ8eROPMJLlRZ43Xg+vTFz0jH3EJP8OnguU+EH82XMHhgDpD0xyWS/mVcDKtYh4rUL/Ky8fXQuxY
3b RU5QKjHYuw88E3impT7VZz9IRcJQUtet9xVh69/qyH56SGfxZ/LjbjUbuEcR
整个过程如下图所示:

- 复制查看的秘钥到ssh里(即码云的GitHub中公钥value框中)
- 码云中

node是一个基于Chrome V8引擎的JavaScript代码运行环境。
- 浏览器(软件)能够运行JavaScript代码,浏览器就是JavaScript代码的运行环境(js是一个客户端语言)
- node(软件)能够运行JavaScript代码,node就是JavaScript代码的运行环境(js是一个服务器端语言)
- 使用JavaScript语法开发后端应用,从而减低了学习的门槛。
- 前端开发工具大多基于Node开发 vue打包 react打包等**(学会安装第三方包)**
- 一些公司要求前端工程师掌握Node开发
- 生态系统活跃,有大量开源库可以使用
3.1 node.js运行环境安装
去官网找到自己环境需要包http://nodejs.cn/,下载稳定版
javaScript的标准是ECMAScript,浏览器可以解析js 提供dom bom,node可以解析js提供一些附加的API。

node.js基础语法
搭建基本服务
// 引入模块
var http=require('http')
// 搭建服务
var app=http.createServer(function(请求,响应){
响应.end('<h1>hello node server run </h1>');
})
// 监听端口
app.listen('3000')
- 在当前文件夹下,地址栏 cmd 回车 打开命令行
- 在命令行写入 node 当前文件名 回车
- 打开游戏器,地址栏输入127.0.0.1:3000 回车
可以看到欢迎页面
5.1 JavaScript开发弊端
javaScript在早期的设计中就没有模块、包、类的概念,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码,我们称为模块化
5.2 模块化的概念
一个功能就是一个模块,多个模块可以组成完整应用,抽离一个模块不会影响其他功能的运行。

5.3 node.js中模块化开发规范
node的应用是模块组成的,用来隔离每个模块的作用域,使每一个模块在自身的命名空间中执行。
-
在 node 的开发过程中,我们是把每一个功能独立做成一个模块
-
然后在使用 导入导出 的方式把他们关联在一起
-
- 利于维护
- 准确定位
-
我们一般把模块分为三种
-
- 内置模块 (node 天生就带有的模块)
- 自定义模块 (我们自己写的文件)
- 第三方模块 (从网上下载的别人写好的模块)
5.4 自定义模块
node自定义模块遵循Commonjs规范。
Commonjs规范是什么:
- 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见
- 模块必须通过module.exports导出对外的变量或接口,通过require()来导入其他模块的输出到当前模块作用域中。
CommonJS 模块化的写法,需要 node 等环境支持。在浏览器中无法直接解析和运行,需要先编译
5.4.1 Commonjs模块化导出语法:
语法一:
aaa.js
module.exports = { // 在此对象中定义导出的变量或函数
flag:true,
name:“xxx”,
add(num1, num2){
returnnum1 + num2;
},
}
语法二:
通过exports来向外部暴露变量和方法,只需要暴露给外部的属性和方法设置为exports的属性即可
yyy.js
exports.x = ‘我是你的哈哈’;
exports.y = ‘我是y’
exports.fn = function(){
console.log(‘我是fn函数’)
}
5.4.2 Commonjs模块化导入语法:
语法:
使用require()引入模块以后,该函数会返回一个对象,这个对象代表的是引入的模块
var xxx = require(‘./yyy.js’)
console(xxx)

5.5 系统模块
什么是系统模块:node运行环境提供的API. 因为这些API都是以模块化的方式进行开发的, 所以我们又称Node运行环境提供的API为系统模块。

5.5.1 系统模块fs文件操作
系统模块读文件:
const fs = require(‘fs’);
//读操作
fs.reaFile(‘文件路径/文件名称’[,‘文件编码’], callback);
fs.readFile(‘…/index.html’, “utf8”, (err,data) =>
});
系统模块写文件:
const content = ‘
正在使用fs.writeFile写入文件内容
’;
fs.writeFile(‘…/index.html’, content, (err,data) =>
console.log(‘文件写入成功’);
})
5.6 第三方模块
什么是第三方模块?
别人写好的、具有特定功能的、我们能直接使用的模块即第三方模块,由于第三方模块通常都是由多个文件组成并且被放置在一个文件夹中,所以又称为包
获取第三方包?
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用
由于新版的nodejs已经集成了npm,所以之前npm也一并安装好了。同样可以通过输入 “npm -v” 来测试是否成功安装。命令如下,出现版本提示表示安装成功。
大家都知道国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像。淘宝 NPM 镜像是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。
使用淘宝 NPM 镜像:
npm install -g cnpm –registry=https://registry.npm.taobao.org
**使用 npm 命令安装模块:**npm 安装 Node.js 模块语法格式如下:
npm install
**package.json:**package.json 位于模块的目录下,用于定义包的属性。
六、具体谈下npm?
6.1 什么是npm?
npm是前端开发广泛使用的包管理工具,它让js开发者分享、复用代码更方便。
可以重复的框架代码被称为包(package)或者模块(module),一个包可是是一个文件夹里放着几个文件
夹,还有一个package.json文件。
npm的作用就是让我们把可复用的框架代码发布到一个地方,可以供大家一起使用。
6.2 安装npm?
npm是依赖node.js的,先去官网https://nodejs.org/en/download/下载安装node.js,下载安
装好node,npm也有了,查看版本
node -v
v10.15.3
npm -v
6.9.0;
6.3 更新npm
npm更新速度很快,安装node附带的npm可能不是最新的,可以执行命令到最新版本
npm。install,安装;-g全局安装;npm@latest 就是 @的格式
npm install npm@latest -g
6.4 package.json文件
- 是一个包说明文件(项目描述文件),用来管理组织的一个包(一个项目)
- 是一个json格式的文件
- 位于当前项目的根目录下
6.5 package.json文件创建
- npm init就可以创建一个package.json文件,
- npm init –yes 可以跳过所有的问题
npm init会弹出很多问题,可以输入对应的内容,也可以直接enter回车使用默认值,回答
所有的问题,最后输入yes就会生成package.json文件
6.6 package.json内容
- description:描述信息,有助于搜索
- main:入口文件,一般都是index.js
- scripts:支持的脚本,默认是一个空的test
- author:作者信息
- license:默认是MIT
- keywords:关键字,有助于人们使用npm search搜索时候发现你的项目
6.7 指定依赖的包
我们需要在package.json文件中指定项目依赖的包,别人拿到项目的时候,可以使用npm install直接下载有依赖
包依赖有2种方式
- dependencies,在生产环境中需要用到的依赖 (用户发布环境)
- devDependencies,在开发、测试环境中用到的依赖(用于本地环境开发时候)
命令 npm install –save 安装时,将信息写入package.json中的dependencies中。
命令 npm install –save-dev 安装,将信息写入package.json中的devDependencies中。
"dependencies": {
"connect-history-api-fallback": "^1.6.0",
"vue": "^2.5.22",
"vue-awesome-mui": "^1.7.3",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.4.0",
"@vue/cli-plugin-eslint": "^3.4.0",
"@vue/cli-service": "^3.4.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.8.0",
"eslint-plugin-vue": "^5.0.0",
"expose-loader": "^0.7.5",
}
npm uninstall 包名 只删除,如果有依赖,依然保存
npm uninstall –save 包名 删除的同时把依赖信息给删除了
6.8 全局安装
什么是全局安装?
全局安装方式是键入命令:npm install xxx -g 时, 模块将被下载安装到【全局目录】中
可以使用npm root -g查看全局安 装目录。
1. 安装模块到全局,不会在项目node_modules目录中保存模块包。
2. 不会将模块依赖写入devDependencies或dependencies 节点。
。**
Commonjs规范是什么:
- 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见
- 模块必须通过module.exports导出对外的变量或接口,通过require()来导入其他模块的输出到当前模块作用域中。
CommonJS 模块化的写法,需要 node 等环境支持。在浏览器中无法直接解析和运行,需要先编译
5.4.1 Commonjs模块化导出语法:
语法一:
aaa.js
module.exports = { // 在此对象中定义导出的变量或函数
flag:true,
name:“xxx”,
add(num1, num2){
returnnum1 + num2;
},
}
语法二:
通过exports来向外部暴露变量和方法,只需要暴露给外部的属性和方法设置为exports的属性即可
yyy.js
exports.x = ‘我是你的哈哈’;
exports.y = ‘我是y’
exports.fn = function(){
console.log(‘我是fn函数’)
}
5.4.2 Commonjs模块化导入语法:
语法:
使用require()引入模块以后,该函数会返回一个对象,这个对象代表的是引入的模块
var xxx = require(‘./yyy.js’)
console(xxx)
[外链图片转存中…(img-UrwLquQL-1649315926230)]
5.5 系统模块
什么是系统模块:node运行环境提供的API. 因为这些API都是以模块化的方式进行开发的, 所以我们又称Node运行环境提供的API为系统模块。
[外链图片转存中…(img-hkzNpOnM-1649315926230)]
5.5.1 系统模块fs文件操作
系统模块读文件:
const fs = require(‘fs’);
//读操作
fs.reaFile(‘文件路径/文件名称’[,‘文件编码’], callback);
fs.readFile(‘…/index.html’, “utf8”, (err,data) =>
});
系统模块写文件:
const content = ‘
正在使用fs.writeFile写入文件内容
’;
fs.writeFile(‘…/index.html’, content, (err,data) =>
console.log(‘文件写入成功’);
})
5.6 第三方模块
什么是第三方模块?
别人写好的、具有特定功能的、我们能直接使用的模块即第三方模块,由于第三方模块通常都是由多个文件组成并且被放置在一个文件夹中,所以又称为包
获取第三方包?
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用
由于新版的nodejs已经集成了npm,所以之前npm也一并安装好了。同样可以通过输入 “npm -v” 来测试是否成功安装。命令如下,出现版本提示表示安装成功。
大家都知道国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像。淘宝 NPM 镜像是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。
使用淘宝 NPM 镜像:
npm install -g cnpm –registry=https://registry.npm.taobao.org
**使用 npm 命令安装模块:**npm 安装 Node.js 模块语法格式如下:
npm install
**package.json:**package.json 位于模块的目录下,用于定义包的属性。
六、具体谈下npm?
6.1 什么是npm?
npm是前端开发广泛使用的包管理工具,它让js开发者分享、复用代码更方便。
可以重复的框架代码被称为包(package)或者模块(module),一个包可是是一个文件夹里放着几个文件
夹,还有一个package.json文件。
npm的作用就是让我们把可复用的框架代码发布到一个地方,可以供大家一起使用。
6.2 安装npm?
npm是依赖node.js的,先去官网https://nodejs.org/en/download/下载安装node.js,下载安
装好node,npm也有了,查看版本
node -v
v10.15.3
npm -v
6.9.0;
6.3 更新npm
npm更新速度很快,安装node附带的npm可能不是最新的,可以执行命令到最新版本
npm。install,安装;-g全局安装;npm@latest 就是 @的格式
npm install npm@latest -g
6.4 package.json文件
- 是一个包说明文件(项目描述文件),用来管理组织的一个包(一个项目)
- 是一个json格式的文件
- 位于当前项目的根目录下
6.5 package.json文件创建
- npm init就可以创建一个package.json文件,
- npm init –yes 可以跳过所有的问题
npm init会弹出很多问题,可以输入对应的内容,也可以直接enter回车使用默认值,回答
所有的问题,最后输入yes就会生成package.json文件
6.6 package.json内容
- description:描述信息,有助于搜索
- main:入口文件,一般都是index.js
- scripts:支持的脚本,默认是一个空的test
- author:作者信息
- license:默认是MIT
- keywords:关键字,有助于人们使用npm search搜索时候发现你的项目
6.7 指定依赖的包
我们需要在package.json文件中指定项目依赖的包,别人拿到项目的时候,可以使用npm install直接下载有依赖
包依赖有2种方式
- dependencies,在生产环境中需要用到的依赖 (用户发布环境)
- devDependencies,在开发、测试环境中用到的依赖(用于本地环境开发时候)
命令 npm install –save 安装时,将信息写入package.json中的dependencies中。
命令 npm install –save-dev 安装,将信息写入package.json中的devDependencies中。
"dependencies": {
"connect-history-api-fallback": "^1.6.0",
"vue": "^2.5.22",
"vue-awesome-mui": "^1.7.3",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.4.0",
"@vue/cli-plugin-eslint": "^3.4.0",
"@vue/cli-service": "^3.4.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.8.0",
"eslint-plugin-vue": "^5.0.0",
"expose-loader": "^0.7.5",
}
npm uninstall 包名 只删除,如果有依赖,依然保存
npm uninstall –save 包名 删除的同时把依赖信息给删除了
6.8 全局安装
什么是全局安装?
全局安装方式是键入命令:npm install xxx -g 时, 模块将被下载安装到【全局目录】中
可以使用npm root -g查看全局安 装目录。
1. 安装模块到全局,不会在项目node_modules目录中保存模块包。
2. 不会将模块依赖写入devDependencies或dependencies 节点。


