JQuery

一. 什么是jQuery:

1. 什么是:

(1). 第三方开发的: 必须先下载,才能用
(2). 执行DOM操作的: jquery还是在执行DOM 5件事,增删改查+事件绑定。学习jq,还是在重复学习DOM。
(3). 极简化的: jquery是对DOM的终极简化。

在这里插入图片描述
(4). 函数库: jq中使用函数来解决一切问题!没有属性!每一项操作,都要加()调用函数完成!

2. 为什么: 2个

(1). 简单: 
(2). 解决了大部分浏览器兼容性问题

3.何时:

几乎所有旧的web项目都是用jq做的

4. 问题:

(1). 没有彻底简化开发步骤!
(2). 只有PC端,没有移动端。

二. 如何使用jQuery

1. 下载:

(1). 官网: jquery.com
(2). 版本: 
a.  1.x  唯一支持旧浏览器的版本。
	1). 未压缩版: jquery-1.11.3.js
	i. 优点: 拥有完备的注释、代码格式,以及见名知意的变量名——极其适合学习之用
	ii. 缺点: 体积大,不便于快速下载运行——不适合于生产环境使用
	2). 压缩版: jquery-1.11.3.min.js
	i. 优点: 体积小,便于快速下载运行——适合于生产环境
	ii. 缺点: 去掉了所有注释、代码格式,极简化了变量名——可读性差,不适合学习之用。
b.  2.x  不再支持旧浏览器
c.  3.x  也不再支持旧浏览器,才开始支持ES6版本

2. 引入页面: 2种:

(1). 将jquery.js文件下载到当前项目文件夹中的本地保存。在网页中,引入当前项目本地的jquery.js文件
js/
 jquery-1.11.3.js
index.html
  <script src="js/jquery-1.11.3.js">
问题: jquery.js文件,只保存在当前项目所在服务器一份。导致距离项目所在服务器不同距离的用户,可能访问jquery.js文件的速度差异很大!
(2). 直接引入CDN网络中的jquery.js网址
a. 什么是CDN网络: 智能的内容分发网络。
b. CDN网络,在全球范围内,有多台服务器,同步保存大家共用的第三方js文件和css文件。
c. 当用户想使用CDN网络中同步保存的文件时,CDN网络会自动计算哪台服务器距离这个用户的网络状况最优,就自动从哪个服务器为用户下载文件。
d. 如何: 
	1). 不用下载jquery.js文件
	2). 找别的公司提供的下载jQuery得cdn网址: 
	<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.3.js"></script>

在这里插入图片描述

3. 示例: 我的第一个jquery程序:

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <h1>jQuery/$工厂函数</h1>
  <button id="btn1">click me(0)</button>
  <script>
    //DOM 4步
    //1. 查找触发事件的元素
    var btn1=document.getElementById("btn1")
    //2. 绑定事件处理函数
    btn1.onclick=function(){
      //3. 查找要修改得元素
      //本例中: 就是要改当前按钮自己的内容:this
      //4. 修改元素
      //4.1 先取出当前按钮中现在的数量是几
      var n=parseInt(
        this.innerHTML //"click me(1000)"
        //                0123456789...-1
            .slice(9,-1)//         |   |
            //复习第一阶段
      );
      //4.2 数量+1
      n++;
      //4.3 将新数量再放回当前按钮内容中
      this.innerHTML=`click me(${n})`
    }
  </script>
</body>
</html>
<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <h1>jQuery/$工厂函数</h1>
  <button id="btn1">click me(0)</button>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //DOM 4步
    //1. 查找触发事件的元素
              //id选择器
    var btn1=$("#btn1");
            //代替了document.getElementById
    //2. 绑定事件处理函数
    btn1.click(function(){//代替了onclick
      //3. 查找要修改得元素
      //本例中: 就是要改当前按钮自己的内容:this
      var $this=$(this);
      //4. 修改元素
      //4.1 先取出当前按钮中现在的数量是几
      var n=parseInt(
            //代替了innerHTML
        $this.html() //"click me(1000)"
        //              0123456789...-1
             .slice(9,-1)//      |   |
            //复习第一阶段
      );
      //4.2 数量+1
      n++;
      //4.3 将新数量再放回当前按钮内容中
      $this.html(`click me(${n})`)
          //代替了InnerHTML
    });
</script>
</body>
</html>

三. jQuery原理

1. 引入<script src="js/jquery-1.11.3.js">
	其实就是在内存中引入了一种新的类型: 2部分
	(1). 构造函数: 专门用来创建该类型的子对象
	(2). 原型对象: 专门为所有子对象保存共有的方法
2. 问题: 如何才能使用到jquery原型对象中的简化版函数
3. 解决: 今后只要想用jquery简化版函数,都必须先创建jquery家子对象
4. 如何: var jq=new jQuery()
5. 问题: jQuery家的所有简化版函数,都是用来操作DOM元素的,那么如何让jquery对象找到他们要操作的DOM元素呢?
6. 解决: 每次创建jQuery子对象时,都要提供一个选择器作为查找条件。jQuery构造函数先用选择器去查找符合要求的DOM元素。再将找到的DOM元素,保存到新创建的jquery子对象中。
7. 问题: jquery提供的简化版函数与DOM原生的函数不一致!
8. 解决: 所有jq子对象天生就自带一个翻译功能。当我们对整个jq子对象调用简化版函数时,jq子对象会自动将简化版函数,翻译为其对应的原生DOM属性和方法,直接作用到jq子对象内部保存的DOM元素上。
9. 问题: 如果每次要操作原生DOM元素时,都要写new jQuery(),太麻烦了!
10. 解决: jq作者,将new jQuery()这句话封装在了jQuery构造函数内。从此调用jQuery()即使不写new,构造函数内部也会自动new!
11. 问题: 如果每次操作原生DOM元素时,都要写jQuery(),太麻烦!
12. 解决: $=jQuery,从此用$等于用jQuery了。
	总结: $底层相当于new jQuery()
13. 问题: jquery也有查找元素的功能,DOM也有查找元素的功能。但是,DOM查找出的元素,不是jq家孩子,无法使用jquery家的简化版函数。而jquery查找的结果是jQuery家子对象,可以使用jq家简化版函数。为了避免jquery家子对象和DOM元素发生混淆,行业中约定俗成的规矩: 只要用$创建的jQuery家子对象,都要以$开头
14. 总结: 
	(1). 今后,只要想使用jQuery家简化版函数,都要先创建jquery家子对象
	(2). 创建jQuery家子对象的标配是: 
		var $变量名=$("任意css选择器")
15. 问题: jquery事件绑定中: this指向谁?
	$btn1.click(function(){ ...this->?.. })
16. 解答: 
	(1). 错误: 看似.前是$btn1,但是this绝对不指.前的jquery对象$btn1
	(2) .click会被自动翻译为原生DOM的onclick: 
		DOM的btn1.onclick=function(){ ... this ... }
		this->点前的原生DOM btn1元素
		无法直接使用jquery简化版函数的。
17. 问题: 难道我们要在事件处理函数外,使用简化版jq,而在事件处理函数内,只能用原生DOM吗?
18. 解决: 重载: 其实jQuery构造函数至少可以接两种参数
	(1). 当接到一个字符串选择器时,jQuery会先去DOM中查找符合要求的DOM元素,保存进新创建jq子对象中
	(2). 当$中接到的是一个原生DOM元素时,就不再查找,而是直接将这个DOM元素包装进一个jQuery子对象中。进而,就可以继续调用jq简化版函数了
	比如: 事件处理函数中的this:
		事件处理函数中的this注定只能指原生的DOM元素
		无法使用jq家简化版函数
		所以,今后在jq事件处理函数中,要使用this,都必须用$(this)包装成jQuery家子对象,才能使用jq简化版函数。

在这里插入图片描述

19. 问题: jq中有些函数即可获取旧值,又可以修改新值。
18. 解答: 其实jQuery中大多数函数都有三大特性
	(1). 一个函数两用: 重载
	a. 如果调用函数时,没有传入新值作为参数,则该函数默认执行获取旧值的操作
	b. 如果调用函数时,传入了新值作为参数,则该函数自动切换为修改新值的操作!
	(2). 自带遍历: 对整个jq子对象调用一次简化版函数,等效于对jq子对象内部保存的每个DOM元素分别调用一次简化版函数。
	a. 如果创建jQuery子对象时,选择器可以找到多个DOM元素,则jQuery子对象是可以保存多个DOM元素的。其实,jquery子对象本质上就是一个类数组对象。
	b. 如果想对jQuery子对象中保存的多个元素都执行相同的操作,不需要自己写for循环,只需要对整个jquery子对象调用一次简化版函数。jq子对象内部就会自动将简化版函数翻译为原生的DOM属性和方法,并通过内部自带的for循环遍历,将原生的DOM属性和方法,送到内部保存的每个DOM元素上。

在这里插入图片描述

	c. 示例: 使用jquery我三个按钮绑定相同的单击事件处理函数
<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <h1>jQueryAPI特点</h1>
  <button id="btn1">click me(0)</button>
  <button id="btn2">click me(0)</button>
  <button id="btn3">click me(0)</button>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //为三个按钮绑定单击事件,记录单击次数
    //DOM4步
    //1. 查找触发事件的元素
    //本例中: 要查找三个按钮
    var btns=document.getElementsByTagName("button");
    //2. 绑定事件处理函数
    //本例中: 遍历查找结果中每个按钮
    for(var btn of btns){
      btn.onclick=function(){
        //3. 查找要修改得元素
        //本例中: 就是要改当前按钮自己的内容:this
        //4. 修改元素
        //4.1 先取出当前按钮中现在的数量是几
        var n=parseInt(
          this.innerHTML //"click me(1000)"
          //                0123456789...-1
              .slice(9,-1)//         |   |
              //复习第一阶段
        );
        //4.2 数量+1
        n++;
        //4.3 将新数量再放回当前按钮内容中
        this.innerHTML=`click me(${n})`
      }
    }
  </script>
</body>
</html>
<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <h1>jQueryAPI特点</h1>
  <button id="btn1">click me(0)</button>
  <button id="btn2">click me(0)</button>
  <button id="btn3">click me(0)</button>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //为三个按钮绑定单击事件,记录单击次数
    //DOM4步
    //1. 查找触发事件的元素
    //本例中: 要查找三个按钮
    var $btns=$("button");
    //2. 绑定事件处理函数
    //本例中: 遍历查找结果中每个按钮
    $btns.click(function(){
      //3. 查找要修改得元素
      //本例中: 就是要改当前按钮自己的内容:this
      var $this=$(this);
      //4. 修改元素
      //4.1 先取出当前按钮中现在的数量是几
      var n=parseInt(
        $this.html() //"click me(1000)"
        //              0123456789...-1
             .slice(9,-1)//      |   |
            //复习第一阶段
      );
      //4.2 数量+1
      n++;
      //4.3 将新数量再放回当前按钮内容中
      $this.html(`click me(${n})`);
    })
  </script>
</body>
</html>
	(3). (待续...)

四. 查找:

  1. jQuery中查找元素基本上都用选择器查找: $(“选择器”)
  2. jQuery中支持几乎所有CSS3选择器
  3. 返回值: 无论找到一个元素还是多个元素,都返回一个jQuery家的子对象,其本质是一个类数组对象。
  4. jQuery还扩展了一些CSS3中没有,jquery中独有的新选择器
(1). 基本过滤选择器: 
	a. 复习CSS中子元素过滤选择器: 
		1). 什么是: 根据元素在其父元素下的相对位置选择元素
		2). 包括: //复习第二阶段子元素过滤选择器
		:first-child  :last-child   :nth-child(i)   :only-child
		3). 强调: css中的下标都是从1开始
		比如: 选择第2个孩子,应该:nth-child(2)
		4). 示例: 使用子元素过滤选择并修改制定元素:
<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8" />
 <title></title>
</head>
<body>
  <h3>子元素过滤选择器.</h3>
  <ul>
    <li>child1-basic0</li>
    <li>child2-basic1</li>
    <li>child3-basic2</li>
  </ul>
  <ul>
    <li>child1-basic3</li>
    <li>child2-basic4</li>
    <li>child3-basic5</li>
  </ul>
  <ul>
    <li>child1-basic6</li>
  </ul>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //查找每个ul中第一个li
    $("ul>li:first-child")
    .css("border","2px solid red");
  //.style.border="2px solid red"
  //<li style="border:2px solid red">
    //查找每个ul中最后一个li
    $("ul>li:last-child")
    .css("color","green");
    //查找每个ul中处于偶数位置的li
    $("ul>li:nth-child(2n)")
    .css("box-shadow","0 0 5px blue")
    //查找每个ul中第2个li
    $("ul>li:nth-child(2)")
    .css("height","50px")
    //查找作为ul下唯一子元素的li
    $("ul>li:only-child")
    .css("background-color","yellow");
  </script>
</body>
</html>

在这里插入图片描述

	b. 基本过滤选择器: CSS中没有,只有jq中才有
		1). 什么是: 先将所以符合要求的元素其中放在一个大的集合中统一编号。按元素在集合中的下标位置选择元素
		2). 何时: 今后只要希望按照元素在查找结果中的大排名位置选择元素时,而不考虑元素原来再起父元素中的相对位置时,都用基本过滤选择器
		3). 包含: 
		i. :first / :last  选择在查找结果中排第一或最后的一个元素
		ii. :even / :odd   选择在查找结果中下标为偶数或奇数的元素
          偶数  奇数
		  强调: 因为下标从0开始,所以基本过滤选择器的奇偶和正常人眼里的奇偶是错位的!

在这里插入图片描述

		iii. :eq(i) / :gt(i) / :lt(i)  专门匹配下标等于i位置、大于i位置、小于i位置的元素
		eq 是equal的缩写
              等于
		gt 是greater than的缩写
               大    于
		lt  是less than的缩写
              小  于

在这里插入图片描述

		4). 示例: 使用基本过滤选择器,选择并修改指定元素
<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8" />
 <title></title>
</head>
<body>
  <h3>基本过滤选择器.</h3>
  <ul>
    <li>child1-basic0</li>
    <li>child2-basic1</li>
    <li>child3-basic2</li>
  </ul>
  <ul>
    <li>child1-basic3</li>
    <li>child2-basic4</li>
    <li>child3-basic5</li>
  </ul>
  <ul>
    <li>child1-basic6</li>
  </ul>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //查找第一个li
    $("ul>li:first").css("border","2px solid red");
    //查找最后一个li
    $("ul>li:last").css("color","green");
    //查找处于偶数位置(用户视角)的li
    $("ul>li:odd").css("background-color","lightBlue");
    //查找第2个li
    $("ul>li:eq(1)").css("box-shadow","0 0 5px yellow");
  </script>
</body>
</html>

在这里插入图片描述
在这里插入图片描述

1. 内容过滤选择器:

	(1). 什么是: 按元素的内容选择元素
	(2). 包括: 
	a. :contains(文本) 专门选择元素内容中包含指定文本的元素
	b. :has(选择器) 专门选择子元素中包含符合选择器要求的元素的父元素——用子元素的特征来选择父元素
	c. :parent 专门选择内容不为空的元素
	d. :empty 专门选择  内容为空的元素
	(3). 示例: 
<!DOCTYPE html>
<html>

<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <link rel="stylesheet" href="css/bootstrap.css" />
  <style>
  </style>
</head>

<body>
  <div class="container">
    <h1>jQuery中的选择器——内容过滤选择器</h1>

    <button>提交订单</button>
    <button>Submit注册信息</button>
    <button>马上提交</button>
    <button>清空重填</button>

    <hr />
    <div class="alert" id="alert1"></div>
    <div class="alert" id="alert2">
      <span class="close">×</span>
      第一个警告框
    </div>

  </div>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //选择包含"提交"二字的按钮,变为绿色按钮
    $("button:contains(提交)")
      .css("background-color", "green")
    //选中包含.close按钮的.alert元素,让它们变为红色的警告框
    $(".alert:has(.close)")
      .css("background-color", "pink");
    //选中不包含.close按钮的.alert元素,让它们变为绿色的警告框
    $(".alert:not(:has(.close))")
      .css("background-color", "lightGreen");
    //给空的对话框元素添加红色阴影
    $(".alert:empty").css("box-shadow", "0 0 5px red")
    //给非空的对话框元素添加绿色阴影
    $(".alert:parent").css("box-shadow", "0 0 5px green")
  </script>
</body>

</html>

在这里插入图片描述

2. 可见性过滤选择器:

	(1). 什么是: 根据元素是否可见,来查找元素
	(2). 包括: 
	a. :visible  专门选择可见的元素
	b. :hidden  专门选择不可见的元素
	(3). 强调: 只能选择display:none和type="hidden"隐藏的元素。无法选择visibility:hidden和opacity:0隐藏的元素。

3. 表单元素过滤选择器:

	(1). 什么是: 专门选择不同类型的表单元素
	(2). 包括:
	a. :input  选择所有表单元素(input、textarea、select、button)
	   input  是css的元素选择器,只能选择input元素
	b. 专门选择不同type类型的input的选择器: 
		:text   专门选择type为text的普通文本框
		:password   专门选择type为password的密码框
		:radio   专门选择type为radio的单选按钮
		:checkbox   专门选择type为checkbox的复选框
		:submit  专门选择type为submit的提交按钮
		... 每种input的type属性值,都有一个专门对应的选择器 ...
	(3). 示例: 点击同意,启用或禁用按钮
<!DOCTYPE html>
<html>
 <head>
  <title>.....</title>
  <meta charset="utf-8"/>
  <style>
  </style>
 </head>
 <body>
  <form>
    用户名:<input disabled></br>
    密码:<input type="password" disabled></br>
    <input type="checkbox">我同意本站的使用条款<br>
    <input type="submit" value="提交注册信息" disabled/>
  </form>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //DOM 4步
    //1. 查找触发事件的元素
    //本例中: type为checkbox的input元素触发了事件
    $(":checkbox")
    //2. 绑定事件处理函数
    .click(function(){
      //this->当前点击的原生的checkbox元素对象
      //3. 查找要修改的元素
      //本例中: 要修改除了type为checkbox的其它元素
      var $others=$(":input:not(:checkbox)")
      //4. 修改元素
      //如果当前checkbox是选中的,说明同意
      //复习DOM第二天的bool类型标准属性
      if(this.checked==true){
        //则其它元素启用,则disabled属性为false
        $others.prop("disabled",false)
              //property 属性
          //.prop是专门用来修改元素属性值的函数
      }else{//否则如果当前checkbox是未选中的,说明不同意
        //则其它元素禁用,则disabled属性为true
        $others.prop("disabled",true)
      }
      
    })
  </script>
 </body>
</html>

在这里插入图片描述
在这里插入图片描述

五.修改

1. 内容: 3种

	(1). 元素开始标签到结束标签之间的原始的HTML内容
	a. DOM中: 元素.innerHTML
	b. jq中: $元素.html(新html内容)
	(2). 元素开始标签到结束标签之间的纯文本内容
	a. DOM中: 元素.textContent
	b. jq中: $元素.text(文本内容)
	(3). 表单元素的值
	a. DOM中: 表单元素.value
	b. jq中: $元素.val(新值)
	(4). 示例: 使用元素内容,实现表单验证:
<!DOCTYPE html>
<html>
 <head>
  <title> new document </title>
  <meta charset="utf-8">
 </head>
 <body>
  <h1>操作元素的内容和值</h1>
  <form action="">
    用户名:<input name="uname">
          <span></span><br>
    密码:<input type="password" name="upwd">
          <span></span><br>
    <input type="button" value="提交注册信息">
  </form>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //正确时,使用图片:"<img src='img/ok.png'>"
    //姓名错误时: "<img src='img/err.png'>用户名必须介于3~9位之间!"
    //密码错误时: "<img src='img/err.png'>密码必须介于6~8位之间!"
    //DOM 4步
    //1. 查找触发事件的元素
    //本例中: 当姓名文本框失去焦点时,触发验证
    //因为表单中只有姓名文本框是普通的文本框,所以可以用:text,选择input type="text"的文本框
    $(":text")
    //2. 绑定事件处理函数
    .blur(function(){
      //this->当前失去焦点的文本框DOM元素对象
      //要想调用简化版函数,必须: 
      var $this=$(this);
      //3. 查找要修改的元素
      //本例中: 查找当前文本框的下一个兄弟span
      var $span=$this.next();
                //this.nextElementSibling;
      //4. 修改元素
      //如果当前文本框的内容的长度>=3位且<=9位
      if($this.val().length>=3&&$this.val().length<=9){
        //就将span的内容改为正确的内容
        $span.html(`<img src='img/ok.png'>`)
      }else{//否则如果当前文本框的内容长度不符合要求
        //就将span的内容改为错误的内容
        $span.html(`<img src='img/err.png'>用户名必须介于3~9位之间!`)
      }
    })
  </script>
 </body>
</html>

在这里插入图片描述
在这里插入图片描述

2. 属性: 3种:

	(1). 字符串类型的HTML标准属性
	a. DOM中: 2种: 
		1). 旧的核心DOM: 
		i. 元素.getAttribute("属性名")
		ii. 元素.setAttribute("属性名","新值")
		2). 新的HTML DOM简写: 
		元素.属性名
	b. jq中: 2种: 
		1). 代替旧核心DOM: 
		$元素.attr("属性名","新属性值")
		2). 代替新HTML DOM: 
		$元素.prop("属性名","新属性值")
			  property属性 的缩写
			  专门用来获取或修改元素的属性值
		
	(2). bool类型的HTML标准属性
	a. DOM中: 只能用新的HTML DOM访问: 
		元素.属性名
	b. jq中: 只能用$元素.prop("属性名",bool值)
	(3). 自定义扩展属性
	a. DOM中: 
		1). 旧核心DOM
		2). HTML5 dataset
	b. jq中: 
		1). $元素.attr("data-自定义属性","属性值")
		2). jq中没有代替dataset的函数的。因为jq诞生时,还没有HTML5标准呢。
	(4). 总结: 
	a. 字符串类型的HTML标准属性: 2种
		$元素.attr()  $元素.prop()
	b. bool类型的HTML标准属性: 1种: $元素.prop()
	c. 自定义扩展属性: 1种: $元素.attr();

3. 样式

	(1). DOM: 
	a. 修改一个元素的css属性: 元素.style.css属性
	b. 获取一个元素的css属性值: getComputedStyle(元素)
	(2). jq中: 统一为$元素.css("css属性名","css属性值")
	a. 当提供了新css属性值时,css()内部自动执行.style操作,修改元素的内联样式:
	b. 当未提供新css属性值时,css()内部自动切换为执行getComputedStyle()获取计算后的完成样式.
	(3). 问题: .css()只能一个属性一个属性的修改元素的样式。如果一个效果需要批量修改一个元素的多个css属性,则使用.css()就会很繁琐。
	(4). 解决: 用class代替单独修改个别css属性值。
	(5). 问题: DOM中className属性代表的是整个class属性值字符串。极其不便于只修改其中某一个class。
		比如: <button class="btn btn-success active"
		DOM中只想去掉active class:
		btn.className.replace("active","");
		DOM中想给按钮加上一个新class item
		btn.className="item"; //错误: 整体覆盖
		btn.className+="item"; //错误: item会和上一个class名连接起来成为一个class名,无法区分
		btn.className+="  item";//麻烦!
	(6). 解决: jq中专门提供了四个操作class的函数: 
	a. $元素.addClass("class名")  专门向元素添加一个新class
	b. $元素.removeClass("class名") 专门从元素上移除一个class
	c. var bool=$元素.hasClass("class名") 专门判断一个元素是否包含某个class
	d. $元素.toggleClass("class名")  专门在有或没有这个class之间来回切换
		1). 相当于: 
		if($元素.hasClass("class名")){
			$元素.removeClass("class名")
		}else{
			$元素.addClass("class名")
		}
		2). 问题: 是不是记住toggleClass,就可以不记addClass()、removeClass()、hasClass()呢?
		3). 解答: 不行
		i. toggleClass,不是总执行addClass,也不是总执行removeClass。它是一次addClass(),一次removeClass()交替执行。所以,无法彻底代替addClass(),和removeClass()
		ii. 除非真的是想在有或者没有一个class之间来回切换时,才用toggleClass();
	(7). 优点: 只影响当前一个class,不会影响其他class。

4. 简写: 其实, .attr()、.prop()和.css()都可以一次性修改多个属性:
	$元素.attr 或 prop 或 css({
		属性名: 新值,
		    ... : ...
	})
5. 示例: 点图片切换下一张图片

在这里插入图片描述

<!DOCTYPE html>
<html>
 <head>
  <title> new document </title>
  <meta charset="utf-8">
 </head>
 <body>
  <h1>操作元素的属性</h1>
  <img src="img/1.jpg" alt="1">
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //单击图片,切换下一张
    //DOM 4步
    //1. 查找触发事件的元素
    //本例中: 点击img触发变化
    $("img")
    //2. 绑定事件处理函数
    .click(function(){
      //3. 查找要修改的元素
      //本例中: 点图片就是要修改自己
      var $this=$(this);
      //4. 修改元素
      //4.1 获取当前图片上alt属性的值
      //因为alt属性是HTML标准中规定的字符串类型的属性,所以既可以用.attr(),又可以用.prop()
      var i=parseInt($this.attr("alt"))
                         //prop
      //4.2 如果i<4,才i+1,否则i=1
      if(i<4){
        i++;
      }else{
        i=1;
      }
      //4.3 将新值i,既放入当前图片的src属性中,又放到alt属性中
      //因为src属性是HTML标准中规定的字符串类型的属性,所以,既可以用.attr(),又可以用.prop()
      // $this.attr("src",`img/${i}.jpg`);
      //    //prop
      // $this.attr("alt",i);
      //    //prop
      $this.attr({
          //prop
        src:`img/${i}.jpg`,
        alt:i
      })
    })
  </script>
 </body>
</html>
6. 示例: 点小图片,切换大图片
<!DOCTYPE html>
<html>

<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <style>
    body {
      text-align: center;
    }
  </style>
</head>

<body>
  <img src="img/1.jpg" data-target="img/1-l.jpg" class="my-small">
  <img src="img/2.jpg" data-target="img/2-l.jpg" class="my-small">
  <img src="img/3.jpg" data-target="img/3-l.jpg" class="my-small">
  <img src="img/4.jpg" data-target="img/4-l.jpg" class="my-small">
  <hr />
  <img src="img/1-l.jpg" class="my-big">
  <script src="js/jquery-1.11.3.js"></script>
  <script>
  //点击小图片,下方my-big中显示大图片
  //DOM 4步
  //1. 查找触发事件的元素
  //本例中: 点四个小图片都会触发变化
  $(".my-small")
  //2. 绑定事件处理函数
  //自带for遍历
  // .click(function(){
  .mouseover(function(){
    //this->当前点击的小图片DOM元素
    var $this=$(this);
    //3. 查找要修改的元素
    //本例中: 要修改大图片: 
    var $big=$(".my-big");
    //4. 修改元素
    //4.1 先取出当前点击的img上data-target属性中保存的大图片路径
    //因为data-target是自定义扩展属性,所以只能用attr访问
    var src=$this.attr("data-target");
                //prop
    //4.2 将大图片路径设置到$big的src属性上
    //因为src是字符串格式的HTML标准属性,所以既可以用.attr(),又可以用.prop()
    $big.attr("src",src);
      // prop
  })

  </script>
</body>

</html>

在这里插入图片描述

7. 示例: 双态按钮: 
<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <style>
    .btn {
      padding: 5px 10px;
      border-radius: 3px;
      border: 1px solid #aaa;
      outline: none;
    }
    /*按钮抬起时的样式类*/
    .up {
      background: #fff;
      color: #333;
    }
    /*按钮按下时的样式类*/
    .down {
      background: #ddd;
      color: #fff;
    }
  </style>
</head>
<body>

  <button class="btn up">双态按钮</button>

<script src="js/jquery-1.11.3.js"></script>
<script>
  //双态按钮: 让按钮的class在up和down之间切换
  //DOM 4步
  //1. 查找触发事件的元素
  //本例中: 点按钮触发变化
  $("button")
  //2. 绑定事件处理函数
  .click(function(){
    //3. 查找要修改的元素
    //本例中: 就是要修改自己
    var $this=$(this);
    //4. 修改元素
    //如果当前按钮有class down
    // if($this.hasClass("down")){
    //   //给当前按钮移除down class
    //   $this.removeClass("down");
    // }else{//否则如果当前按钮没有class down
    //   //给当前按钮添加down class
    //   $this.addClass("down");
    // }
    $this.toggleClass("down");
  })
</script>
</body>
</html>

在这里插入图片描述
在这里插入图片描述

六. 按节点间关系查找:

1. DOM中: 2大类

	(1). 父子关系: 4个
	a. 元素的父元素: 元素.parentElement
	b. 元素的所有直接子元素们: 元素.children
	c. 元素的第一个直接子元素: 元素.firstElementChild
	d. 元素的最后一个直接子元素: 元素.lastElementChild
	(2). 兄弟关系: 2个
	a. 元素的前一个兄弟元素: 
		元素.previousElementSibling
	b. 元素的后一个兄弟元素:
		元素.nextElementSibling

2. jq中: 2大类关系,8个函数

	(1). 父子关系: 3个函数
	a. 获得元素的父元素: $元素.parent()
	b. 获得元素的所有直接子元素们: 
		1). 增强版: $元素.children("选择器")
		i. 旧.children,只能获取所有直接子元素,无法有选择的获取个别直接子元素
		ii. jq中.children(),可以用选择器,只选择符合要求的个别子元素。
		2). 问题: children的局限是,只能在直接子元素中查找符合要求的元素。无法在所有后代中查找。
		3). 解决: jq新增了一个函数: $元素.find("选择器"),专门在所有后代中查找符合要求的元素。
	c. 获得第一个直接子元素: 
		1). jq中没有专门对应的函数
		2). jq中: 用 .children(":first-child") 代替
	d. 获得最后一个直接子元素: 
		1). jq中没有专门对应的函数
		2). jq中: 用 .children(":last-child") 代替

在这里插入图片描述

	(2). 兄弟关系: 5个函数
	a. 前一个兄弟: $元素.prev()
	b. 之前所有兄弟: $元素.prevAll("选择器")
	c. 后一个兄弟: $元素.next()
	d. 之后所有兄弟: $元素.nextAll("选择器")
	e. 除自己之外,其余所有兄弟: $元素.siblings("选择器")

在这里插入图片描述
在这里插入图片描述

3. 示例: 标签页

在这里插入图片描述

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <style>
    .tabs{ list-style:none; padding:0 }
    .tabs a{
      text-decoration:none;
      color:#000;
      padding:6px 12px;
      display:inline-block;
    }
    .tabs>li{
      float:left;
      border-bottom:1px solid #000;
    }
    .tabs>.active{
      border:1px solid #000;
      border-bottom:0;
    }
  </style>
 </head>
 <body>
    <h1>使用属性选择器实现标签页头的切换</h1>
    <ul class="tabs">
      <li class="active">
        <a data-toggle="tab" href="#">十元套餐</a>
      </li>
      <li>
        <a data-toggle="tab" href="#">二十元套餐</a>
      </li>
      <li>
        <a data-toggle="tab" href="#">三十元套餐</a>
      </li>
    </ul>
    <script src="js/jquery-1.11.3.js"></script>
    <script>
      //DOM 4步
      //1. 查找触发事件的元素
      //本例中: 点击每个li中的带有data-toggle属性,且属性值为tab的元素,触发事件: 
      var $tabs=$("ul.tabs>li>[data-toggle=tab]");
      //2. 绑定事件处理函数
      //自带for遍历
      $tabs.click(function(){
        //this->当前点击的a元素
        var $this=$(this);
        //3. 查找要修改的元素
        //4. 修改元素
        //先给自己的父元素li,添加class active
        $this
        .parent()
        .addClass("active")
        //自动return $this.parent()
        //再给自己的父元素li的其余兄弟移除class active
        .siblings()
        .removeClass("active");
      })
    </script>
 </body>
</html>

在这里插入图片描述
总结: jQuery简化版函数3大特点:
(1). 自带for循环:
(2). 一个函数两用:
(3). 大多数函数都会自动返回当前.前的主语对象: 如果前一个函数返回的对象,刚好是下一个函数需要的主语,就可以连续使用.继续调用下一个函数——链式操作

七. 添加/删除/替换/克隆

1. 添加新元素:

	(1). DOM中: 
	a. 添加一个新元素:3步: 
		1). 创建一个新的空元素: 
		var 新元素=document.createElement("标签名")
		2). 设置必要属性
		新元素.属性名="属性值"
		3). 将新元素添加到DOM树
		i. 在父元素下所有子元素末尾追加: 
			父元素.appendChild(新元素)
		ii. 在父元素下一个现有子元素前插入: 
			父元素.insertBefore(新元素, 现有元素)
		iii. 替换父元素下一个现有子元素:
			父元素.replaceChild(新元素, 现有元素)
	b. 同时添加多个新元素: 2种: 
		1). 同时添加父元素和子元素时,应该先将子元素添加到父元素,最后,再一次性将父元素添加到DOM树
		2). 如果父元素已经在DOM树上了,要同时添加多个平级子元素,就要借助与文档片段: 3步
		i. 先创建文档片段: 
		var frag=document.createDocumentFragment()
		ii. 将子元素添加到文档片段中: 
		frag.appendChild(子元素)
		iii. 将frag一次性添加到DOM树上
		父元素.appendChild(frag)
	(2). jq中,无论要添加多少元素都只需要2步: 	
	a. 先用HTML代码片段创建所有要添加的新元素: 
	var $新元素=$(`HTML代码片段`)
	b. 将$新元素添加到DOM树上: 
		1). 强调: 如果$新元素中包含多个新元素要添加到DOM树,jq会自动创建文档片段对象,使用优化的方式添加到DOM树。从此,不用我们自己再写文档片段。
		2). 包括: 10个函数
		a. 将新元素追加到所有子元素末尾: 
		  $父元素.append($新元素) //自动返回$父元素
		  $新元素.appendTo($父元素) //自动返回$新元素
		b. 将新元素插入到所有子元素开头: 
		  $父元素.prepend($新元素)//自动返回$父元素
		  $新元素.prependTo($父元素)//自动返回$新元素
		c. 将新元素插入到一个现有元素之前: 
		  $现有元素.before($新元素)//自动返回$现有元素
		  $新元素.insertBefore($现有元素)//自动返回$新元素
		d. 将新元素插入到一个现有元素之后: 
		  $现有元素.after($新元素) //自动返回$现有元素
		  $新元素.insertAfter($现有元素)//自动返回$新元素
		e. 用新元素替换一个现有元素
		  $现有元素.replaceWith($新元素) //自动返回$现有元素
		  $新元素.replaceAll($现有元素) //自动返回$新元素

在这里插入图片描述

2. 删除元素:$元素.remove()

3. 示例: 点击按钮,添加方块,点击×,删除方块:

<!DOCTYPE html>
<html>
 <head>
  <title> new document </title>
  <meta charset="utf-8">
  <style>
    .container {
      border: 1px solid #aaa;  overflow:hidden;
    }
    .block {
      float: left; margin: 10px;
      border: 1px solid #aaa;
      background: #faa;
      width: 150px; height: 150px;
    }
    .block:hover{ box-shadow:0 5px 6px #000; }
    .close {
      float:right; padding:5px;
      font-weight:bold; opacity:.2; cursor: pointer;
    }
    .close:hover { opacity: .5; }
  </style>
 </head>
 <body>
  <h1>添加/删除节点</h1>
  <button id="add-block">添加区块</button>
  
  <div class="container">
    <!-- <div class="block">
      <span class="close">×</span>
    </div> -->
  </div>
  
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //第一个功能: 点按钮,动态生成方块,随机背景色
    //DOM 4步
    //1. 查找触发事件的元素
    //本例中,点按钮触发变化: 
    $("#add-block")
    //2. 绑定事件处理函数
    .click(function(){
      //3. 查找要修改的元素
      //本例中,新生成的方块,都是要添加到class为container的div中
      //4. 修改元素
      //4.1 新创建一个方块: 
      $(`<div class="block">
        <span class="close">×</span>
      </div>`)
      //4.2 设置新方块随机背景色:
      .css(
        "background-color",
        `rgb(${
          parseInt(Math.random()*255)
        },${
          parseInt(Math.random()*255)
        },${
          parseInt(Math.random()*255)
        })`
      )//return $新方块
      //4.3 将方块插入到div的开头
      // .prependTo($(".container"));
      .prependTo(".container");
      //10个将新元素添加到DOM树的函数,都自带查找功能。我们只需要提供选择器即可!
    });
    //点×删除方块: 
    //DOM4步
    //1. 查找触发事件的元素
    //本例中: 因为多个×都能单击,所以应该用事件委托优化。事件应该只绑定在父元素上一份即可
    $(".container")
    //2. 绑定事件处理函数
    .click(function(e){
      //用e.target代替this
      var $span=$(e.target);
      //判断当前目标元素是否是想要的
      //如果点击的元素的内容是×
      if($span.html()=="×"){
        //3. 查找要修改的元素
        //本例中,点span,要删除父元素div
        $span.parent()
        //4. 修改元素:删除元素
        .remove()
      }
    })
  </script>
  
 </body>
</html>

在这里插入图片描述

4. 克隆元素: var 一 模 一 样 的 新 元 素 = 一模一样的新元素= =旧元素.clone()

5. 示例: 选飞机:

<!DOCTYPE html>
<html>

<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <style>
    body {
      text-align: center;
    }
  </style>
</head>

<body>
  <h1>替换节点</h1>

  <div id="chosen">
    <img src="img/p0.png">
  </div>
  <hr />
  <div id="list">
    <img src="img/p3.png">
    <img src="img/p4.png">
    <img src="img/p5.png">
  </div>

  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //DOM 4步
    //1. 查找触发事件的元素
    //本例中: id为list下的所有img都可以单击,所以应该用事件委托优化。事件只绑定在父元素list上一份即可
    $("#list")
    //2. 绑定事件处理函数
    .click(function(e){
      //用e.target代替this
      var $img=$(e.target);
      //判断当前点击的元素是不是img元素
      //错误:因为$img已经是jq家孩子了,无法使用DOM家原生的属性和方法 
      //if($img.nodeName=="IMG"){
      //正确:    元素选择器
      if($img.is("img")){
        //3. 查找要修改的元素
        //本例中: 点下方的飞机,要修改上方id为chosen下的img飞机
        $("#chosen>img")
        //4. 修改元素
        //先将当前点击的飞机,克隆一个副本,用副本代替上方的飞机。
        .replaceWith($img.clone());
      }
    })
  </script>
</body>

</html>

在这里插入图片描述
在这里插入图片描述

补: $元素.is("选择器")
        是
专门判断.前的元素是否符合选择器的要求!如果.前的元素符合选择器的要求,则返回true。如果.前的元素不符合选择器的要求,则返回false。

八. 事件:

1. 绑定事件处理函数

	(1). DOM中: js中绑定: 2种: 
	a. 赋值: 元素.on事件名=function(){ ... }
	b. 添加事件监听: 
	  元素.addEventListener("事件名",事件处理函数)
	  元素.removeEventListener("事件名", 原事件处理函数)
	  
	(2). jq中: 1种: 添加事件监听方式
	a. 标准: $元素.on("事件名",事件处理函数)
			$元素.off("事件名", 原事件处理函数对象)
	b. 简写: 如果要绑定的事件属于常用事件列表中,则可以省略on
		$元素.事件名(事件处理函数)
	比如: $btn.click(function(){ ... })
	c. 常用事件列表: 
		blur 失去焦点 
		change 下拉列表选中项改变 
		click 单击 
		dblclick 双击 
		focus 获得焦点  
		keydown 键盘按键按下 
		keyup 键盘按键抬起
		mousedown 鼠标按键按下 
		mouseenter 鼠标进入(jq)
		mouseleave 鼠标移出(jq)
		mousemove  鼠标移动
		mouseout 鼠标移出(dom)
		mouseover 鼠标进入(dom)
		mouseup 鼠标按键抬起
		resize  窗口大小改变
		scroll  网页滚动
		load 加载完成

	(3). 问题: DOM中如果绑定时,使用有名称的函数绑定,则只能添加一次同名的事件处理函数。无法反复添加多个同名事件处理函数——DOM没有解决
	
	(4). jq中: 即使使用有名称的函数,也能反复添加多个同名的事件处理函数。当使用函数名移除事件处理函数时,会一次性将所有同名的事件处理函数都移除。
	
	(5). 示例: 使用jq绑定和移除事件处理函数
<!DOCTYPE html>
<html>
 <head>
  <title> new document </title>
  <meta charset="utf-8">
 </head>
 <body>
  <h1>事件绑定</h1>
  <button id="btn1">发射子弹</button>
  <button id="btn2">获得奖励</button>
  <button id="btn3">失去奖励</button>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    var $btn1=$("#btn1");
    var $btn2=$("#btn2");
    var $btn3=$("#btn3");
    //单击btn1时,发射普通子弹
    $btn1.click(function(){
      console.log(`发射普通子弹......`)
    })
    function shoot2(){
      alert(`发射跟踪导弹=>=>=>`)
    }
    //单击btn2时,给btn1多添加一种跟踪导弹
    $btn2.click(function(){
      $btn1.click(shoot2)
    })
    //单击btn3时,从btn1上移除跟踪导弹
    $btn3.click(function(){
      $btn1.off("click",shoot2)
    })
  </script>
 </body>
</html>

在这里插入图片描述

2. 事件委托: (了解)

	(1). DOM中: 3步
	a. 事件只绑定在父元素上一份即可
	b. 用e.target代替this
	c. 判断e.target是不是想要的元素
	父元素.onclick=function(e){
		//用e.target代替this
		if(e.target是xxx元素){
			才执行事件操作
		}
	}
	(2). jq中: 3步
	a. 事件还是要绑定在父元素上,但是,必须用.on("事件名")方式绑定
	b. 在.on()添加第二个实参值——选择器,作为自动判断当前元素是否符合要求的条件
		1). .on()会用选择器自动判断当前元素是否符合要求。
		i. 只有当前点击的元素符合选择器要求时,才执行事件处理函数
		ii. 如果当前点击的元素不符合选择器要求时,就不执行事件处理函数
		2). 事件处理函数内部,就不用自己写if了!
	c. jq中,如果用.on方式实现事件委托,则this又重新指回了目标元素。不用e.target了!
					   判断条件
	$父元素.on("事件名","选择器",function(){
		//this->目标元素,不用e.target了!
		//也不用自己写if了
	})
	(3). 示例: 使用jq事件委托简化删除方块功能
<!DOCTYPE html>
<html>
 <head>
  <title> new document </title>
  <meta charset="utf-8">
  <style>
    .container {
      border: 1px solid #aaa;  overflow:hidden;
    }
    .block {
      float: left; margin: 10px;
      border: 1px solid #aaa;
      background: #faa;
      width: 150px; height: 150px;
    }
    .block:hover{ box-shadow:0 5px 6px #000; }
    .close {
      float:right; padding:5px;
      font-weight:bold; opacity:.2; cursor: pointer;
    }
    .close:hover { opacity: .5; }
  </style>
 </head>
 <body>
  <h1>添加/删除节点</h1>
  <button id="add-block">添加区块</button>
  
  <div class="container">
    <!-- <div class="block">
      <span class="close">×</span>
    </div> -->
  </div>
  
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //第一个功能: 点按钮,动态生成方块,随机背景色
    //DOM 4步
    //1. 查找触发事件的元素
    //本例中,点按钮触发变化: 
    $("#add-block")
    //2. 绑定事件处理函数
    .click(function(){
      //3. 查找要修改的元素
      //本例中,新生成的方块,都是要添加到class为container的div中
      //4. 修改元素
      //4.1 新创建一个方块: 
      $(`<div class="block">
        <span class="close">×</span>
      </div>`)
      //4.2 设置新方块随机背景色:
      .css(
        "background-color",
        `rgb(${
          parseInt(Math.random()*255)
        },${
          parseInt(Math.random()*255)
        },${
          parseInt(Math.random()*255)
        })`
      )//return $新方块
      //4.3 将方块插入到div的开头
      // .prependTo($(".container"));
      .prependTo(".container");
      //10个将新元素添加到DOM树的函数,都自带查找功能。我们只需要提供选择器即可!
    });
    //点×删除方块: 
    //DOM4步
    //1. 查找触发事件的元素
    //本例中: 因为多个×都能单击,所以应该用事件委托优化。事件应该只绑定在父元素上一份即可
    $(".container")
    //2. 绑定事件处理函数
    //只允许class为close的元素触发事件
    .on("click",".close",function(){
      //this指当前点击的这个span.close元素
      $(this)
      //3. 查找要修改的元素
      //本例中,点span,要删除父元素div
      .parent()
      //4. 修改元素:删除元素
      .remove()
    })
  </script>
  
 </body>
</html>

在这里插入图片描述

3. 页面加载完成后自动执行:

	(1). 问题: 今后,所有js代码都不会放在.html网页中。都是保存在网页外部的专门.js文件中的。然后,网页通过<script src="">引入外部独立的js文件,来运行js程序。但是,绝大多数js程序,要求必须在所有网页内容加载完成后,才能正常执行!但是,公司里,有人喜欢把js文件在head中集中引入,有人喜欢把js文件放在body结尾引入。如何保证无论这个js文件是在网页开头引入,还是在网页结尾引入,都能正常执行呢?
	(2). 解决: 
	a. 在整个网页加载完成时,浏览器内部会自动触发一个事件: window.onload=function(){ ... }。凡是放入window.onload中的代码,都不是立刻执行,而是必须等到整个网页所有内容都加载完才能自动执行。
	b. 如果在js文件中,不是立刻执行js程序,而是暂时将要执行的js程序,放入window的onload事件中保存,就可以实现,无论在哪里引入js文件,都能保证,注定只能在整个页面所有内容加载完才执行!

在这里插入图片描述

	(3). 问题: 如果页面功能比较多/复杂时,经常需要多个人在多个js文件中,各自编写各自的代码。最后,再引入一
个网页中一起运行!但是,如果多个js中都包含window.onload=function(){ ... },会发生冲突!只有最后引
入的js文件中的window.onload=function(){ ... }会覆盖之前所有,保存下来。

在这里插入图片描述

	(4). 解决: 用addEventListener()代替onload
	window.addEventListener("load",function(){
		... ...
	})

在这里插入图片描述

	(5). 问题: window.onload事件,必须等待所有网页内容(HTML+CSS+JS+图片)都加载完,才能执行。有点晚。有些着急的操作,用户根本不会关心css样式和图片,就希望第一时间尽快用上!比如: 抢票。
	(6). 解决: 其实,在整个页面加载过程中,有两次页面加载完成事件。
	a. 先触发一个DOMContentLoaded事件。仅HTML+JS加载完就能提前触发。无需等待CSS和图片,就可提前用上功能。早!
	window.addEventListener("DOMContentLoaded",function(){
		... ...
	})
	b. 后触发一个window.onload。必须等待所有网页内容HTML+CSS+JS+图片都加载完。晚!

在这里插入图片描述
在这里插入图片描述

	(7). 总结: 今后,只要希望在页面加载完成后就能自动执行的操作,都要放在DOMContentLoaded事件中提前触发,让用户提前使用。
	(8). 问题: DOMContentLoaded事件将来用的很频繁,但是反复写,就很繁琐
	(9). 解决: 
	a. $(document).ready(function(){ ... })
       DOM内容已就绪
	b. 简写: $().ready(function(){ ... })
	c. 更简写: $(function(){ ... })
	d. 和ES6结合: $(()=>{ ... })
	e. 强调: 因为事件处理函数不是立刻执行,所以结尾不能加()
	(10). 总结: 
	a. 今后只要编写jq代码都要放在$(function(){ ... })$(()=>{ ... })中!
	b. $(function(){ ... }) 是在绑定DOMContentLoaded事件。
	(11). 示例: 在DOM内容加载完成时,就给按钮绑定单击事件: 
//直接放在js文件中的代码,被引入网页时,都是立刻执行的!
//但是,放在window.onload中的代码,属于事件绑定,暂时不执行的!注定只能在整个网页内容加载完成后,触发加载完成事件时,才能被自动执行
// window.οnlοad=function(){
// window.addEventListener("load",function(){
// window.addEventListener("DOMContentLoaded",function(){
//$(document).ready(function(){
// $().ready(function(){
// $(function(){
$(()=>{
  alert("DOMContentLoaded时,给btn1绑定单击事件")
  $("#btn1").click(function(){
    alert(`btn1 疼!`)
  })
})//强调: 结尾一定不要加()
// window.οnlοad=function(){
// window.addEventListener("load",function(){
// window.addEventListener("DOMContentLoaded",function(){
//$(document).ready(function(){
// $().ready(function(){
// $(function(){
$(()=>{
  alert("DOMContentLoaded时,给btn2绑定单击事件")
  $("#btn2").click(function(){
    alert(`btn2 疼!`)
  })
})
<!DOCTYPE html>
<html>

<head>
  <title> new document </title>
  <meta charset="utf-8">
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    // window.οnlοad=function(){
    $(window).load(function(){
      alert(`所有网页内容(HTML+CSS+JS+图片)都加载完成!`)
    });
  </script>
  <script src="14_ready.js">
    //window.οnlοad=function(){
    //window.addEventListener("load",function(){ 
    //window.addEventListener("DOMContentLoaded",function(){ 
      //...
    //}
  </script>
  <script src="14_ready2.js">
    //window.οnlοad=function(){
    //window.addEventListener("load",function(){  
    //window.addEventListener("DOMContentLoaded",function(){
      //...
    //}
  </script>
</head>

<body>
  <button id="btn1">click me1</button>
  <button id="btn2">click me2</button>
  
</body>

</html>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. 鼠标事件:

	(1). 问题: 旧鼠标进入和移出事件有问题。如果反复进出子元素,也会冒泡触发父元素上的事件处理函数。与实际不符。
	(2). 解决: 今后,几乎都用mouseenter和mouseleave代替mouseover和mouseout
	(3). 优点: 即使反复进出子元素,也不会触发父元素上的鼠标进入和移出事件。效果和现实相符。
	(4). 示例: 鼠标进入出d1,输出进入/移出d1
<!DOCTYPE HTML>
<html>

<head>
  <title>事件处理</title>
  <meta charset="utf-8" />
  <style>
    #d1 #d2 #d3 {
      cursor: pointer
    }

    #d1 {
      background-color: green;
      position: relative;
      width: 150px;
      height: 150px;
      text-align: center;
      cursor: pointer;
    }

    #d2 {
      background-color: blue;
      position: absolute;
      top: 25px;
      left: 25px;
      width: 100px;
      height: 100px;
    }

    #d3 {
      background-color: red;
      position: absolute;
      top: 25px;
      left: 25px;
      width: 50px;
      height: 50px;
      line-height: 50px;
    }
  </style>
</head>

<body>
  <div id="d1">
    <div id="d2">
      <div id="d3">
      </div>
    </div>
  </div>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //当鼠标进入d1时,输出进入d1
    $("#d1")
    // .mouseover(function(){
    .mouseenter(function(){
      console.log(`进入d1`)
    })
    //当鼠标移出d1时,输出移出d1
    // .mouseout(function(){
    .mouseleave(function(){
      console.log(`移出d1`)
    })
  </script>
</body>

</html>
	(5). 简写: 经常需要鼠标进入元素,变样,鼠标离开元素,恢复。所以,今后只要既绑定mouseenter,又绑定mouseleave时,就可以简写为
	a. .hover: 绑定一个.hover,等效于同时绑定mouseenter和mouseleave。但是因为毕竟mouseenter时和mouseleave时执行的操作不同!所以,.hover要求,必须提供两个事件处理函数
		$元素.hover( //mouseenter+mouseleave
			function(){ ... }, //给mouseenter
			function(){ ... } //给mouseleave
		)
	b. 特殊: 如果你有本事将两个function,改为完全相同的function。则只需要写一个function即可!
	  强调: 当只写一个function时,也是既给mouseenter,又给mouseleave
	(6). 示例: 鼠标进入时元素高亮显示,鼠标移出恢复原样
<!DOCTYPE html>
<html>
 <head>
  <title> new document </title>
  <meta charset="utf-8">
  <style>
    #target {
      border: 1px solid #eee;
      border-radius: 6px;
      padding: 10px;
      transition: all .5s linear;
    }
    /*自定义样式类*/
    #target.hover {
      border: 1px solid #aaa;
      box-shadow: 0 0 6px #aaa;
      background-color:red;
      color:#fff;
    }
  </style>
 </head>
 <body>
  <h1>使用hover(fn,fn)</h1>

  <h3>鼠标悬停在div上方,则突出显示;移出则取消突出显示</h3>
  <div id="target">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eligendi neque quae voluptatum ducimus culpa itaque maxime distinctio soluta cum cupiditate esse tenetur deserunt fuga perferendis sed veritatis asperiores. Numquam officia.</p>
  </div>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //DOM4步
    //1. 查找触发事件的元素
    $("#target")
    .hover(
      function(){
        $(this).toggleClass("hover")
      }
    )
    // .hover(
    //  function(){
    //    // $(this).addClass("hover")
    //    $(this).toggleClass("hover");
    //  },
    //  function(){
    //    // $(this).removeClass("hover")
    //    $(this).toggleClass("hover");
    //  }
    // )
    // //2. 绑定事件处理函数
    // .mouseenter(function(){
    //  //3. 查找要修改的元素
    //  $(this)
    //  //4. 修改元素
    //  .addClass("hover")
    // })
    // .mouseleave(function(){
    //  $(this).removeClass("hover");
    // })
  </script>
 </body>
</html>
运行结果: 

在这里插入图片描述
在这里插入图片描述

5. 模拟触发:

	(1). 什么是: 即使没有点击到按钮,也能触发按钮上的单击事件处理函数
	(2). 如何: 
	a. 标准: $按钮.trigger("事件名")
                  触发
		比如: $btn.trigger("click")
			模拟触发btn按钮上的单击事件处理函数
	b. 简写: 如果要触发的事件属于常用事件列表中
		$按钮.事件名()
		比如: $btn.click()
	(3). 示例: 在文本框中输入内容或按回车,或点击按钮都可还行搜索操作
<!DOCTYPE html>
<html>

<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <style>
  </style>
</head>

<body>
  <input type="text"><button>百度一下</button>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //当单击按钮时
    $("button").click(function(){
      //先获得文本款中现在的值
      var val=$(":text").val();
      //如果文本框中的内容去掉前后多余的空格后,不是空字符串,说明用户却是输入了有用的关键词
      //复习js高级第二天
      if(val.trim()!==""){
        //执行搜索操作
        console.log(`搜索 ${val} 相关的内容...`)
      }
    })
    //想实现在文本框中一边输入,一边搜索
    //当在文本款中输入了内容时
    $(":text")
    .on("input",function(){
      //模拟触发按钮的单击事件,执行查找操作
      // $("button").trigger("click");
      $("button").click();
    })
    //在文本框上按下回车时,也能执行搜索
    // .keydown(function(e){
    //在文本框按下回车再抬起时,才执行搜索
    .keyup(function(e){
      //只有当用户按的是13号键时,才执行搜索操作
      if(e.keyCode==13){
        //模拟触发按钮的单击事件,执行查找操作
        // $("button").trigger("click");
        $("button").click();
      }
    })
  </script>
</body>

</html>
运行结果: 

在这里插入图片描述

总结: $()共有4种:

  1. $(“选择器”) 查找DOM元素,并包装进jQuery对象中
  2. $(DOM元素对象) 不用查找,直接将DOM元素包装进jQuery对象中
  3. $(HTML片段) 创建新元素
  4. $(function(){ … }) 绑定DOMContentLoaded事件处理函数,在DOM内容加载后就自动提前执行!

九. 动画: 2种:

1. 简单动画: 固定的三种动画效果

	(1). 显示隐藏: 
	a. $元素.show(ms数)   显示元素
	b. $元素.hide(ms数)   隐藏元素
	c. $元素.toggle(ms数)  在显示和隐藏之间来回切换
	d. 问题: show() hide() toggle(),没有传参时,默认情况下,相当于display:none,瞬间显示隐藏。没有动画效果
	e. 解决: 只要在三个函数中,加入动画持续时间ms数,作为实参值,则三个函数就变成带动画效果了。
	(2). 上滑下滑: 
	$元素.slideUp()  $元素.slideDown()   $元素.slideToggle()
	说明: 就是不带ms数参数,也自带动画效果
	(3). 淡入淡出: 
	$元素.fadeIn()   $元素.fadeOut()     $元素.fadeToggle()
	说明: 就是不带ms数参数,也自带动画效果
	(4). 致命问题: 
	a. 因为我们可以在f12->elements中看到动画的变化过程,说明这些函数底层都是js程序+定时器——效率远不如css
	b. 效果不好看,而且因为底层是用js写的,所以几乎找不到,且不便于维护。
	(5). 示例: 测试简单动画函数: 
<!DOCTYPE html>
<html>
 <head>
  <title> new document </title>
  <meta charset="utf-8">
  <style>
    *{margin:0; padding:0;}
    #target{
      border-radius:10px;
      background:#eee;
    }
    .fade{/*动画起始状态*/
      height:104px; width:970px; opacity:1;
      padding: 10px; overflow:hidden;
      border: 1px solid #aaa; 

    }
    .out{/*动画结束状态*/
      
    }
  </style>
 </head>
 <body>
  <h1>jQuery动画函数——显示隐藏动画</h1>
  <button id="btn1">显示/隐藏div</button>
  <div id="target">
    <p><span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore debitis animi sint iste sequi sunt ad excepturi error labore molestiae est expedita eos nisi placeat provident dolorem quos facilis! Sapiente!</span><span>Accusamus neque id reprehenderit! Voluptatem in deleniti laboriosam commodi facere magnam impedit minima corrupti distinctio culpa amet optio natus esse. Inventore incidunt ab id perspiciatis atque minus magnam tempore harum.</span></p>
  </div>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    $("#btn1").click(function(){
      var $tar=$("#target");
      //如果现在是显示的,就隐藏
      //复习昨天的is()和jq新增选择器
      // if($tar.is(":visible")){
      //  $tar.hide(2000);
      // }else{//否则就显示
      //  $tar.show(2000);
      // }
      // $tar.toggle(2000);//切换显示隐藏
      // $tar.slideToggle();//切换上滑下滑
      $tar.fadeToggle();//切换淡入淡出
    });
  </script>
 </body>
</html>

在这里插入图片描述

	(6). 其实: .show()  .hide()   .toggle()在不加实参值时,还是可以代替并简化display:none或display:block的!所以,在jq中,显示元素就应该用.show(),隐藏元素就应该用.hide()。如果实在显示和隐藏之间来回切换,就可用.toggle()
	(7). 示例: 部分显示和隐藏品牌
<!DOCTYPE html>
<html>

<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <style>
    body {
      text-align: center;
    }

    ul {
      list-style: none;
    }

    li {
      margin: 0;
      padding: 0;
      display: inline-block;
      width: 30%;
    }
  </style>
</head>

<body>
  <ul id="list">
    <li>尼康(234)</li>
    <li>佳能(22)</li>
    <li>索尼(932)</li>
    <li>宾得(11)</li>
    <li>爱国者(3234)</li>
    <li>欧巴(32)</li>
    <li>海鸥(2334)</li>
    <li>卡西欧(334)</li>
    <li>三星(834)</li>
    <li>松下(234)</li>
    <li>其它品牌(2343)</li>
  </ul>

  <button data-toggle="brandlist">精简显示品牌</button>

  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //DOM 4步
    //1. 查找触发事件的元素
    //本例中: 查找按钮
    $("button")
    //2. 绑定事件处理函数
    .click(function(){
      //3. 查找要修改的元素
      //本例中: 要切换显示隐藏的li是>4位置且不是最后一个元素的所有li
      $("ul>li:gt(4):not(:last)")
      //4. 修改元素
      .toggle();
      //3. 查找要修改的元素: 就是当前按钮自己
      var $this=$(this)
      //4. 修改元素
      //如果当前按钮的内容是精简显示品牌
      if($this.html()==="精简显示品牌"){
        //就将按钮的内容改为显示所有品牌
        $this.html("显示所有品牌")
      }else{//否则
        //就将按钮的内容改为精简显示品牌
        $this.html("精简显示品牌")
      }
    })
  </script>
</body>

</html>
运行结果: 

2. 万能动画: 可以对多种css属性应用动画效果

	(1). $元素.animate({
		  css属性:"目标值"
           ... : ...
	    }, 动画持续时间ms数)
	(2). 原理: 
	a. animate()先获得当前元素指定css属性的当前值
	b. 用{}中给的目标值-当前值,自动求出差。
	c. 根据差值,自动规划动画的变化过程
	d. 按照动画持续时间的要求,在规定时间内,让元素均匀变化到目标位置。
	(3). 支持哪些属性: 
	a. 支持一切单个数值的属性
	  比如: width/height、left/bottom/top/right、margin/padding、fontSize、lineHeight、borderRadius ... ...
	b. 不支持: 颜色变化,CSS3变换(transform)
	c. 不如: css的transition,transition支持颜色也支持CSS3变化!
	(4). 问题: 底层也是用js程序+定时器实现的,效率远不如css。且animate()也是异步的!
	(5). 示例: 测试animate()都支持哪些CSS属性
<!DOCTYPE html>
<html>
 <head>
  <title> new document </title>
  <meta charset="utf-8">
  <style>
    #d1{
      border:1px solid #aaa;
      border-radius:6px;
      background:#eee;
      width:50px; height:50px;
      position:absolute; top:120px; left:0;
    }
  </style>
 </head>
 <body>
  <h1>animate</h1>
  <button id="btn1">启动动画</button>
  <div id="d1">abcd</div>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //当单击按钮时
    $("#btn1").click(function(){
      //让d1的left属性值,在3s内,均匀变化到300px的位置
      $("#d1").animate({
        //left:300,//top/bottom/right
        // width:300, //height
        padding:50, //margin

        // backgroundColor:"red" //不支持
        // transform:"rotate(90deg)" //不支持
      },3000)
    })
  </script>
 </body>
</html>
运行结果: 
	(6). 排队和并发: 
	a. 并发: 
		1). 多个css属性同时改变
		2). 一个animate({})中的多个css属性并发变化
	b. 排队: 
		1). 多个css属性按顺序依次变化
		2). 对一个元素先后调用多个animate(),则多个animate()中的css属性是排队变化的
		3). 原理: 
		a. jq中每个元素都有一个自己的动画队列
		b. 其实我们调用animate()和其它动画函数时,并不是立刻执行动画,而是将动画加入队列中等待的意思
		c. 如果队列中之前没有正在播放的动画,则新加入的动画才能立刻执行
		d. 如果队列中之前有正在播放的动画,则新加入的动画,必须等待队列中之前所有动画都执行完,才能执行。
	(7). 停止动画: 
	a. $元素.stop()
	b. 问题: .stop()只能停止当前正在播放的一个动画。如果队列中还有后续等待的动画,则后续动画依然继续执行。
	c. 解决: $元素stop(true)  既停止当前动画,又清空队列
	(8). jq新增选择器:  :animated 专门用来判断或匹配正在播放动画的元素。
	(9). 在动画播放完成后自动执行: 
	a. 错误: 将代码直接放在.animate()之后。
	b. 原因: 因为animate()底层是定时器,是异步的,主程序不会等异步函数指望完,就已经提前执行了!
	c. 解决: 今后,只要希望在动画结束后自动执行一项任务时,都要为animate()添加第三个回调函数参数!凡是放在第三个回调函数参数中的代码,注定只有在动画播放结束后,才会被自动调用执行
	d. 如何: 
		$元素.animate(
			{
				css属性:目标值, 
				  ... : ...
			},
			动画持续时间ms数,
			function(){
				//只会在动画播放结束后,自动调用执行
			}
		)
	(10). 示例: 实现四个小星星不同的动画效果
<!DOCTYPE html>
<html>

<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <style>
    img {
      position: relative;
    }
  </style>
</head>

<body>
  <img id="s1" src="img/star.png"><br />
  <img id="s2" src="img/star.png"><br />
  <img id="s3" src="img/star.png"><br />
  <img id="s4" src="img/star.png"><br />

  <script src="js/jquery-1.11.3.js"></script>
  <script>
    /*
    s1在屏幕左上角的小星星, 点击后从左移动到屏幕右边
    s2在屏幕左上角的小星星,点击后从左移动到屏幕右边,再移动到下边——走直角
    s3在屏幕左上角的小星星,点击后从左上角移动到屏幕右下边,走斜线
    s4点击小星星,变大、变淡....  直至消失
  */
    $("#s1").click(function(){
      var $this=$(this);
      //如果正在移动
      if($this.is(":animated")){
        $this.stop();
      }else{//否则
        $this.animate({
          left:300
        },3000);  
      }    
    })
    $("#s2").click(function(){
      var $this=$(this);
      //如果正在移动
      if($this.is(":animated")){
        $this.stop(true);
      }else{//否则
        $this.animate({
          left:300
        },2000)
        .animate({
          top:100
        },1000);
      }
    })
    $("#s3").click(function(){
      var $this=$(this);
      //如果正在移动
      if($this.is(":animated")){
        $this.stop();
      }else{//否则
        $this.animate({
          left:300,
          top:100
        },3000);
      }
    })
    $("#s4").click(function(){
      alert("疼!")
      var $this=$(this);
      $this.animate(
        { //异步
          width:192,
          height:192,
          opacity:0
        },
        3000,
        function(){
          //希望必须等动画播放完,才能执行.hide()
          $this.hide();//主程序 display:none
        }
      );
    })
  </script>
</body>

</html>
运行结果: 

在这里插入图片描述

十. 类数组对象操作:

1. 问题:  js中类数组对象非常受歧视。虽然长的像数组,但是不能使用数组家任何函数
2. 解决: jq中,模仿着数组家的函数,对类数组对象提供了一些常用的函数,来简化类数组对象操作。
3. 遍历: 
	(1). js中: 
	arr.forEach(function(当前元素值, 当前位置, 当前数组){
		//对当前元素值执行相同的操作
	})
	(2). jq中: 也可以遍历查找结果中每个DOM元素对象,然后,对每个DOM元素对象自动调用一次回调函数,执行相同的操作。
	$查找结果.each(function(当前位置, 当前DOM元素对象){
		//强调: each每次从查找结果对象中取出的都是一个DOM元素对象。如果希望对取出的DOM元素调用简化版函数,则必须$(DOM元素对象)包裹一下.
	})
	(3). 示例: 遍历ul下所有li,根据每个li内容不同,执行相同的操作。
	9_each.html
<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <style>
  </style>
</head>
<body>

<ul id="list">
  <li>98</li>
  <li>85</li>
  <li>33</li>
  <li>99</li>
  <li>52</li>
</ul>

<script src="js/jquery-1.11.3.js"></script>
<script>
  var arr=["亮亮","然然","东东"];
  arr.forEach(function(elem){
    console.log(`${elem} 到!`)
  })

  //请给每个不足60分的成绩+10分,并将超过90分的成绩用绿色背景标识出来
  var $lis=$("ul>li");
  console.log($lis);
  $lis.each(function(i,elem){
    console.log(elem);//li DOM元素对象
    //如果想对elem取出的li DOM元素对象调用简化版函数,比如
    var $elem=$(elem);
    //如果当前元素的内容>=90
    if($elem.html()>=90){
      //就设置当前元素的背景为绿色
      $elem.css("background-color","green")
    }else{//否则
      //先获得当前元素的内容
      var n=parseInt($elem.html())
      //如果当前元素的内容<60
      if(n<60){
        //就给当前元素的内容+10
        n+=10;
      }
      //再放回当前元素中
      $elem.html(n);
    }
  })
</script>
</body>
</html>

在这里插入图片描述

4. 查找: 
	(1). js中: 
	var i=arr.indexOf(要找的元素值)
	(2). jq中: 也可以查找一个DOM元素在整个查找结果中的下标位置
	var i=$查找结果.index(要找的DOM元素)
	(3). 示例: 5星评价: 

在这里插入图片描述

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <style>
    .score {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    .score li {
      display: inline-block;
      width: 50px;
      height: 50px;
      border: 1px solid #f00;
      border-radius: 50%;
      cursor: pointer;
    }
  </style>
</head>
<body>

<h3>请打分</h3>
<ul class="score">
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

<script src="js/jquery-1.11.3.js"></script>
<script>
  var arr=[1,2,3,4,5];
  //       0 1 2 3 4
  //想查找数字3在数组中的下标位置
  var i=arr.indexOf(3);
  console.log(i);//2

  //获得当前单击的li在所有li中的位置i,i及其执行的都变为红色,i之后的都变为白色
  //DOM 4步
  //1. 查找触发事件的元素
  //本例中: 因为所有li都可以点击,所以可以用事件委托优化,事件只绑定在父元素上一份即可
  $("ul.score")
  //2. 绑定事件处理函数
  .click(function(e){
    //用e.target代替this
    var $tar=$(e.target);
    //判断,只有$tar是li时,才执行事件处理函数
    //         元素选择器
    if($tar.is("li")){
      //3. 查找要修改的元素
      //4. 修改元素
      //先获得当前点击的li的下标位置i
      var i=$("ul>li").index($tar);
      // alert(i);
      //<i+1位置的所有元素,背景变为黄色
      $(`ul>li:lt(${i+1})`)
      .css("background-color","yellow")
      //>i位置的所有元素,背景变为白色
      $(`ul>li:gt(${i})`)
      .css("background-color","#fff")
    }
  })
</script>
</body>
</html>
运行结果:

在这里插入图片描述

十一. 添加自定义函数:

1. 何时: 如果在项目中,经常用到一个功能,但是,jq家有没有提供简化版函数,此时就可以添加一个自定义的函数
2. 问题: 保护容易添加了一个自定义函数,当然希望所有的jq家子对象都能使用
3. 解决: 应该将新添加的自定义函数保存进jquery的原型对象中: 
4. 如何: jQuery.prototype.自定义函数名=function(){
			//this->将来调用这个函数的.前的jq查找结果对象
			//因为this已经指向一个jq查找结果对象了,所以,如果this想调用jq家简化版函数,无需再$(this)
		}

在这里插入图片描述

5. 简写: jQuery.fn=jQuery.prototype
	所以: jQuery.fn.sum=function(){ ... }
6. 示例: 为jquery家添加自定义函数sum()可以计算所有找到的元素内容的和
<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <ul>
    <li>85</li>
    <li>91</li>
    <li>73</li>
    <li>59</li>
  </ul>
  <script src="js/jquery-1.11.3.js"></script>
  <script>
    //向jq原型对象中添加一个自定义函数sum
    // jQuery.prototype.sum=function(){
    jQuery.fn.sum=function(){
      //this->将来调用这个sum()函数的.前的jQuery查找结果对象
      //所有,如果this想调用jq家其它简化版函数,无需再$(this)包裹。
      console.log(`调用了一次自定义的sum()`)
      //对数组求和: 
      //先定义变量,准备累加值
      var result=0;
      //遍历数组中每个元素
      this.each(function(i,elem){
        //取出每个DOM元素的内容,转为整数,累加到result上
        //因为each是从jq查找结果对象中取出一个一个的DOM元素对象。所以elem可直接使用DOm家的属性或方法。
        result+=parseInt(elem.innerHTML);
      })
      return result;
    }

    //想对ul下所有li的内容求和
    console.log($("ul>li").sum());
  </script>
</body>
</html>
运行结果: 
调用了一次自定义的sum()
308

十二. 封装自定义插件:

1. 什么是插件/组件: 页面中一块可重用的独立的功能区域。
2. 为什么: 重用,提高开发效率,极其便于维护
3. 何时: 今后只要发现页面中有一块功能区域,可能被反复使用时,都要先封装为插件,再反复使用插件
4. 官方插件: 
	(1). 其实,jq官方提供了一套非常好用的插件库: jQuery UI
	(2). 下载: jqueryui.com
	(3). 引入项目: 
	a. 下载插件文件,保存到项目指定目录下: 

在这里插入图片描述

	b. 在网页中引入jquery ui插件: 
	<link rel="stylesheet" href="css/jquery-ui.css">
	<script src="js/jquery-1.11.3.js">
	<script src="js/jquery-ui.js">
	(4). 使用jquery ui中的某一个插件: 
	a. 在HTML中,按照插件的要求定义插件的HTML结构和内容
		1). 所有元素不用加任何class
		2). 最好在唯一父元素上加一个id,为了将来好查找
	b. 在自定义<script>脚本中,按id名查找到插件唯一父元素。调用jquery ui提供的插件对应的函数。
	c. 结果: 自动添加上了所有样式和交互行为,甚至包含动画效果。
	(5). 示例: 使用jquery ui快速实现手风琴效果
	12_widget_accordion.html
<!DOCTYPE html>
<html>

<head>
  <title> new document </title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="css/jquery-ui.css">
  <script src="js/jquery-1.11.3.js"></script>
  <script src="js/jquery-ui.js"></script>
</head>

<body>
  <h1>jQueryUI:Widgets —— Accordion</h1>
  <div id="my-accordion">
    <div>《西游记》简介</div>
    <div>一个和尚和四个动物的故事: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Similique nulla
      voluptas velit minus esse voluptatem illum quis magni nihil sint facilis cupiditate nobis quia ab neque. Modi
      veniam omnis nisi? </div>
    <div>《水浒传》简介</div>
    <div>105个男人和三个女人的故事: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Omnis provident
      sapiente aperiam reprehenderit repellat rem magnam vel odio quia harum hic impedit dolorem similique ea est
      consequatur adipisci at nemo!</div>
    <div>《红楼梦》简介</div>
    <div>一个男人和一群女人的故事: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus minima
      quidem aspernatur eligendi optio cupiditate minus nam expedita? Aliquid veritatis doloribus maxime vel dicta illo
      unde iusto qui quasi doloremque.</div>
  </div>
  <script>
    $("#my-accordion").accordion();
  </script>
</body>

</html>
运行结果: 

在这里插入图片描述

	(6). 原理: 
	a. jquery-ui提供了一批专门的插件函数: 
	比如: accordion()
	b. 当找到插件唯一的父元素时,对父元素调用插件函数,会自动做两件事: 
		1). 自动添加样式:以自动为元素添加class来实现的
		2). 自动添加了事件绑定
	(7). 问题: 
	a. 只有pc端,没有移动端,不支持响应式
	b. 所有class都自动生成,程序员一无所知,极其不便于项目的维护
	(8). 但是,如果只是自己封装一个插件,给自己用时,这种自动化的方式还是很可取的!
5. 封装自定义插件: 
	(0). 前提: 封装插件不是从0开始实现一个功能。而是,这个插件的功能已经在网页上实现了!封装,其实只是将插件的CSS和JS提取出来便于反复使用的过程。
	(1). 提取css: 将插件相关的css,剪切出来,保存到一个独立的css文件中
	(2). 为jquery家添加自定义插件函数:
	jQuery.prototype.插件函数=function(){
		//因为将来这个插件函数是
		//$插件父元素.插件函数()调用的

		//所以插件函数中的this->.前的$插件父元素,无需再$()包裹
		//2件事:
		//a. 自动为元素添加css
		//b. 自动绑定事件处理函数(可直接复制网页中已经实现的事件处理函数)
	}
6. 使用自定义插件: 用法同使用jqueryui完全一行: 
	(1). 在网页中引入: 自定义插件的css、jquery.js、自定义插件的js
	(2). 在网页中按插件规定,编写HTML结构和内容(不用写任何class)
	(3). 在网页结尾,自定义<script>中查找插件的唯一父元素,调用自定义插件函数。
7. 示例: 封装自定义手风琴插件: 

css

.accordion{width:80%; margin:0 auto;}
.accordion>.title{
  background:#eee; border:1px soild #aaa;
  padding:6px; font-size:1.5em; 
  font-weight:bold; cursor:pointer;
}
.accordion>.content{
  border-left:1px solid #eee;
  border-right:1px solid #eee;
}
.accordion>:last-child{
  border-bottom:1px solid #eee;
}
.fade{
  height:0;
  opacity:0;
  overflow:hidden;
  transition:all .5s linear;
}
.in{
  height:84px;
  opacity:1;
}

js
在这里插入图片描述

jQuery.prototype.myAccordion=function(){
  //2件事: 
  //1. 自动添加样式(class)
  //1.1 为当前父元素添加class accordion
  //因为将来是先找到插件的父元素,再用父元素调用插件函数
  //比如:$("#my-accordion").myAccordion()
  //所以, this指向.前的父元素,且已经是$()jq对象了。不用自己再$()包裹了
  this.addClass("accordion")
  //return $当前父元素
  //1.2 为父元素下所有子元素中奇数位置的元素添加class title
  .children(":nth-child(2n+1)")
  .addClass("title")
  //return $所有奇数位置的元素
  //1.3 为所有奇数位置的元素的下一个兄弟元素(偶数位置的元素)加class content fade
  .next()
  .addClass("content fade")
  //return $所有偶数位置的元素
  //1.4 为所有偶数位置的元素中第一个元素添加class in
  .first() //可获得查找结果中第一个元素,且返回的是jq子对象。而[0],返回的是DOM元素对象。
  .addClass("in");
  //2. 自动绑定事件处理函数
  $(".accordion")
  .on("click",".title",function(){
    $(this)
    .next(".content")
    .toggleClass("in")
    .siblings(".content")
    .removeClass("in")
  });
}

html

<!DOCTYPE html>
<html>
 <head>
  <title> new document </title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="dong-ui/dong.css">
  <script src="js/jquery-1.11.3.js"></script>
  <script src="dong-ui/dong.js"></script>
 </head>
 <body>
  <h1>使用“高度动画”实现“手风琴”组件</h1>
  <div id="my-accordion">
    <div>《西游记》简介</div>
    <div>一个和尚和四个动物的故事: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Similique nulla voluptas velit minus esse voluptatem illum quis magni nihil sint facilis cupiditate nobis quia ab neque. Modi veniam omnis nisi? </div>
    <div>《水浒传》简介</div>
    <div>105个男人和三个女人的故事: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Omnis provident sapiente aperiam reprehenderit repellat rem magnam vel odio quia harum hic impedit dolorem similique ea est consequatur adipisci at nemo!</div>
    <div>《红楼梦》简介</div>
    <div>一个男人和一群女人的故事: Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus minima quidem aspernatur eligendi optio cupiditate minus nam expedita? Aliquid veritatis doloribus maxime vel dicta illo unde iusto qui quasi doloremque.</div>
  </div>
  <script>
    //先找到插件的唯一父元素,再调用插件函数
    $("#my-accordion").myAccordion()
  </script>
 </body>
</html>
运行结果: 

在这里插入图片描述

十三. ajax

1. $.ajax({ //异步!
	url:"服务器端接口地址",
	type:"get或post", //默认是get
	data:{ 参数名:值, 参数名:值, ... : ... }
	dataType:"json", //$.ajax会自动调用JSON.parse()
	//回调函数,当请求响应成功结束时自动执行。
	//参数result会自动接住服务器端返回的响应结果(已经转为数组或对象的,可直接使用)
	success:function(result){
		//今后,所有希望在拿到响应结果后才执行的操作,都要放在success函数中!
	}
  })
2. 示例: 使用$.ajax,向新浪云服务器发送各种请求,获取响应结果: 
15_$_ajax.html

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="js/jquery-1.11.3.js"></script>
</head>
<body>
  <script>
    //想请求东哥新浪云服务器上的/index接口,获取首页6个商品信息
    $.ajax({
      url:"http://xzserver.applinzi.com/index",
      dataType:"json", //自动调用JSON.parse()
      success:function(result){
        console.log(result);
      }
    })
    //想从东哥新浪云服务器获取lid为5的商品的详细信息
    $.ajax({
      url:"http://xzserver.applinzi.com/details",
      data:{ lid:5 },
      dataType:"json",
      success:function(result){
        console.log(result);
      }
    })
    //想用东哥的新浪云服务器验证用户登录是否成功
    $.ajax({
      url:"http://xzserver.applinzi.com/users/signin",
      type:"post",
      data:{ uname:"dingding", upwd:"123456" },
      dataType:"json",
      success:function(result){
        console.log(result);
      }
    })
  </script>
</body>
</html>
运行结果: 

在这里插入图片描述

十六. 跨域

1. 什么是: 一个网站下的网页,使用了另一个网站中的资源(文件、数据)
2. 比如: 
	<link rel="stylesheet" href="别的网站的css">
	<script src="别的网站的js">
	<img src="别的网站的图片">
	... ...
	$.ajax({ url:"中央气象局的公共接口地址" })
3. 包括: 
	(1). 域名不同: 
	从http://www.a.com 向 http://www.b.com发送请求
	(2). 子级域名不同: 
	从http://oa.tedu.cn 向 http://hr.tedu.cn 发送请求
	(3). 端口号不同:
	从http://localhost:5500 向 http://localhost:3000 发送请求
	(4). 协议不同:
	从 http://12306.cn 向 https://12306.cn 发送请求
	(5). 即使本机内,域名向IP发送请求: 
	从 http://localhost:3000 向 http://127.0.0.1:3000 发送请求
4. 问题: 一个正常的接口,用ajax跨域请求,竟然报错!
5. 错误: 
	Access to XMLHttpRequest at 'http://localhost:3000/' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: 
从 源头 'http://127.0.0.1:5500''http://localhost:3000/'的xhr请求被CORS策略阻止了!
No 'Access-Control-Allow-Origin' header is present on the requested resource.
且,又没有在请求的资源上设置'Access-Control-Allow-Origin' 头信息。(所以,无法跨域访问)
6. 原因: 
	(1). 浏览器内部都有一个"同源策略(Cross Origin Resources Sharing)"。专门检查从服务器端响应回来的数据,来源地址是否和当前浏览器地址栏中网页所在的地址一致!
	(2). 如果浏览器检查,返回的数据的来源地址,与当前网页所在的地址不一致!就不允许使用响应回来的数据,就报跨域错误
	(3). 如果浏览器检查,返回的数据的来源地址,与当前网页所在的地址一致!才允许当前网页使用响应回来的数据。

在这里插入图片描述

7. 示例: 复现跨域错误: 
16_server.js
//不用会写!
//引入nodejs核心模块http,用来创建http服务器端程序
const http=require("http");
//创建服务器端程序,准备接受请求,返回响应
http.createServer((req,res)=>{
  var weather="北京 晴 11~-1";
  //解决中文乱码: 
  res.writeHead(200,{
    "Content-Type":"text/plain;charset=utf-8"
  })
  res.write(weather);//写入响应流
  res.end();//正式发送响应流
}).listen(3000)//监听3000端口
//运行: 
//1. 右键单击16_server.js,选择在集成终端/命令行中运行。
//2. 在打开的窗口中: node 16_server.js回车
//3. 打开浏览器,地址栏中: http://localhost:3000
//4. 结果: 看到北京天气,就对了
//常见错误: 
//Error: listen EADDRINUSE: address already in use :::3000
//说明开了两个服务器端程序,端口冲突!
//解决: 点击终端窗口右上角垃圾桶图标,直到点关闭位置。就关闭了所有的服务器端程序。再只打开一个。

_index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="js/jquery-1.11.3.js"></script>
</head>
<body>
  <h3>今日天气:<span id="s1" style="background-color:red; color:yellow"></span></h3>
  <script>
    $.ajax({
      url:"http://localhost:3000",
      success:function(result){
        $("#s1").html(result);
      }
    })
  </script>
</body>
</html>
运行结果: 

在这里插入图片描述

8. 解决: 
	(1). 纯服务器端解决: CORS方式跨域: 
	a. 其实就是让服务器端在返回结果之前,修改响应头中的"Access-Control-Allow-Origin"设置为客户端网页所在的地址

在这里插入图片描述

	b. 服务器端: 
	res.writeHead(200,{
		... : ... ,
		"Access-Control-Allow-Origin":"客户端网页所在的域名"
	})
	c. 原理: 设置"Access-Control-Allow-Origin"相当于修改响应结果的寄件人地址。如果寄件人地址和网页所在地址一致,则浏览器的同源策略就允许程序使用响应回来的结果
	d. 简写: 如果多个域名的客户端网页都想使用这个服务器端的接口,则可以将"Access-Control-Allow-Origin"设置为*。
		结果: 将来任何域名的客户端网页都可随意访问当前接口
	e. 优点: 只需要服务器端修改,客户端不需要做任何修改
	f. 缺点: 2个
		1). 要么只能写一个客户端地址
		2). 要么允许任意客户端访问接口——不安全
	g. 示例: 使用cors方式解决跨域问题: 
	

16_server.js

//不用会写!
//引入nodejs核心模块http,用来创建http服务器端程序
const http=require("http");
//创建服务器端程序,准备接受请求,返回响应
http.createServer((req,res)=>{
  var weather="北京 晴 11~-1";
  //解决中文乱码: 
  res.writeHead(200,{
    "Content-Type":"text/plain;charset=utf-8",
    // "Access-Control-Allow-Origin":"http://127.0.0.1:5500"
    "Access-Control-Allow-Origin":"*"
  })
  res.write(weather);//写入响应流
  res.end();//正式发送响应流
}).listen(3000)//监听3000端口
//运行: 
//1. 右键单击16_server.js,选择在集成终端/命令行中运行。
//2. 在打开的窗口中: node 16_server.js回车
//3. 打开浏览器,地址栏中: http://localhost:3000
//4. 结果: 看到北京天气,就对了
//常见错误: 
//Error: listen EADDRINUSE: address already in use :::3000
//说明开了两个服务器端程序,端口冲突!
//解决: 点击终端窗口右上角垃圾桶图标,直到点关闭位置。就关闭了所有的服务器端程序。再只打开一个。

16_index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="js/jquery-1.11.3.js"></script>
</head>
<body>
  <h3>今日天气:<span id="s1" style="background-color:red; color:yellow"></span></h3>
  <script>
    $.ajax({
      url:"http://localhost:3000",
      success:function(result){
        $("#s1").html(result);
      }
    })
  </script>
</body>
</html>
运行结果: 

在这里插入图片描述

	(2). 服务器端+客户端一起解决: 
	JSONP: JSON with padding  填充式json
	a. 基本思想: 浏览器的同源策略只防xhr的ajax请求。不防别的跨域(link, script, img)。如果我们可以
	请其他可以跨域的元素,帮我们发送请求,就可以躲过浏览器的同源策略
	b. 因为只有<script>元素和程序有关,且能发送请求,所以,请<script>代替ajax发送请求.
	c. <script>有一个要求: script只能接受一条js语句,不能会直接接受一个数据!
	d. 解决: 
		1). 后端: 不能只返回一个数据。应该将数组拼接在一条语法正确的js语句中返回:
		比如: weather="北京 晴 11~-1"

			res.write(`document.write('${weather}')`)

		结果: `document.write('北京 晴 11~-1')`
		2). 前端: 
		i. 不要用任何ajax
		ii. 只能用<script src="接口地址">发送请求

在这里插入图片描述

	c. 问题: 服务器端将要执行的语句写死了!客户端众口难调。
	d. 解决: 
		1). 服务端: 不要写死操作的语句,只写一个函数调用语句
		比如: weather="北京 晴 11~-1"
			res.write(`fun('${weather}')`)

		结果: `fun('北京 晴 11~-1')` //调用函数的语句
		2). 客户端: 提前定义一个同名的函数等着!
		<script>
			function fun(data){
				//对data执行操作
			}
		</script>
		<script src="服务器端接口地址">

在这里插入图片描述

	e. 优点: 与客户端域名和IP地址无关,不需要知道客户端域名和IP地址
	f. 缺点: 客户端和服务器端都要改,太麻烦了!
	g. 示例: 使用JSONP方式解决跨域问题: 

17_server2.js

//不用会写!
//引入nodejs核心模块http,用来创建http服务器端程序
const http=require("http");
//创建服务器端程序,准备接受请求,返回响应
http.createServer((req,res)=>{
  var weather="北京 晴 11~-1";
  //解决中文乱码: 
  res.writeHead(200,{
    "Content-Type":"text/plain;charset=utf-8",
  })
  // res.write(`alert('${weather}')`);//写入响应流
  //其实返回的: alert('北京 晴 11~-1')
  res.write(`fun('${weather}')`);
  //其实返回的: fun('北京 晴 11~-1')
  res.end();//正式发送响应流
}).listen(3000)//监听3000端口
//运行: 
//1. 右键单击16_server.js,选择在集成终端/命令行中运行。
//2. 在打开的窗口中: node 16_server.js回车
//3. 打开浏览器,地址栏中: http://localhost:3000
//4. 结果: 看到北京天气,就对了
//常见错误: 
//Error: listen EADDRINUSE: address already in use :::3000
//说明开了两个服务器端程序,端口冲突!
//解决: 点击终端窗口右上角垃圾桶图标,直到点关闭位置。就关闭了所有的服务器端程序。再只打开一个。

17_index2.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="js/jquery-1.11.3.js"></script>
</head>
<body>
  <h3>今日天气:<span id="s1" style="background-color:red; color:yellow"></span></h3>
  <script>
    function fun(data){
      $("#s1").html(data);
    }
  </script>
  <script src="http://localhost:3000"></script>
</body>
</html>
运行结果:

在这里插入图片描述

9. 鄙视: 你们公司的项目,如何解决跨域问题?
   答: (既不用CORS,也不用JSONP,VUE讲...)
10. 要求: CORS和JSONP跨域可以不会写,但是,鄙视面试被问到原理,要能简单聊几句,或者会画图。

总结: $()共有4种:
1. $(“选择器”) 查找DOM元素,并包装进jQuery对象中
2. $(DOM元素对象) 不用查找,直接将DOM元素包装进jQuery对象中
3. $(HTML片段) 创建新元素
4. $(function(){ … }) 绑定DOMContentLoaded事件处理函数,在DOM内容加载后就自动提前执行!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值